| /* |
| * Copyright 2000-2012 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 org.jetbrains.jps.incremental.artifacts; |
| |
| import com.intellij.openapi.util.io.FileUtil; |
| import com.intellij.util.PathUtil; |
| import org.jetbrains.jps.model.artifact.JpsArtifact; |
| import org.jetbrains.jps.model.java.JpsJavaExtensionService; |
| import org.jetbrains.jps.model.library.JpsLibrary; |
| import org.jetbrains.jps.model.module.JpsModule; |
| import org.jetbrains.jps.util.JpsPathUtil; |
| |
| import java.io.BufferedOutputStream; |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.util.Enumeration; |
| import java.util.jar.JarEntry; |
| import java.util.jar.JarFile; |
| import java.util.zip.CRC32; |
| import java.util.zip.ZipEntry; |
| import java.util.zip.ZipFile; |
| import java.util.zip.ZipOutputStream; |
| |
| import static com.intellij.util.io.TestFileSystemBuilder.fs; |
| import static org.jetbrains.jps.incremental.artifacts.LayoutElementTestUtil.archive; |
| import static org.jetbrains.jps.incremental.artifacts.LayoutElementTestUtil.root; |
| |
| /** |
| * @author nik |
| */ |
| public class ArtifactBuilderTest extends ArtifactBuilderTestCase { |
| public void testFileCopy() { |
| final JpsArtifact a = addArtifact(root().fileCopy(createFile("file.txt", "foo"))); |
| buildAll(); |
| assertOutput(a, fs().file("file.txt", "foo")); |
| } |
| |
| public void testDir() { |
| final JpsArtifact a = addArtifact( |
| root() |
| .fileCopy(createFile("abc.txt")) |
| .dir("dir") |
| .fileCopy(createFile("xxx.txt", "bar")) |
| ); |
| buildAll(); |
| assertOutput(a, fs() |
| .file("abc.txt") |
| .dir("dir") |
| .file("xxx.txt", "bar") |
| ); |
| } |
| |
| public void testArchive() { |
| final JpsArtifact a = addArtifact( |
| root() |
| .archive("xxx.zip") |
| .fileCopy(createFile("X.class", "data")) |
| .dir("dir") |
| .fileCopy(createFile("Y.class")) |
| ); |
| buildAll(); |
| assertOutput(a, fs() |
| .archive("xxx.zip") |
| .file("X.class", "data") |
| .dir("dir") |
| .file("Y.class") |
| ); |
| } |
| |
| public void testTwoDirsInArchive() { |
| final String dir1 = PathUtil.getParentPath(PathUtil.getParentPath(createFile("dir1/a/x.txt"))); |
| final String dir2 = PathUtil.getParentPath(PathUtil.getParentPath(createFile("dir2/a/y.txt"))); |
| final JpsArtifact a = addArtifact( |
| root() |
| .archive("a.jar") |
| .dirCopy(dir1) |
| .dirCopy(dir2) |
| .dir("a").fileCopy(createFile("z.txt")) |
| ); |
| buildAll(); |
| assertOutput(a, fs() |
| .archive("a.jar") |
| .dir("a") |
| .file("x.txt") |
| .file("y.txt") |
| .file("z.txt") |
| ); |
| } |
| |
| public void testArchiveInArchive() { |
| final JpsArtifact a = addArtifact( |
| root() |
| .archive("a.jar") |
| .archive("b.jar") |
| .fileCopy(createFile("xxx.txt", "foo")) |
| ); |
| buildAll(); |
| assertOutput(a, fs() |
| .archive("a.jar") |
| .archive("b.jar") |
| .file("xxx.txt", "foo") |
| ); |
| } |
| |
| public void testIncludedArtifact() { |
| final JpsArtifact included = addArtifact("included", |
| root() |
| .fileCopy(createFile("aaa.txt"))); |
| final JpsArtifact a = addArtifact( |
| root() |
| .dir("dir") |
| .artifact(included) |
| .end() |
| .fileCopy(createFile("bbb.txt")) |
| ); |
| buildAll(); |
| |
| assertOutput(included, fs().file("aaa.txt")); |
| assertOutput(a, fs() |
| .dir("dir") |
| .file("aaa.txt") |
| .end() |
| .file("bbb.txt") |
| ); |
| } |
| |
| public void testMergeDirectories() { |
| final JpsArtifact included = addArtifact("included", |
| root().dir("dir").fileCopy(createFile("aaa.class"))); |
| final JpsArtifact a = addArtifact( |
| root() |
| .artifact(included) |
| .dir("dir") |
| .fileCopy(createFile("bbb.class"))); |
| buildAll(); |
| assertOutput(a, fs() |
| .dir("dir") |
| .file("aaa.class") |
| .file("bbb.class") |
| ); |
| } |
| |
| public void testCopyLibrary() { |
| final JpsLibrary library = addProjectLibrary("lib", getJUnitJarPath()); |
| final JpsArtifact a = addArtifact(root().lib(library)); |
| buildAll(); |
| assertOutput(a, fs().file("junit.jar")); |
| } |
| |
| public void testModuleOutput() { |
| final String file = createFile("src/A.java", "public class A {}"); |
| final JpsModule module = addModule("a", PathUtil.getParentPath(file)); |
| final JpsArtifact artifact = addArtifact(root().module(module)); |
| |
| buildArtifacts(artifact); |
| assertOutput(artifact, fs().file("A.class")); |
| } |
| |
| public void testCopyResourcesFromModuleOutput() { |
| String file = createFile("src/a.xml", ""); |
| JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(myProject).addResourcePattern("*.xml"); |
| JpsModule module = addModule("a", PathUtil.getParentPath(file)); |
| JpsArtifact artifact = addArtifact(root().module(module)); |
| buildArtifacts(artifact); |
| assertOutput(artifact, fs().file("a.xml")); |
| } |
| |
| public void testIgnoredFile() { |
| final String file = createFile("a/.svn/a.txt"); |
| createFile("a/svn/b.txt"); |
| final JpsArtifact a = addArtifact(root().parentDirCopy(PathUtil.getParentPath(file))); |
| buildAll(); |
| assertOutput(a, fs().dir("svn").file("b.txt")); |
| } |
| |
| public void testIgnoredFileInArchive() { |
| final String file = createFile("a/.svn/a.txt"); |
| createFile("a/svn/b.txt"); |
| final JpsArtifact a = addArtifact(archive("a.jar").parentDirCopy(PathUtil.getParentPath(file))); |
| buildAll(); |
| assertOutput(a, fs().archive("a.jar").dir("svn").file("b.txt")); |
| } |
| |
| public void testCopyExcludedFolder() { |
| //explicitly added excluded files should be copied (e.g. compile output) |
| final String file = createFile("xxx/excluded/a.txt"); |
| createFile("xxx/excluded/CVS"); |
| final String excluded = PathUtil.getParentPath(file); |
| final String dir = PathUtil.getParentPath(excluded); |
| |
| final JpsModule module = addModule("myModule"); |
| module.getContentRootsList().addUrl(JpsPathUtil.pathToUrl(dir)); |
| module.getExcludeRootsList().addUrl(JpsPathUtil.pathToUrl(excluded)); |
| |
| final JpsArtifact a = addArtifact(root().dirCopy(excluded)); |
| buildAll(); |
| assertOutput(a, fs().file("a.txt")); |
| } |
| |
| public void testCopyExcludedFile() { |
| //excluded files under non-excluded directory should not be copied |
| final String file = createFile("xxx/excluded/a.txt"); |
| createFile("xxx/b.txt"); |
| createFile("xxx/CVS"); |
| final String dir = PathUtil.getParentPath(PathUtil.getParentPath(file)); |
| |
| JpsModule module = addModule("myModule"); |
| module.getContentRootsList().addUrl(JpsPathUtil.pathToUrl(dir)); |
| module.getExcludeRootsList().addUrl(JpsPathUtil.pathToUrl(PathUtil.getParentPath(file))); |
| |
| final JpsArtifact a = addArtifact(root().dirCopy(dir)); |
| buildAll(); |
| assertOutput(a, fs().file("b.txt")); |
| } |
| |
| public void testExtractDirectory() { |
| final JpsArtifact a = addArtifact("a", root().dir("dir").extractedDir(getJUnitJarPath(), "/junit/textui/")); |
| buildAll(); |
| assertOutput(a, fs().dir("dir") |
| .file("ResultPrinter.class") |
| .file("TestRunner.class")); |
| } |
| |
| public void testExtractDirectoryFromExcludedJar() throws IOException { |
| String jarPath = createFile("dir/lib/j.jar"); |
| FileUtil.copy(new File(getJUnitJarPath()), new File(jarPath)); |
| JpsModule module = addModule("m"); |
| String libDir = PathUtil.getParentPath(jarPath); |
| module.getContentRootsList().addUrl(JpsPathUtil.pathToUrl(PathUtil.getParentPath(libDir))); |
| module.getExcludeRootsList().addUrl(JpsPathUtil.pathToUrl(libDir)); |
| final JpsArtifact a = addArtifact("a", root().extractedDir(jarPath, "/junit/textui/")); |
| buildAll(); |
| assertOutput(a, fs().file("ResultPrinter.class") |
| .file("TestRunner.class")); |
| } |
| |
| public void testPackExtractedDirectory() { |
| final JpsArtifact a = addArtifact("a", root().archive("a.jar").extractedDir(getJUnitJarPath(), "/junit/textui/")); |
| buildAll(); |
| assertOutput(a, fs().archive("a.jar") |
| .file("ResultPrinter.class") |
| .file("TestRunner.class")); |
| } |
| |
| public void testSelfIncludingArtifact() { |
| final JpsArtifact a = addArtifact("a", root()); |
| LayoutElementTestUtil.addArtifactToLayout(a, a); |
| assertBuildFailed(a); |
| } |
| |
| public void testCircularInclusion() { |
| final JpsArtifact a = addArtifact("a", root()); |
| final JpsArtifact b = addArtifact("b", root()); |
| LayoutElementTestUtil.addArtifactToLayout(a, b); |
| LayoutElementTestUtil.addArtifactToLayout(b, a); |
| assertBuildFailed(a); |
| assertBuildFailed(b); |
| } |
| |
| public void testArtifactContainingSelfIncludingArtifact() { |
| JpsArtifact c = addArtifact("c", root()); |
| final JpsArtifact a = addArtifact("a", root().artifact(c)); |
| LayoutElementTestUtil.addArtifactToLayout(a, a); |
| final JpsArtifact b = addArtifact("b", root().artifact(a)); |
| |
| buildArtifacts(c); |
| assertBuildFailed(b); |
| assertBuildFailed(a); |
| } |
| |
| public void testArtifactContainingSelfIncludingArtifactWithoutOutput() { |
| final JpsArtifact a = addArtifact("a", root()); |
| LayoutElementTestUtil.addArtifactToLayout(a, a); |
| final JpsArtifact b = addArtifact("b", root().artifact(a)); |
| a.setOutputPath(null); |
| |
| assertBuildFailed(b); |
| } |
| |
| //IDEA-73893 |
| public void testManifestFileIsFirstEntry() throws IOException { |
| final String firstFile = createFile("src/A.txt"); |
| final String manifestFile = createFile("src/MANIFEST.MF"); |
| final String lastFile = createFile("src/Z.txt"); |
| final JpsArtifact a = addArtifact(archive("a.jar").dir("META-INF") |
| .fileCopy(firstFile).fileCopy(manifestFile).fileCopy(lastFile)); |
| buildArtifacts(a); |
| final String jarPath = a.getOutputPath() + "/a.jar"; |
| JarFile jarFile = new JarFile(new File(jarPath)); |
| try { |
| final Enumeration<JarEntry> entries = jarFile.entries(); |
| assertTrue(entries.hasMoreElements()); |
| final JarEntry firstEntry = entries.nextElement(); |
| assertEquals(JarFile.MANIFEST_NAME, firstEntry.getName()); |
| } |
| finally { |
| jarFile.close(); |
| } |
| } |
| |
| public void testPreserveCompressionMethodForEntryExtractedFromOneArchiveAndPackedIntoAnother() throws IOException { |
| String path = createFile("data/a.jar"); |
| ZipOutputStream output = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(new File(path)))); |
| try { |
| ZipEntry entry = new ZipEntry("a.txt"); |
| byte[] text = "text".getBytes(); |
| entry.setMethod(ZipEntry.STORED); |
| entry.setSize(text.length); |
| CRC32 crc32 = new CRC32(); |
| crc32.update(text); |
| entry.setCrc(crc32.getValue()); |
| output.putNextEntry(entry); |
| output.write(text); |
| output.closeEntry(); |
| } |
| catch (Exception e) { |
| e.printStackTrace(); |
| } |
| finally { |
| output.close(); |
| } |
| JpsArtifact a = addArtifact(archive("b.jar").extractedDir(path, "")); |
| buildAll(); |
| assertOutput(a, fs().archive("b.jar").file("a.txt", "text")); |
| |
| final String jarPath = a.getOutputPath() + "/b.jar"; |
| ZipFile zipFile = new ZipFile(new File(jarPath)); |
| try { |
| ZipEntry entry = zipFile.getEntry("a.txt"); |
| assertNotNull(entry); |
| assertEquals(ZipEntry.STORED, entry.getMethod()); |
| } |
| finally { |
| zipFile.close(); |
| } |
| } |
| |
| public void testBuildModuleBeforeArtifactIfSomeDirectoryInsideModuleOutputIsCopiedToArtifact() { |
| String src = PathUtil.getParentPath(PathUtil.getParentPath(createFile("src/x/A.java", "package x; class A{}"))); |
| JpsModule module = addModule("m", src); |
| File output = JpsJavaExtensionService.getInstance().getOutputDirectory(module, false); |
| JpsArtifact artifact = addArtifact(root().dirCopy(new File(output, "x").getAbsolutePath())); |
| rebuildAll(); |
| assertOutput(module, fs().dir("x").file("A.class")); |
| assertOutput(artifact, fs().file("A.class")); |
| } |
| |
| public void testClearOutputOnRebuild() throws IOException { |
| String file = createFile("d/a.txt"); |
| JpsArtifact a = addArtifact(root().parentDirCopy(file)); |
| buildAll(); |
| createFileInArtifactOutput(a, "b.txt"); |
| buildAllAndAssertUpToDate(); |
| assertOutput(a, fs().file("a.txt").file("b.txt")); |
| |
| rebuildAll(); |
| assertOutput(a, fs().file("a.txt")); |
| } |
| |
| public void testDeleteOnlyOutputFileOnRebuildForArchiveArtifact() throws IOException { |
| String file = createFile("a.txt"); |
| JpsArtifact a = addArtifact(archive("a.jar").fileCopy(file)); |
| buildAll(); |
| createFileInArtifactOutput(a, "b.txt"); |
| buildAllAndAssertUpToDate(); |
| assertOutput(a, fs().archive("a.jar").file("a.txt").end().file("b.txt")); |
| |
| rebuildAll(); |
| assertOutput(a, fs().archive("a.jar").file("a.txt").end().file("b.txt")); |
| } |
| |
| public void testDoNotCreateEmptyArchive() { |
| String file = createFile("dir/a.txt"); |
| JpsArtifact a = addArtifact(archive("a.jar").parentDirCopy(file)); |
| delete(file); |
| buildAll(); |
| assertEmptyOutput(a); |
| } |
| |
| public void testDoNotCreateEmptyArchiveInsideArchive() { |
| String file = createFile("dir/a.txt"); |
| JpsArtifact a = addArtifact(archive("a.jar").archive("inner.jar").parentDirCopy(file)); |
| delete(file); |
| buildAll(); |
| assertEmptyOutput(a); |
| } |
| |
| public void testDoNotCreateEmptyArchiveFromExtractedDirectory() { |
| final JpsArtifact a = addArtifact("a", archive("a.jar").dir("dir").extractedDir(getJUnitJarPath(), "/xxx/")); |
| buildAll(); |
| assertEmptyOutput(a); |
| } |
| |
| public void testExtractNonExistentJarFile() { |
| JpsArtifact a = addArtifact(root().extractedDir("this-file-does-not-exist.jar", "/")); |
| buildAll(); |
| assertEmptyOutput(a); |
| } |
| |
| public void testRepackNonExistentJarFile() { |
| JpsArtifact a = addArtifact(archive("a.jar").extractedDir("this-file-does-not-exist.jar", "/").fileCopy(createFile("a.txt"))); |
| buildAll(); |
| assertOutput(a, fs().archive("a.jar").file("a.txt")); |
| } |
| |
| private static void createFileInArtifactOutput(JpsArtifact a, final String fileName) throws IOException { |
| assertTrue(new File(a.getOutputPath(), fileName).createNewFile()); |
| } |
| } |