From d31fba13b9f31f37835ddaa6476ff3b7a3cbd49b Mon Sep 17 00:00:00 2001 From: nik Date: Mon, 2 Aug 2010 16:51:59 +0400 Subject: [PATCH] IDEA-51729: Ability to include exploded JARs in artifacts --- .../ArchiveAntCopyInstructionCreator.java | 11 +- .../DirectoryAntCopyInstructionCreator.java | 20 ++- .../impl/packagingCompiler/JarsBuilder.java | 43 ++++++- .../impl/artifacts/ArtifactUtil.java | 5 +- .../impl/compiler/ArtifactCompilerUtil.java | 68 ++++++++++ .../compiler/ArtifactsCompilerInstance.java | 50 ++++++-- .../DirectoryCopyPackagingElement.java | 2 +- .../ExtractedDirectoryElementType.java | 80 ++++++++++++ .../ExtractedDirectoryPackagingElement.java | 116 ++++++++++++++++++ .../elements/FileCopyPackagingElement.java | 2 +- .../elements/PackagingElementFactoryImpl.java | 10 +- .../ui/ExtractedDirectoryPresentation.java | 65 ++++++++++ .../impl/ui/FileCopyPresentation.java | 7 +- .../compiler/ant/taskdefs/Include.java | 4 +- .../compiler/ant/taskdefs/PatternSet.java | 4 +- .../intellij/compiler/ant/taskdefs/Unzip.java | 27 ++++ .../compiler/ant/taskdefs/ZipFileSet.java | 13 ++ .../elements/AntCopyInstructionCreator.java | 9 +- .../elements/PackagingElementFactory.java | 4 + .../packaging/ui/PackagingElementWeights.java | 1 + platform/icons/src/nodes/copyOfFolder.png | Bin 727 -> 588 bytes platform/icons/src/nodes/extractedFolder.png | Bin 0 -> 657 bytes .../intellij/openapi/util/io/FileUtil.java | 2 +- 23 files changed, 498 insertions(+), 45 deletions(-) create mode 100644 java/compiler/impl/src/com/intellij/packaging/impl/compiler/ArtifactCompilerUtil.java create mode 100644 java/compiler/impl/src/com/intellij/packaging/impl/elements/ExtractedDirectoryElementType.java create mode 100644 java/compiler/impl/src/com/intellij/packaging/impl/elements/ExtractedDirectoryPackagingElement.java create mode 100644 java/compiler/impl/src/com/intellij/packaging/impl/ui/ExtractedDirectoryPresentation.java create mode 100644 java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Unzip.java create mode 100644 platform/icons/src/nodes/extractedFolder.png diff --git a/java/compiler/impl/src/com/intellij/compiler/ant/artifacts/ArchiveAntCopyInstructionCreator.java b/java/compiler/impl/src/com/intellij/compiler/ant/artifacts/ArchiveAntCopyInstructionCreator.java index 8343e9f86b52..1857676997c0 100644 --- a/java/compiler/impl/src/com/intellij/compiler/ant/artifacts/ArchiveAntCopyInstructionCreator.java +++ b/java/compiler/impl/src/com/intellij/compiler/ant/artifacts/ArchiveAntCopyInstructionCreator.java @@ -43,11 +43,18 @@ public class ArchiveAntCopyInstructionCreator implements AntCopyInstructionCreat } @NotNull - public AntCopyInstructionCreator subFolder(String directoryName) { + public AntCopyInstructionCreator subFolder(@NotNull String directoryName) { return new ArchiveAntCopyInstructionCreator(myPrefix + "/" + directoryName); } - public Generator createSubFolderCommand(String directoryName) { + public Generator createSubFolderCommand(@NotNull String directoryName) { return null; } + + @NotNull + @Override + public Generator createExtractedDirectoryInstruction(@NotNull String jarPath, @NotNull String pathInJar) { + final String pattern = pathInJar.length() == 0 ? null : pathInJar + "**"; + return ZipFileSet.createUnpackedSet(jarPath, pathInJar, true, pattern); + } } diff --git a/java/compiler/impl/src/com/intellij/compiler/ant/artifacts/DirectoryAntCopyInstructionCreator.java b/java/compiler/impl/src/com/intellij/compiler/ant/artifacts/DirectoryAntCopyInstructionCreator.java index ad9c41d49398..0d8d08c4a41a 100644 --- a/java/compiler/impl/src/com/intellij/compiler/ant/artifacts/DirectoryAntCopyInstructionCreator.java +++ b/java/compiler/impl/src/com/intellij/compiler/ant/artifacts/DirectoryAntCopyInstructionCreator.java @@ -17,9 +17,7 @@ package com.intellij.compiler.ant.artifacts; import com.intellij.compiler.ant.Generator; import com.intellij.compiler.ant.Tag; -import com.intellij.compiler.ant.taskdefs.Copy; -import com.intellij.compiler.ant.taskdefs.FileSet; -import com.intellij.compiler.ant.taskdefs.Mkdir; +import com.intellij.compiler.ant.taskdefs.*; import com.intellij.packaging.elements.AntCopyInstructionCreator; import org.jetbrains.annotations.NotNull; @@ -50,11 +48,23 @@ public class DirectoryAntCopyInstructionCreator implements AntCopyInstructionCre } @NotNull - public AntCopyInstructionCreator subFolder(String directoryName) { + public AntCopyInstructionCreator subFolder(@NotNull String directoryName) { return new DirectoryAntCopyInstructionCreator(myOutputDirectory + "/" + directoryName); } - public Generator createSubFolderCommand(String directoryName) { + public Generator createSubFolderCommand(@NotNull String directoryName) { return new Mkdir(myOutputDirectory + "/" + directoryName); } + + @NotNull + @Override + public Generator createExtractedDirectoryInstruction(@NotNull String jarPath, @NotNull String pathInJar) { + final Unzip unzip = new Unzip(jarPath, myOutputDirectory); + if (pathInJar.length() > 0) { + final PatternSet patterns = new PatternSet(null); + patterns.add(new Include(pathInJar + "**")); + unzip.add(patterns); + } + return unzip; + } } diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/packagingCompiler/JarsBuilder.java b/java/compiler/impl/src/com/intellij/compiler/impl/packagingCompiler/JarsBuilder.java index 7e1a218a04a1..10b387d762ec 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/packagingCompiler/JarsBuilder.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/packagingCompiler/JarsBuilder.java @@ -25,6 +25,7 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.packaging.impl.compiler.ArtifactCompilerUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.graph.CachingSemiGraph; import com.intellij.util.graph.DFSTBuilder; @@ -159,8 +160,14 @@ public class JarsBuilder { try { final THashSet writtenPaths = new THashSet(); for (Pair pair : jar.getPackedFiles()) { - File file = VfsUtil.virtualToIoFile(pair.getSecond()); - addFileToJar(jarOutputStream, file, pair.getFirst(), writtenPaths); + final VirtualFile sourceFile = pair.getSecond(); + if (sourceFile.isInLocalFileSystem()) { + File file = VfsUtil.virtualToIoFile(sourceFile); + addFileToJar(jarOutputStream, file, pair.getFirst(), writtenPaths); + } + else { + extractFileAndAddToJar(jarOutputStream, sourceFile, pair.getFirst(), writtenPaths); + } } for (Pair nestedJar : jar.getPackedJars()) { @@ -178,9 +185,35 @@ public class JarsBuilder { } } + private void extractFileAndAddToJar(JarOutputStream jarOutputStream, VirtualFile sourceFile, String relativePath, THashSet writtenPaths) + throws IOException { + relativePath = addParentDirectories(jarOutputStream, writtenPaths, relativePath); + myContext.getProgressIndicator().setText2(relativePath); + if (!writtenPaths.add(relativePath)) return; + + final BufferedInputStream input = ArtifactCompilerUtil.getJarEntryInputStream(sourceFile, myContext); + if (input == null) return; + + ZipEntry entry = new ZipEntry(relativePath); + entry.setTime(ArtifactCompilerUtil.getJarFile(sourceFile).lastModified()); + jarOutputStream.putNextEntry(entry); + FileUtil.copy(input, jarOutputStream); + jarOutputStream.closeEntry(); + } + private void addFileToJar(final @NotNull JarOutputStream jarOutputStream, final @NotNull File file, @NotNull String relativePath, final @NotNull THashSet writtenPaths) throws IOException { - //todo[nik] check file exists? + if (!file.exists()) { + return; + } + + relativePath = addParentDirectories(jarOutputStream, writtenPaths, relativePath); + myContext.getProgressIndicator().setText2(relativePath); + ZipUtil.addFileToZip(jarOutputStream, file, relativePath, writtenPaths, myFileFilter); + } + + private static String addParentDirectories(JarOutputStream jarOutputStream, THashSet writtenPaths, String relativePath) + throws IOException { while (relativePath.startsWith("/")) { relativePath = relativePath.substring(1); } @@ -193,9 +226,7 @@ public class JarsBuilder { } i = relativePath.indexOf('/', i + 1); } - - myContext.getProgressIndicator().setText2(relativePath); - ZipUtil.addFileToZip(jarOutputStream, file, relativePath, writtenPaths, myFileFilter); + return relativePath; } private static void addEntry(final ZipOutputStream output, @NonNls final String relativePath) throws IOException { diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java index 3d246a41c078..da39774c3698 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java @@ -320,6 +320,7 @@ public class ArtifactUtil { boolean processSubstitutions) { processPackagingElements(artifact, PackagingElementFactoryImpl.FILE_COPY_ELEMENT_TYPE, processor, context, processSubstitutions); processPackagingElements(artifact, PackagingElementFactoryImpl.DIRECTORY_COPY_ELEMENT_TYPE, processor, context, processSubstitutions); + processPackagingElements(artifact, PackagingElementFactoryImpl.EXTRACTED_DIRECTORY_ELEMENT_TYPE, processor, context, processSubstitutions); } public static Collection> findContainingArtifactsWithOutputPaths(@NotNull final VirtualFile file, @NotNull Project project) { @@ -417,8 +418,8 @@ public class ArtifactUtil { ContainerUtil.addIfNotNull(fileCopyElement.findFile(), result); } } - else if (element instanceof DirectoryCopyPackagingElement) { - final VirtualFile sourceRoot = ((DirectoryCopyPackagingElement)element).findFile(); + else if (element instanceof DirectoryCopyPackagingElement || element instanceof ExtractedDirectoryPackagingElement) { + final VirtualFile sourceRoot = ((FileOrDirectoryCopyPackagingElement)element).findFile(); if (sourceRoot != null) { ContainerUtil.addIfNotNull(sourceRoot.findFileByRelativePath(path), result); } diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/compiler/ArtifactCompilerUtil.java b/java/compiler/impl/src/com/intellij/packaging/impl/compiler/ArtifactCompilerUtil.java new file mode 100644 index 000000000000..f512c68e7a0b --- /dev/null +++ b/java/compiler/impl/src/com/intellij/packaging/impl/compiler/ArtifactCompilerUtil.java @@ -0,0 +1,68 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.packaging.impl.compiler; + +import com.intellij.openapi.compiler.CompileContext; +import com.intellij.openapi.compiler.CompilerMessageCategory; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.JarFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.Nullable; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.IOException; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +/** + * @author nik + */ +public class ArtifactCompilerUtil { + private static final Logger LOG = Logger.getInstance("#com.intellij.packaging.impl.compiler.ArtifactCompilerUtil"); + + private ArtifactCompilerUtil() { + } + + @Nullable + public static BufferedInputStream getJarEntryInputStream(VirtualFile sourceFile, final CompileContext context) throws IOException { + final String fullPath = sourceFile.getPath(); + final int jarEnd = fullPath.indexOf(JarFileSystem.JAR_SEPARATOR); + LOG.assertTrue(jarEnd != -1, fullPath); + String pathInJar = fullPath.substring(jarEnd + JarFileSystem.JAR_SEPARATOR.length()); + String jarPath = fullPath.substring(0, jarEnd); + final ZipFile jarFile = new ZipFile(new File(FileUtil.toSystemDependentName(jarPath))); + final ZipEntry entry = jarFile.getEntry(pathInJar); + if (entry == null) { + context.addMessage(CompilerMessageCategory.ERROR, "Cannot extract '" + pathInJar + "' from '" + jarFile.getName() + "': entry not found", null, -1, -1); + return null; + } + + return new BufferedInputStream(jarFile.getInputStream(entry)) { + @Override + public void close() throws IOException { + super.close(); + jarFile.close(); + } + }; + } + + public static File getJarFile(VirtualFile jarEntry) { + String fullPath = jarEntry.getPath(); + return new File(FileUtil.toSystemDependentName(fullPath.substring(fullPath.indexOf(JarFileSystem.JAR_SEPARATOR)))); + } +} diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/compiler/ArtifactsCompilerInstance.java b/java/compiler/impl/src/com/intellij/packaging/impl/compiler/ArtifactsCompilerInstance.java index f2746de16b45..46c1ed0bab25 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/compiler/ArtifactsCompilerInstance.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/compiler/ArtifactsCompilerInstance.java @@ -31,7 +31,7 @@ import com.intellij.openapi.deployment.DeploymentUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; -import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.SystemInfo; @@ -53,9 +53,7 @@ import com.intellij.util.text.CaseInsensitiveStringHashingStrategy; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; -import java.io.File; -import java.io.FileFilter; -import java.io.IOException; +import java.io.*; import java.util.*; /** @@ -164,7 +162,7 @@ public class ArtifactsCompilerInstance extends CompilerInstance> changedItems, final Set processedItems, - final Set writtenPaths, final Set deletedJars) { + final @NotNull Set writtenPaths, final Set deletedJars) { final boolean testMode = ApplicationManager.getApplication().isUnitTestMode(); final DeploymentUtil deploymentUtil = DeploymentUtil.getInstance(); @@ -188,20 +186,26 @@ public class ArtifactsCompilerInstance extends CompilerInstance exception = Ref.create(null); new ReadAction() { protected void run(final Result result) { - final File fromFile = VfsUtil.virtualToIoFile(sourceItem.getFile()); + final VirtualFile sourceFile = sourceItem.getFile(); for (DestinationInfo destination : sourceItem.getDestinations()) { if (destination instanceof ExplodedDestinationInfo) { final ExplodedDestinationInfo explodedDestination = (ExplodedDestinationInfo)destination; File toFile = new File(FileUtil.toSystemDependentName(explodedDestination.getOutputPath())); - if (fromFile.exists()) { - try { - deploymentUtil.copyFile(fromFile, toFile, myContext, writtenPaths, fileFilter); + try { + if (sourceFile.isInLocalFileSystem()) { + final File ioFromFile = VfsUtil.virtualToIoFile(sourceFile); + if (ioFromFile.exists()) { + deploymentUtil.copyFile(ioFromFile, toFile, myContext, writtenPaths, fileFilter); + } } - catch (IOException e) { - exception.set(e); - return; + else { + extractFile(sourceFile, toFile, writtenPaths, fileFilter); } } + catch (IOException e) { + exception.set(e); + return; + } } else { changedJars.add(((JarDestinationInfo)destination).getJarInfo()); @@ -254,6 +258,28 @@ public class ArtifactsCompilerInstance extends CompilerInstance writtenPaths, FileFilter fileFilter) throws IOException { + if (!writtenPaths.add(toFile.getPath())) { + return; + } + + if (!FileUtil.createParentDirs(toFile)) { + myContext.addMessage(CompilerMessageCategory.ERROR, "Cannot create directory for '" + toFile.getAbsolutePath() + "' file", null, -1, -1); + return; + } + + final BufferedInputStream input = ArtifactCompilerUtil.getJarEntryInputStream(sourceFile, myContext); + if (input == null) return; + final BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(toFile)); + try { + FileUtil.copy(input, output); + } + finally { + input.close(); + output.close(); + } + } + private void onBuildStartedOrFinished(final boolean finished) throws Exception { final Set artifacts = myContext.getUserData(ArtifactsCompiler.AFFECTED_ARTIFACTS); if (artifacts != null) { diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/DirectoryCopyPackagingElement.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/DirectoryCopyPackagingElement.java index 3721180f6a32..77ad2d567313 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/elements/DirectoryCopyPackagingElement.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/DirectoryCopyPackagingElement.java @@ -51,7 +51,7 @@ public class DirectoryCopyPackagingElement extends FileOrDirectoryCopyPackagingE @NotNull ArtifactAntGenerationContext generationContext, @NotNull ArtifactType artifactType) { final String path = generationContext.getSubstitutedPath(myFilePath); - return Collections.singletonList((Generator)creator.createDirectoryContentCopyInstruction(path)); + return Collections.singletonList(creator.createDirectoryContentCopyInstruction(path)); } @Override diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ExtractedDirectoryElementType.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ExtractedDirectoryElementType.java new file mode 100644 index 000000000000..34be7a6e00bf --- /dev/null +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ExtractedDirectoryElementType.java @@ -0,0 +1,80 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.packaging.impl.elements; + +import com.intellij.openapi.fileChooser.FileChooserDescriptor; +import com.intellij.openapi.fileChooser.FileChooserDialog; +import com.intellij.openapi.fileChooser.FileChooserFactory; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.vfs.JarFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.packaging.artifacts.Artifact; +import com.intellij.packaging.elements.CompositePackagingElement; +import com.intellij.packaging.elements.PackagingElementType; +import com.intellij.packaging.ui.ArtifactEditorContext; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.util.ArrayList; +import java.util.List; + +/** +* @author nik +*/ +public class ExtractedDirectoryElementType extends PackagingElementType { + public static final Icon EXTRACTED_FOLDER_ICON = IconLoader.getIcon("/nodes/extractedFolder.png"); + + ExtractedDirectoryElementType() { + super("extracted-dir", "Extracted Directory"); + } + + @Override + public Icon getCreateElementIcon() { + return EXTRACTED_FOLDER_ICON; + } + + @Override + public boolean canCreate(@NotNull ArtifactEditorContext context, @NotNull Artifact artifact) { + return true; + } + + @NotNull + public List chooseAndCreate(@NotNull ArtifactEditorContext context, @NotNull Artifact artifact, + @NotNull CompositePackagingElement parent) { + final FileChooserDescriptor descriptor = new FileChooserDescriptor(false, true, true, false, true, true) { + @Override + public boolean isFileSelectable(VirtualFile file) { + if (file.isInLocalFileSystem() && file.isDirectory()) return false; + return super.isFileSelectable(file); + } + }; + final FileChooserDialog chooser = FileChooserFactory.getInstance().createFileChooser(descriptor, context.getProject()); + final VirtualFile[] files = chooser.choose(null, context.getProject()); + final List list = new ArrayList(); + for (VirtualFile file : files) { + final String fullPath = file.getPath(); + final int jarEnd = fullPath.indexOf(JarFileSystem.JAR_SEPARATOR); + list.add(new ExtractedDirectoryPackagingElement(fullPath.substring(0, jarEnd), fullPath.substring(jarEnd + 1))); + } + return list; + } + + @NotNull + public ExtractedDirectoryPackagingElement createEmpty(@NotNull Project project) { + return new ExtractedDirectoryPackagingElement(); + } +} diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ExtractedDirectoryPackagingElement.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ExtractedDirectoryPackagingElement.java new file mode 100644 index 000000000000..32ccc9396a19 --- /dev/null +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ExtractedDirectoryPackagingElement.java @@ -0,0 +1,116 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.packaging.impl.elements; + +import com.intellij.compiler.ant.Generator; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.JarFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.packaging.artifacts.ArtifactType; +import com.intellij.packaging.elements.*; +import com.intellij.packaging.impl.ui.ExtractedDirectoryPresentation; +import com.intellij.packaging.ui.ArtifactEditorContext; +import com.intellij.packaging.ui.PackagingElementPresentation; +import com.intellij.util.xmlb.annotations.Attribute; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +/** + * @author nik + */ +public class ExtractedDirectoryPackagingElement extends FileOrDirectoryCopyPackagingElement { + private String myPathInJar; + + public ExtractedDirectoryPackagingElement() { + super(PackagingElementFactoryImpl.EXTRACTED_DIRECTORY_ELEMENT_TYPE); + } + + public ExtractedDirectoryPackagingElement(String jarPath, String pathInJar) { + super(PackagingElementFactoryImpl.EXTRACTED_DIRECTORY_ELEMENT_TYPE, jarPath); + myPathInJar = pathInJar; + if (!StringUtil.startsWithChar(myPathInJar, '/')) { + myPathInJar = "/" + myPathInJar; + } + if (!StringUtil.endsWithChar(myPathInJar, '/')) { + myPathInJar += "/"; + } + } + + @Override + public PackagingElementPresentation createPresentation(@NotNull ArtifactEditorContext context) { + return new ExtractedDirectoryPresentation(this); + } + + @Override + public VirtualFile findFile() { + final VirtualFile jarFile = super.findFile(); + if (jarFile == null) return null; + + final VirtualFile jarRoot = JarFileSystem.getInstance().getJarRootForLocalFile(jarFile); + if ("/".equals(myPathInJar)) return jarRoot; + return jarRoot != null ? jarRoot.findFileByRelativePath(myPathInJar) : null; + } + + @Override + public List computeAntInstructions(@NotNull PackagingElementResolvingContext resolvingContext, + @NotNull AntCopyInstructionCreator creator, + @NotNull ArtifactAntGenerationContext generationContext, + @NotNull ArtifactType artifactType) { + final String jarPath = generationContext.getSubstitutedPath(myFilePath); + return Collections.singletonList(creator.createExtractedDirectoryInstruction(jarPath, StringUtil.trimStart(myPathInJar, "/"))); + } + + + @Override + public void computeIncrementalCompilerInstructions(@NotNull IncrementalCompilerInstructionCreator creator, + @NotNull PackagingElementResolvingContext resolvingContext, + @NotNull ArtifactIncrementalCompilerContext compilerContext, + @NotNull ArtifactType artifactType) { + final VirtualFile file = findFile(); + if (file != null && file.isValid() && file.isDirectory()) { + creator.addDirectoryCopyInstructions(file); + } + } + + @Override + public boolean isEqualTo(@NotNull PackagingElement element) { + return element instanceof ExtractedDirectoryPackagingElement && super.isEqualTo(element) + && Comparing.equal(myPathInJar, ((ExtractedDirectoryPackagingElement)element).getPathInJar()); + } + + @Override + public ExtractedDirectoryPackagingElement getState() { + return this; + } + + @Override + public void loadState(ExtractedDirectoryPackagingElement state) { + myFilePath = state.getFilePath(); + myPathInJar = state.getPathInJar(); + } + + @Attribute("path-in-jar") + public String getPathInJar() { + return myPathInJar; + } + + public void setPathInJar(String pathInJar) { + myPathInJar = pathInJar; + } +} diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/FileCopyPackagingElement.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/FileCopyPackagingElement.java index 8835d077beec..6513c765e76e 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/elements/FileCopyPackagingElement.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/FileCopyPackagingElement.java @@ -58,7 +58,7 @@ public class FileCopyPackagingElement extends FileOrDirectoryCopyPackagingElemen } public PackagingElementPresentation createPresentation(@NotNull ArtifactEditorContext context) { - return new FileCopyPresentation(myFilePath, getOutputFileName(), context); + return new FileCopyPresentation(myFilePath, getOutputFileName()); } @Override diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/PackagingElementFactoryImpl.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/PackagingElementFactoryImpl.java index 1d527a257ddc..be6c0b32993f 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/elements/PackagingElementFactoryImpl.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/PackagingElementFactoryImpl.java @@ -51,11 +51,12 @@ public class PackagingElementFactoryImpl extends PackagingElementFactory { public static final PackagingElementType ARCHIVE_ELEMENT_TYPE = new ArchiveElementType(); public static final PackagingElementType FILE_COPY_ELEMENT_TYPE = new FileCopyElementType(); public static final PackagingElementType DIRECTORY_COPY_ELEMENT_TYPE = new DirectoryCopyElementType(); + public static final PackagingElementType EXTRACTED_DIRECTORY_ELEMENT_TYPE = new ExtractedDirectoryElementType(); public static final PackagingElementType> ARTIFACT_ROOT_ELEMENT_TYPE = new ArtifactRootElementType(); private static final PackagingElementType[] STANDARD_TYPES = { DIRECTORY_ELEMENT_TYPE, ARCHIVE_ELEMENT_TYPE, LibraryElementType.LIBRARY_ELEMENT_TYPE, ModuleOutputElementType.MODULE_OUTPUT_ELEMENT_TYPE, - ArtifactElementType.ARTIFACT_ELEMENT_TYPE, FILE_COPY_ELEMENT_TYPE, DIRECTORY_COPY_ELEMENT_TYPE + ArtifactElementType.ARTIFACT_ELEMENT_TYPE, FILE_COPY_ELEMENT_TYPE, DIRECTORY_COPY_ELEMENT_TYPE, EXTRACTED_DIRECTORY_ELEMENT_TYPE }; @NotNull @@ -253,6 +254,13 @@ public class PackagingElementFactoryImpl extends PackagingElementFactory { return createParentDirectories(relativeOutputPath, new DirectoryCopyPackagingElement(filePath)); } + @Override + @NotNull + public PackagingElement createExtractedDirectoryWithParentDirectories(@NotNull String jarPath, @NotNull String pathInJar, + @NotNull String relativeOutputPath) { + return createParentDirectories(relativeOutputPath, new ExtractedDirectoryPackagingElement(jarPath, pathInJar)); + } + @NotNull @Override public PackagingElement createFileCopyWithParentDirectories(@NotNull String filePath, @NotNull String relativeOutputPath) { diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/ui/ExtractedDirectoryPresentation.java b/java/compiler/impl/src/com/intellij/packaging/impl/ui/ExtractedDirectoryPresentation.java new file mode 100644 index 000000000000..3649f0cc7ec8 --- /dev/null +++ b/java/compiler/impl/src/com/intellij/packaging/impl/ui/ExtractedDirectoryPresentation.java @@ -0,0 +1,65 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.packaging.impl.ui; + +import com.intellij.ide.projectView.PresentationData; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.packaging.impl.elements.ExtractedDirectoryElementType; +import com.intellij.packaging.impl.elements.ExtractedDirectoryPackagingElement; +import com.intellij.packaging.ui.PackagingElementPresentation; +import com.intellij.packaging.ui.PackagingElementWeights; +import com.intellij.ui.SimpleTextAttributes; +import com.intellij.util.PathUtil; +import org.jetbrains.annotations.NotNull; + +/** + * @author nik + */ +public class ExtractedDirectoryPresentation extends PackagingElementPresentation { + private final String myJarPath; + private final String myPathInJar; + private final VirtualFile myFile; + + public ExtractedDirectoryPresentation(ExtractedDirectoryPackagingElement element) { + myFile = element.findFile(); + myJarPath = element.getFilePath(); + myPathInJar = element.getPathInJar(); + } + + public String getPresentableName() { + return PathUtil.getFileName(myJarPath) + myPathInJar; + } + + public void render(@NotNull PresentationData presentationData, SimpleTextAttributes mainAttributes, SimpleTextAttributes commentAttributes) { + presentationData.setIcons(ExtractedDirectoryElementType.EXTRACTED_FOLDER_ICON); + final String parentPath = PathUtil.getParentPath(myJarPath); + if (myFile == null || !myFile.isDirectory()) { + mainAttributes = SimpleTextAttributes.ERROR_ATTRIBUTES; + final VirtualFile parentFile = LocalFileSystem.getInstance().findFileByPath(parentPath); + if (parentFile == null) { + commentAttributes = SimpleTextAttributes.ERROR_ATTRIBUTES; + } + } + presentationData.addText("Unpacked '" + PathUtil.getFileName(myJarPath) + myPathInJar + "'", mainAttributes); + presentationData.addText(" (" + parentPath + ")", commentAttributes); + } + + @Override + public int getWeight() { + return PackagingElementWeights.EXTRACTED_DIRECTORY; + } +} \ No newline at end of file diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/ui/FileCopyPresentation.java b/java/compiler/impl/src/com/intellij/packaging/impl/ui/FileCopyPresentation.java index 853f72c87b9d..a48648ddf913 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/ui/FileCopyPresentation.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/ui/FileCopyPresentation.java @@ -20,7 +20,6 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.packaging.impl.elements.FileCopyElementType; -import com.intellij.packaging.ui.ArtifactEditorContext; import com.intellij.packaging.ui.PackagingElementPresentation; import com.intellij.packaging.ui.PackagingElementWeights; import com.intellij.ui.SimpleTextAttributes; @@ -33,12 +32,10 @@ import org.jetbrains.annotations.NotNull; public class FileCopyPresentation extends PackagingElementPresentation { private final String mySourcePath; private final String myOutputFileName; - private final ArtifactEditorContext myContext; private final VirtualFile myFile; - public FileCopyPresentation(String filePath, String outputFileName, ArtifactEditorContext context) { + public FileCopyPresentation(String filePath, String outputFileName) { myOutputFileName = outputFileName; - myContext = context; String parentPath; myFile = LocalFileSystem.getInstance().findFileByPath(filePath); @@ -65,7 +62,7 @@ public class FileCopyPresentation extends PackagingElementPresentation { public void render(@NotNull PresentationData presentationData, SimpleTextAttributes mainAttributes, SimpleTextAttributes commentAttributes) { if (myFile != null && !myFile.isDirectory()) { - presentationData.setIcons(myFile != null ? myFile.getIcon() : FileCopyElementType.ICON); + presentationData.setIcons(myFile.getIcon()); presentationData.addText(myOutputFileName, mainAttributes); presentationData.addText(" (" + mySourcePath + ")", commentAttributes); } diff --git a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Include.java b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Include.java index b0a5cff3c0ba..73352a24d983 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Include.java +++ b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Include.java @@ -17,7 +17,6 @@ package com.intellij.compiler.ant.taskdefs; import com.intellij.compiler.ant.Tag; -import com.intellij.openapi.util.Pair; import org.jetbrains.annotations.NonNls; /** @@ -27,8 +26,7 @@ import org.jetbrains.annotations.NonNls; public class Include extends Tag { public Include(@NonNls final String name) { - //noinspection HardCodedStringLiteral - super("include", new Pair[] {new Pair("name", name)}); + super("include", pair("name", name)); } } diff --git a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/PatternSet.java b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/PatternSet.java index eee85abbd7ad..6a1d2375e6bb 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/PatternSet.java +++ b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/PatternSet.java @@ -17,7 +17,6 @@ package com.intellij.compiler.ant.taskdefs; import com.intellij.compiler.ant.Tag; -import com.intellij.openapi.util.Pair; import org.jetbrains.annotations.NonNls; /** @@ -26,7 +25,6 @@ import org.jetbrains.annotations.NonNls; */ public class PatternSet extends Tag{ public PatternSet(@NonNls final String id) { - //noinspection HardCodedStringLiteral - super("patternset", new Pair[] {new Pair("id", id)}); + super("patternset", pair("id", id)); } } diff --git a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Unzip.java b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Unzip.java new file mode 100644 index 000000000000..8e3a4e7d2369 --- /dev/null +++ b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/Unzip.java @@ -0,0 +1,27 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.compiler.ant.taskdefs; + +import com.intellij.compiler.ant.Tag; + +/** + * @author nik + */ +public class Unzip extends Tag { + public Unzip(String archivePath, String dest) { + super("unzip", pair("src", archivePath), pair("dest", dest)); + } +} diff --git a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/ZipFileSet.java b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/ZipFileSet.java index 50991595783b..9970a9d004d5 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/ZipFileSet.java +++ b/java/compiler/openapi/src/com/intellij/compiler/ant/taskdefs/ZipFileSet.java @@ -17,9 +17,11 @@ package com.intellij.compiler.ant.taskdefs; import com.intellij.compiler.ant.Tag; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; @@ -31,12 +33,23 @@ import java.io.File; public class ZipFileSet extends Tag{ public static final ZipFileSet[] EMPTY_ARRAY = new ZipFileSet[0]; + private ZipFileSet(@NonNls String tagName, Pair... tagOptions) { + super(tagName, tagOptions); + } + public ZipFileSet(@NonNls String fileOrDir, @NonNls final String relativePath, boolean isDir) { super("zipfileset", pair(isDir ? "dir" : "file", fileOrDir), pair("prefix", prefix(isDir, relativePath))); } + public static ZipFileSet createUnpackedSet(@NonNls String zipFilePath, @NotNull String relativePath, final boolean isDir, String pattern) { + return new ZipFileSet("zipfileset", + pair("src", zipFilePath), + pair("prefix", prefix(isDir, relativePath)), + pair("includes", pattern)); + } + @Nullable private static String prefix(final boolean isDir, final String relativePath) { String path; diff --git a/java/compiler/openapi/src/com/intellij/packaging/elements/AntCopyInstructionCreator.java b/java/compiler/openapi/src/com/intellij/packaging/elements/AntCopyInstructionCreator.java index 33dccf956950..0c20bb61c4b8 100644 --- a/java/compiler/openapi/src/com/intellij/packaging/elements/AntCopyInstructionCreator.java +++ b/java/compiler/openapi/src/com/intellij/packaging/elements/AntCopyInstructionCreator.java @@ -15,8 +15,8 @@ */ package com.intellij.packaging.elements; -import com.intellij.compiler.ant.Tag; import com.intellij.compiler.ant.Generator; +import com.intellij.compiler.ant.Tag; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -32,8 +32,11 @@ public interface AntCopyInstructionCreator { Tag createFileCopyInstruction(@NotNull String filePath, String outputFileName); @NotNull - AntCopyInstructionCreator subFolder(String directoryName); + AntCopyInstructionCreator subFolder(@NotNull String directoryName); @Nullable - Generator createSubFolderCommand(String directoryName); + Generator createSubFolderCommand(@NotNull String directoryName); + + @NotNull + Generator createExtractedDirectoryInstruction(@NotNull String jarPath, @NotNull String pathInJar); } diff --git a/java/compiler/openapi/src/com/intellij/packaging/elements/PackagingElementFactory.java b/java/compiler/openapi/src/com/intellij/packaging/elements/PackagingElementFactory.java index 88364671f4da..2cbad503ce6a 100644 --- a/java/compiler/openapi/src/com/intellij/packaging/elements/PackagingElementFactory.java +++ b/java/compiler/openapi/src/com/intellij/packaging/elements/PackagingElementFactory.java @@ -67,6 +67,10 @@ public abstract class PackagingElementFactory { @NotNull public abstract PackagingElement createDirectoryCopyWithParentDirectories(@NotNull String filePath, @NotNull String relativeOutputPath); + @NotNull + public abstract PackagingElement createExtractedDirectoryWithParentDirectories(@NotNull String jarPath, @NotNull String pathInJar, + @NotNull String relativeOutputPath); + @NotNull public abstract PackagingElement createFileCopyWithParentDirectories(@NotNull String filePath, @NotNull String relativeOutputPath, @Nullable String outputFileName); diff --git a/java/compiler/openapi/src/com/intellij/packaging/ui/PackagingElementWeights.java b/java/compiler/openapi/src/com/intellij/packaging/ui/PackagingElementWeights.java index e36ac1229052..f193e9be3490 100644 --- a/java/compiler/openapi/src/com/intellij/packaging/ui/PackagingElementWeights.java +++ b/java/compiler/openapi/src/com/intellij/packaging/ui/PackagingElementWeights.java @@ -22,6 +22,7 @@ public class PackagingElementWeights { public static final int ARTIFACT = 100; public static final int DIRECTORY = 50; public static final int DIRECTORY_COPY = 40; + public static final int EXTRACTED_DIRECTORY = 39; public static final int LIBRARY = 30; public static final int MODULE = 20; public static final int FACET = 10; diff --git a/platform/icons/src/nodes/copyOfFolder.png b/platform/icons/src/nodes/copyOfFolder.png index b4c66afd4e8698202cab596ad0d74f15a97c7442..eaa813b50df2edcccc95c7bf8477cee38055ae20 100644 GIT binary patch delta 530 zcmV+t0`2|R1&*l98_w@({?yvW`3vwYo%mOmx=A+LHPw%W_`2YJG z!~cKZ8UFwI4mMm#iCd|yD)c5JBgC?QK$rdc^=*1%_qGWz2e5!7f7Ru98I1Mn85o&3 zAfEXD5AGRXhJR`d|3N1FX885#Fhh6m$~+(kVE`-)85#dG96h{+;rh8f43O{ug#?KF z3zk>Vv|zAQe~J+VEN~Xk*6U|>F@!s^GVrQLU?^NLa~cDqwlagMg`*6*0Zr>DLX8EeFCh$|fOV delta 668 zcmV;N0%QHm1lI+SBn<>-K}|sb0I$e51&ZmBAt!$VX-PyuRCwBA{Qv(y12$lvzuW5X zuTKsCetu&A_v`bF6HD@zV^aqZKnx%Quwm=;RcBV-{r4Y)O@o`x;8F(=Kuioc!0!(a zzJciJhZq_De0}~6mpXs|!f5~yaN=O20Du5uLFQPeESdE0*C&I2KR+}4`~Bq)O#I)U zAAf%gToMmKxeqSvnI8v}0|+1#1OEQ_pj*_GZ42Xn{lmzhB+0;FGj*N?i2v$21H zL=-&$0mO(N3$evh{`+QUGwi(0h)@J%KD!RYn-k9hZ8t$y4-i0L1Fm+PGcd7of-!@# z?f;6!PZ%Pbr!wpS8Uixr`3(jJrsLTRc>#Z#3>#LjJp1b(3&ZdK%nS=R>@fidAaEeU zG@rTp@XX(rI~m%Ngcw%TXELaBKs0k-$Y)sI?#*DU^N(S2cdBts6ua@ye-NJl1Q3{H zV&h^sckSUBJtJP@8xKA)usq$x&=&8(P(3Gufs2WWVP=sY!>0?Y7}z;^8D4(A&G3KZ z@@0l!{|&(g00a=&fOFR#or!E)Y0U8dAA|0{zd(^cprB`1YbC+J@E^$kdWV5QTpGy! z&2VMv1_lleHiqB-n85}B1Q6JOKMbru_1_r&zr6s|_!ATzQ2ZSQGqVdZu&}W(u&^?N z!vF*T0tjrtZ=eCdhzBYHCb+*pF*JWdFi@P8i-C)mlYyB9VE{k?ferZ1zzs?T5JUd` z!h(N8@m~gJRu+cbEm~)LlvjeI6Ci+?U|sY;jaSWqj_|JcCApXh#)6B%e1~vd7zyO-@NU(z`{Bi&Q002ovPDBK*LSTaC C^)O-p diff --git a/platform/icons/src/nodes/extractedFolder.png b/platform/icons/src/nodes/extractedFolder.png new file mode 100644 index 0000000000000000000000000000000000000000..6526ba4f8db2369fde0dc7565a36f26b782444b3 GIT binary patch literal 657 zcmV;C0&e|@P)|_tx#2%=Ig~-eG=5Kim#Zm^9RRHq~gkI;j#`+m?o-y)jHqWYO4_sJRD!0H|!ntXBY*)Pk;6LHI3rHnxOf zM>oD67{HpM!EO+0Ex4YUY?qn&R{-rNtqt%zkDaIPkkm(+Ta!wV7U!X^CYL?&U}GbC}OK356!)}*Y5*R*uY%R41_Yf&F