diff --git a/jps/antLayout/src/jetbrains/antlayout/datatypes/JarContainer.java b/jps/antLayout/src/jetbrains/antlayout/datatypes/JarContainer.java index 01d490cbb6fb..ad1d02c664a0 100644 --- a/jps/antLayout/src/jetbrains/antlayout/datatypes/JarContainer.java +++ b/jps/antLayout/src/jetbrains/antlayout/datatypes/JarContainer.java @@ -1,46 +1,50 @@ -package jetbrains.antlayout.datatypes; - -import org.apache.tools.ant.taskdefs.Zip; -import org.apache.tools.ant.taskdefs.Jar; -import org.apache.tools.ant.taskdefs.Manifest; -import org.apache.tools.ant.taskdefs.ManifestException; -import org.apache.tools.ant.types.ZipFileSet; -import org.apache.tools.ant.types.Path; - -import java.io.File; - -/** - * @author max - */ -public class JarContainer extends ZipContainer { - protected Zip createTask() { - Jar task = new Jar(); - task.setTaskName("jar"); - task.setWhenmanifestonly((Zip.WhenEmpty) Zip.WhenEmpty.getInstance(Zip.WhenEmpty.class, "skip")); - return task; - } - - public void setIndex(boolean flag) { - ((Jar) task).setIndex(flag); - } - - public void setManifestEncoding(String manifestEncoding) { - ((Jar) task).setManifestEncoding(manifestEncoding); - } - - public void setManifest(File manifestFile) { - ((Jar) task).setManifest(manifestFile); - } - - public void setFilesetmanifest(Jar.FilesetManifestConfig config) { - ((Jar) task).setFilesetmanifest(config); - } - - public void addConfiguredManifest(Manifest newManifest) throws ManifestException { - ((Jar) task).addConfiguredManifest(newManifest); - } - - public void addMetainf(ZipFileSet fs) { - ((Jar) task).addMetainf(fs); - } -} +package jetbrains.antlayout.datatypes; + +import org.apache.tools.ant.Main; +import org.apache.tools.ant.taskdefs.*; +import org.apache.tools.ant.types.ZipFileSet; + +import java.io.File; + +/** + * @author max + */ +public class JarContainer extends ZipContainer { + protected Zip createTask() { + String version = Main.getAntVersion(); + Jar task; + if (version != null && (version.indexOf("1.8.0") != -1 || version.indexOf("1.8.1") != -1)) { + task = new PatchedJar(); + } + else { + task = new Jar(); + } + task.setTaskName("jar"); + task.setWhenmanifestonly((Zip.WhenEmpty) Zip.WhenEmpty.getInstance(Zip.WhenEmpty.class, "skip")); + return task; + } + + public void setIndex(boolean flag) { + ((Jar) task).setIndex(flag); + } + + public void setManifestEncoding(String manifestEncoding) { + ((Jar) task).setManifestEncoding(manifestEncoding); + } + + public void setManifest(File manifestFile) { + ((Jar) task).setManifest(manifestFile); + } + + public void setFilesetmanifest(Jar.FilesetManifestConfig config) { + ((Jar) task).setFilesetmanifest(config); + } + + public void addConfiguredManifest(Manifest newManifest) throws ManifestException { + ((Jar) task).addConfiguredManifest(newManifest); + } + + public void addMetainf(ZipFileSet fs) { + ((Jar) task).addMetainf(fs); + } +} diff --git a/jps/antLayout/src/org/apache/tools/ant/taskdefs/PatchedJar.java b/jps/antLayout/src/org/apache/tools/ant/taskdefs/PatchedJar.java new file mode 100644 index 000000000000..4c77d5361c98 --- /dev/null +++ b/jps/antLayout/src/org/apache/tools/ant/taskdefs/PatchedJar.java @@ -0,0 +1,83 @@ +package org.apache.tools.ant.taskdefs; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.taskdefs.Jar; +import org.apache.tools.ant.taskdefs.Zip; +import org.apache.tools.ant.types.ArchiveFileSet; +import org.apache.tools.ant.types.FileSet; +import org.apache.tools.ant.types.Resource; +import org.apache.tools.ant.types.ResourceCollection; + +import java.io.File; + +/** + * This class is added to workaround https://issues.apache.org/bugzilla/show_bug.cgi?id=49605 + * in Ant 1.8.0 and 1.8.1 + * + * @author nik + */ +public class PatchedJar extends Jar { + private static final String MANIFEST_NAME = "META-INF/MANIFEST.MF"; + + @Override + protected ArchiveState getResourcesToAdd(ResourceCollection[] rcs, File zipFile, boolean needsUpdate) throws BuildException { + if (skipWriting) { + // this pass is only there to construct the merged + // manifest this means we claim an update was needed and + // only include the manifests, skipping any uptodate + // checks here defering them for the second run + Resource[][] manifests = grabManifests(rcs); + int count = 0; + for (int i = 0; i < manifests.length; i++) { + count += manifests[i].length; + } + log("found a total of " + count + " manifests in " + + manifests.length + " resource collections", + Project.MSG_VERBOSE); + return new ArchiveState(true, manifests); + } + + return super.getResourcesToAdd(rcs, zipFile, needsUpdate); + } + + /** + * This method is copied from Jar class in Ant 1.8.2 + */ + private Resource[][] grabManifests(ResourceCollection[] rcs) { + Resource[][] manifests = new Resource[rcs.length][]; + for (int i = 0; i < rcs.length; i++) { + Resource[][] resources = null; + if (rcs[i] instanceof FileSet) { + resources = grabResources(new FileSet[] {(FileSet) rcs[i]}); + } else { + resources = grabNonFileSetResources(new ResourceCollection[] { + rcs[i] + }); + } + for (int j = 0; j < resources[0].length; j++) { + String name = resources[0][j].getName().replace('\\', '/'); + if (rcs[i] instanceof ArchiveFileSet) { + ArchiveFileSet afs = (ArchiveFileSet) rcs[i]; + if (!"".equals(afs.getFullpath(getProject()))) { + name = afs.getFullpath(getProject()); + } else if (!"".equals(afs.getPrefix(getProject()))) { + String prefix = afs.getPrefix(getProject()); + if (!prefix.endsWith("/") && !prefix.endsWith("\\")) { + prefix += "/"; + } + name = prefix + name; + } + } + if (name.equalsIgnoreCase(MANIFEST_NAME)) { + manifests[i] = new Resource[] {resources[0][j]}; + break; + } + } + if (manifests[i] == null) { + manifests[i] = new Resource[0]; + } + } + return manifests; + } +} diff --git a/jps/testData/manifestInArtifact/META-INF/MANIFEST.MF b/jps/testData/manifestInArtifact/META-INF/MANIFEST.MF new file mode 100644 index 000000000000..2706814bd46f --- /dev/null +++ b/jps/testData/manifestInArtifact/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: MyClass + diff --git a/jps/testData/manifestInArtifact/manifest.ipr b/jps/testData/manifestInArtifact/manifest.ipr new file mode 100644 index 000000000000..9710b41f1c2e --- /dev/null +++ b/jps/testData/manifestInArtifact/manifest.ipr @@ -0,0 +1,21 @@ + + + + + $PROJECT_DIR$/out/artifacts/simple + + + + + + + + + + + + + + + + diff --git a/jps/testSrc/org/jetbrains/jps/ManifestInArtifactTest.groovy b/jps/testSrc/org/jetbrains/jps/ManifestInArtifactTest.groovy new file mode 100644 index 000000000000..a81208420d61 --- /dev/null +++ b/jps/testSrc/org/jetbrains/jps/ManifestInArtifactTest.groovy @@ -0,0 +1,21 @@ +package org.jetbrains.jps + +import java.util.jar.Manifest +import org.jetbrains.jps.util.ZipUtil +import java.util.jar.Attributes + +/** + * @author nik + */ +class ManifestInArtifactTest extends JpsBuildTestCase { + public void test() { + def project = buildAll("testData/manifestInArtifact/manifest.ipr", [:], {}) + File jarFile = new File(project.targetFolder + "/artifacts/simple/simple.jar") + assertTrue(jarFile.exists()) + File extracted = ZipUtil.extractToTempDir(jarFile) + File manifestFile = new File(extracted, "META-INF/MANIFEST.MF") + assertTrue(manifestFile.exists()) + Manifest manifest = new Manifest(new FileInputStream(manifestFile)) + assertEquals("MyClass", manifest.getMainAttributes().getValue(Attributes.Name.MAIN_CLASS)) + } +}