@Test public void mainClassFromManifest() throws Exception { this.testJarFile.addClass("a/b/C.class", ClassWithoutMainMethod.class); Manifest manifest = new Manifest(); manifest.getMainAttributes().putValue("Manifest-Version", "1.0"); manifest.getMainAttributes().putValue("Main-Class", "a.b.C"); this.testJarFile.addManifest(manifest); File file = this.testJarFile.getFile(); Repackager repackager = new Repackager(file); repackager.repackage(NO_LIBRARIES); Manifest actualManifest = getManifest(file); assertThat(actualManifest.getMainAttributes().getValue("Main-Class")) .isEqualTo("org.springframework.boot.loader.JarLauncher"); assertThat(actualManifest.getMainAttributes().getValue("Start-Class")) .isEqualTo("a.b.C"); assertThat(hasLauncherClasses(file)).isTrue(); }
@Test public void duplicateLibraries() throws Exception { TestJarFile libJar = new TestJarFile(this.temporaryFolder); libJar.addClass("a/b/C.class", ClassWithoutMainMethod.class); final File libJarFile = libJar.getFile(); this.testJarFile.addClass("a/b/C.class", ClassWithMainMethod.class); File file = this.testJarFile.getFile(); Repackager repackager = new Repackager(file); this.thrown.expect(IllegalStateException.class); this.thrown.expectMessage("Duplicate library"); repackager.repackage(new Libraries() { @Override public void doWithLibraries(LibraryCallback callback) throws IOException { callback.library(new Library(libJarFile, LibraryScope.COMPILE, false)); callback.library(new Library(libJarFile, LibraryScope.COMPILE, false)); } }); }
@Test public void customLayout() throws Exception { TestJarFile libJar = new TestJarFile(this.temporaryFolder); libJar.addClass("a/b/C.class", ClassWithoutMainMethod.class); final File libJarFile = libJar.getFile(); this.testJarFile.addClass("a/b/C.class", ClassWithMainMethod.class); File file = this.testJarFile.getFile(); Repackager repackager = new Repackager(file); Layout layout = mock(Layout.class); final LibraryScope scope = mock(LibraryScope.class); given(layout.getLauncherClassName()).willReturn("testLauncher"); given(layout.getLibraryDestination(anyString(), eq(scope))).willReturn("test/"); repackager.setLayout(layout); repackager.repackage(new Libraries() { @Override public void doWithLibraries(LibraryCallback callback) throws IOException { callback.library(new Library(libJarFile, scope)); } }); assertThat(hasEntry(file, "test/" + libJarFile.getName())).isTrue(); assertThat(getManifest(file).getMainAttributes().getValue("Main-Class")) .isEqualTo("testLauncher"); }
@Test public void mainClassFromManifest() throws Exception { this.testJarFile.addClass("a/b/C.class", ClassWithoutMainMethod.class); Manifest manifest = new Manifest(); manifest = new Manifest(); manifest.getMainAttributes().putValue("Manifest-Version", "1.0"); manifest.getMainAttributes().putValue("Main-Class", "a.b.C"); this.testJarFile.addManifest(manifest); File file = this.testJarFile.getFile(); Repackager repackager = new Repackager(file); repackager.repackage(NO_LIBRARIES); Manifest actualManifest = getManifest(file); assertThat(actualManifest.getMainAttributes().getValue("Main-Class"), equalTo("org.springframework.boot.loader.JarLauncher")); assertThat(actualManifest.getMainAttributes().getValue("Start-Class"), equalTo("a.b.C")); assertThat(hasLauncherClasses(file), equalTo(true)); }
@Test public void customLayout() throws Exception { TestJarFile libJar = new TestJarFile(this.temporaryFolder); libJar.addClass("a/b/C.class", ClassWithoutMainMethod.class); final File libJarFile = libJar.getFile(); this.testJarFile.addClass("a/b/C.class", ClassWithMainMethod.class); File file = this.testJarFile.getFile(); Repackager repackager = new Repackager(file); Layout layout = mock(Layout.class); final LibraryScope scope = mock(LibraryScope.class); given(layout.getLauncherClassName()).willReturn("testLauncher"); given(layout.getLibraryDestination(anyString(), eq(scope))).willReturn("test/"); repackager.setLayout(layout); repackager.repackage(new Libraries() { @Override public void doWithLibraries(LibraryCallback callback) throws IOException { callback.library(new Library(libJarFile, scope)); } }); assertThat(hasEntry(file, "test/" + libJarFile.getName()), equalTo(true)); assertThat(getManifest(file).getMainAttributes().getValue("Main-Class"), equalTo("testLauncher")); }
@Test public void dontRecompressZips() throws Exception { TestJarFile nested = new TestJarFile(this.temporaryFolder); nested.addClass("a/b/C.class", ClassWithoutMainMethod.class); final File nestedFile = nested.getFile(); this.testJarFile.addFile("test/nested.jar", nestedFile); this.testJarFile.addClass("A.class", ClassWithMainMethod.class); File file = this.testJarFile.getFile(); Repackager repackager = new Repackager(file); repackager.repackage(new Libraries() { @Override public void doWithLibraries(LibraryCallback callback) throws IOException { callback.library(new Library(nestedFile, LibraryScope.COMPILE)); } }); JarFile jarFile = new JarFile(file); try { assertThat(jarFile.getEntry("lib/" + nestedFile.getName()).getMethod(), equalTo(ZipEntry.STORED)); assertThat(jarFile.getEntry("test/nested.jar").getMethod(), equalTo(ZipEntry.STORED)); } finally { jarFile.close(); } }
@Test public void findMainClassInJar() throws Exception { this.testJarFile.addClass("B.class", ClassWithMainMethod.class); this.testJarFile.addClass("A.class", ClassWithoutMainMethod.class); String actual = MainClassFinder.findMainClass(this.testJarFile.getJarFile(), ""); assertThat(actual).isEqualTo("B"); }
@Test public void findMainClassInJarSubFolder() throws Exception { this.testJarFile.addClass("a/b/c/D.class", ClassWithMainMethod.class); this.testJarFile.addClass("a/b/c/E.class", ClassWithoutMainMethod.class); this.testJarFile.addClass("a/b/F.class", ClassWithoutMainMethod.class); String actual = MainClassFinder.findMainClass(this.testJarFile.getJarFile(), ""); assertThat(actual).isEqualTo("a.b.c.D"); }
@Test public void findMainClassInFolder() throws Exception { this.testJarFile.addClass("B.class", ClassWithMainMethod.class); this.testJarFile.addClass("A.class", ClassWithoutMainMethod.class); String actual = MainClassFinder.findMainClass(this.testJarFile.getJarSource()); assertThat(actual).isEqualTo("B"); }
@Test public void findMainClassInSubFolder() throws Exception { this.testJarFile.addClass("a/b/c/D.class", ClassWithMainMethod.class); this.testJarFile.addClass("a/b/c/E.class", ClassWithoutMainMethod.class); this.testJarFile.addClass("a/b/F.class", ClassWithoutMainMethod.class); String actual = MainClassFinder.findMainClass(this.testJarFile.getJarSource()); assertThat(actual).isEqualTo("a.b.c.D"); }
@Test public void doWithFolderMainMethods() throws Exception { this.testJarFile.addClass("a/b/c/D.class", ClassWithMainMethod.class); this.testJarFile.addClass("a/b/c/E.class", ClassWithoutMainMethod.class); this.testJarFile.addClass("a/b/F.class", ClassWithoutMainMethod.class); this.testJarFile.addClass("a/b/G.class", ClassWithMainMethod.class); ClassNameCollector callback = new ClassNameCollector(); MainClassFinder.doWithMainClasses(this.testJarFile.getJarSource(), callback); assertThat(callback.getClassNames().toString()).isEqualTo("[a.b.G, a.b.c.D]"); }
@Test public void doWithJarMainMethods() throws Exception { this.testJarFile.addClass("a/b/c/D.class", ClassWithMainMethod.class); this.testJarFile.addClass("a/b/c/E.class", ClassWithoutMainMethod.class); this.testJarFile.addClass("a/b/F.class", ClassWithoutMainMethod.class); this.testJarFile.addClass("a/b/G.class", ClassWithMainMethod.class); ClassNameCollector callback = new ClassNameCollector(); MainClassFinder.doWithMainClasses(this.testJarFile.getJarFile(), "", callback); assertThat(callback.getClassNames().toString()).isEqualTo("[a.b.G, a.b.c.D]"); }
@Test public void specificMainClass() throws Exception { this.testJarFile.addClass("a/b/C.class", ClassWithoutMainMethod.class); File file = this.testJarFile.getFile(); Repackager repackager = new Repackager(file); repackager.setMainClass("a.b.C"); repackager.repackage(NO_LIBRARIES); Manifest actualManifest = getManifest(file); assertThat(actualManifest.getMainAttributes().getValue("Main-Class")) .isEqualTo("org.springframework.boot.loader.JarLauncher"); assertThat(actualManifest.getMainAttributes().getValue("Start-Class")) .isEqualTo("a.b.C"); assertThat(hasLauncherClasses(file)).isTrue(); }
@Test public void noMainClass() throws Exception { this.testJarFile.addClass("a/b/C.class", ClassWithoutMainMethod.class); this.thrown.expect(IllegalStateException.class); this.thrown.expectMessage("Unable to find main class"); new Repackager(this.testJarFile.getFile()).repackage(NO_LIBRARIES); }
@Test public void noMainClassAndLayoutIsNoneWithNoMain() throws Exception { this.testJarFile.addClass("a/b/C.class", ClassWithoutMainMethod.class); File file = this.testJarFile.getFile(); Repackager repackager = new Repackager(file); repackager.setLayout(new Layouts.None()); repackager.repackage(file, NO_LIBRARIES); Manifest actualManifest = getManifest(file); assertThat(actualManifest.getMainAttributes().getValue("Main-Class")) .isEqualTo(null); assertThat(hasLauncherClasses(file)).isFalse(); }
@Test public void libraries() throws Exception { TestJarFile libJar = new TestJarFile(this.temporaryFolder); libJar.addClass("a/b/C.class", ClassWithoutMainMethod.class, JAN_1_1985); final File libJarFile = libJar.getFile(); final File libJarFileToUnpack = libJar.getFile(); final File libNonJarFile = this.temporaryFolder.newFile(); FileCopyUtils.copy(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, libNonJarFile); this.testJarFile.addClass("a/b/C.class", ClassWithMainMethod.class); this.testJarFile.addFile("BOOT-INF/lib/" + libJarFileToUnpack.getName(), libJarFileToUnpack); File file = this.testJarFile.getFile(); libJarFile.setLastModified(JAN_1_1980); Repackager repackager = new Repackager(file); repackager.repackage(new Libraries() { @Override public void doWithLibraries(LibraryCallback callback) throws IOException { callback.library(new Library(libJarFile, LibraryScope.COMPILE)); callback.library( new Library(libJarFileToUnpack, LibraryScope.COMPILE, true)); callback.library(new Library(libNonJarFile, LibraryScope.COMPILE)); } }); assertThat(hasEntry(file, "BOOT-INF/lib/" + libJarFile.getName())).isTrue(); assertThat(hasEntry(file, "BOOT-INF/lib/" + libJarFileToUnpack.getName())) .isTrue(); assertThat(hasEntry(file, "BOOT-INF/lib/" + libNonJarFile.getName())).isFalse(); JarEntry entry = getEntry(file, "BOOT-INF/lib/" + libJarFile.getName()); assertThat(entry.getTime()).isEqualTo(JAN_1_1985); entry = getEntry(file, "BOOT-INF/lib/" + libJarFileToUnpack.getName()); assertThat(entry.getComment()).startsWith("UNPACK:"); assertThat(entry.getComment().length()).isEqualTo(47); }
@Test public void nullCustomLayout() throws Exception { this.testJarFile.addClass("a/b/C.class", ClassWithoutMainMethod.class); Repackager repackager = new Repackager(this.testJarFile.getFile()); this.thrown.expect(IllegalArgumentException.class); this.thrown.expectMessage("Layout must not be null"); repackager.setLayout(null); }
@Test public void dontRecompressZips() throws Exception { TestJarFile nested = new TestJarFile(this.temporaryFolder); nested.addClass("a/b/C.class", ClassWithoutMainMethod.class); final File nestedFile = nested.getFile(); this.testJarFile.addFile("test/nested.jar", nestedFile); this.testJarFile.addClass("A.class", ClassWithMainMethod.class); File file = this.testJarFile.getFile(); Repackager repackager = new Repackager(file); repackager.repackage(new Libraries() { @Override public void doWithLibraries(LibraryCallback callback) throws IOException { callback.library(new Library(nestedFile, LibraryScope.COMPILE)); } }); JarFile jarFile = new JarFile(file); try { assertThat( jarFile.getEntry("BOOT-INF/lib/" + nestedFile.getName()).getMethod()) .isEqualTo(ZipEntry.STORED); assertThat(jarFile.getEntry("BOOT-INF/classes/test/nested.jar").getMethod()) .isEqualTo(ZipEntry.STORED); } finally { jarFile.close(); } }
@Test public void unpackLibrariesTakePrecedenceOverExistingSourceEntries() throws Exception { TestJarFile nested = new TestJarFile(this.temporaryFolder); nested.addClass("a/b/C.class", ClassWithoutMainMethod.class); final File nestedFile = nested.getFile(); this.testJarFile.addFile("BOOT-INF/lib/" + nestedFile.getName(), nested.getFile()); this.testJarFile.addClass("A.class", ClassWithMainMethod.class); File file = this.testJarFile.getFile(); Repackager repackager = new Repackager(file); repackager.repackage(new Libraries() { @Override public void doWithLibraries(LibraryCallback callback) throws IOException { callback.library(new Library(nestedFile, LibraryScope.COMPILE, true)); } }); JarFile jarFile = new JarFile(file); try { assertThat( jarFile.getEntry("BOOT-INF/lib/" + nestedFile.getName()).getComment()) .startsWith("UNPACK:"); } finally { jarFile.close(); } }
@Test public void existingSourceEntriesTakePrecedenceOverStandardLibraries() throws Exception { TestJarFile nested = new TestJarFile(this.temporaryFolder); nested.addClass("a/b/C.class", ClassWithoutMainMethod.class); final File nestedFile = nested.getFile(); this.testJarFile.addFile("BOOT-INF/lib/" + nestedFile.getName(), nested.getFile()); this.testJarFile.addClass("A.class", ClassWithMainMethod.class); File file = this.testJarFile.getFile(); Repackager repackager = new Repackager(file); long sourceLength = nestedFile.length(); repackager.repackage(new Libraries() { @Override public void doWithLibraries(LibraryCallback callback) throws IOException { nestedFile.delete(); File toZip = RepackagerTests.this.temporaryFolder.newFile(); ZipUtil.packEntry(toZip, nestedFile); callback.library(new Library(nestedFile, LibraryScope.COMPILE)); } }); JarFile jarFile = new JarFile(file); try { assertThat(jarFile.getEntry("BOOT-INF/lib/" + nestedFile.getName()).getSize()) .isEqualTo(sourceLength); } finally { jarFile.close(); } }
@Test public void findMainClassInJar() throws Exception { this.testJarFile.addClass("B.class", ClassWithMainMethod.class); this.testJarFile.addClass("A.class", ClassWithoutMainMethod.class); String actual = MainClassFinder.findMainClass(this.testJarFile.getJarFile(), ""); assertThat(actual, equalTo("B")); }
@Test public void findMainClassInJarSubFolder() throws Exception { this.testJarFile.addClass("a/b/c/D.class", ClassWithMainMethod.class); this.testJarFile.addClass("a/b/c/E.class", ClassWithoutMainMethod.class); this.testJarFile.addClass("a/b/F.class", ClassWithoutMainMethod.class); String actual = MainClassFinder.findMainClass(this.testJarFile.getJarFile(), ""); assertThat(actual, equalTo("a.b.c.D")); }