--- old/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java 2016-12-14 22:22:57.000000000 +0530 +++ new/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java 2016-12-14 22:22:57.000000000 +0530 @@ -58,7 +58,6 @@ import static java.util.stream.Collectors.*; import jdk.tools.jlink.internal.BasicImageWriter; -import jdk.tools.jlink.internal.plugins.FileCopierPlugin.SymImageFile; import jdk.tools.jlink.internal.ExecutableImage; import jdk.tools.jlink.plugin.ResourcePool; import jdk.tools.jlink.plugin.ResourcePoolEntry; @@ -149,20 +148,6 @@ Files.createDirectories(mdir); } - private void storeRelease(ResourcePool pool) throws IOException { - Properties props = new Properties(); - Optional release = pool.findEntry("/java.base/release"); - if (release.isPresent()) { - try (InputStream is = release.get().content()) { - props.load(is); - } - } - File r = new File(root.toFile(), "release"); - try (FileOutputStream fo = new FileOutputStream(r)) { - props.store(fo, null); - } - } - @Override public void storeFiles(ResourcePool files) { try { @@ -180,9 +165,6 @@ throw new PluginException("TargetPlatform attribute is missing for java.base module"); } - // store 'release' file - storeRelease(files); - Path bin = root.resolve(BIN_DIRNAME); // check any duplicated resource files @@ -373,13 +355,22 @@ return Paths.get(LEGAL_DIRNAME, entryToFileName(entry)); case TOP: return Paths.get(entryToFileName(entry)); - case OTHER: - return Paths.get("other", entryToFileName(entry)); default: throw new IllegalArgumentException("invalid type: " + entry); } } + private void storeRelease(ResourcePoolEntry release) throws IOException { + Properties props = new Properties(); + try (InputStream is = release.content()) { + props.load(is); + } + File r = new File(root.toFile(), "release"); + try (FileOutputStream fo = new FileOutputStream(r)) { + props.store(fo, null); + } + } + private void accept(ResourcePoolEntry file) throws IOException { if (file.linkedTarget() != null && file.type() != Type.LEGAL_NOTICE) { throw new UnsupportedOperationException("symbolic link not implemented: " + file); @@ -412,19 +403,9 @@ } break; case TOP: - break; - case OTHER: - String filename = entryToFileName(file); - if (file instanceof SymImageFile) { - SymImageFile sym = (SymImageFile) file; - Path target = root.resolve(sym.getTargetPath()); - if (!Files.exists(target)) { - throw new IOException("Sym link target " + target - + " doesn't exist"); - } - writeSymEntry(root.resolve(filename), target); - } else { - writeEntry(in, root.resolve(filename)); + // only TOP file as of now is "release" file. + if ("/java.base/release".equals(file.path())) { + storeRelease(file); } break; default: --- old/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ArchiveEntryResourcePoolEntry.java 2016-12-14 22:22:58.000000000 +0530 +++ new/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ArchiveEntryResourcePoolEntry.java 2016-12-14 22:22:58.000000000 +0530 @@ -80,7 +80,7 @@ case NATIVE_LIB: return Type.NATIVE_LIB; default: - return ResourcePoolEntry.Type.OTHER; + throw new IllegalArgumentException("Unknown archive entry type: " + entry.type()); } } } --- old/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ResourcePoolEntry.java 2016-12-14 22:22:59.000000000 +0530 +++ new/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ResourcePoolEntry.java 2016-12-14 22:22:59.000000000 +0530 @@ -58,7 +58,6 @@ * * * - * * */ public enum Type { @@ -69,8 +68,7 @@ MAN_PAGE, NATIVE_CMD, NATIVE_LIB, - TOP, - OTHER + TOP } /** --- old/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties 2016-12-14 22:23:00.000000000 +0530 +++ new/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties 2016-12-14 22:23:00.000000000 +0530 @@ -52,12 +52,6 @@ By default, all resources are compressed. You can express the set \n\ of resources to compress or not compress (use ^ for negation). -copy-files.argument== to copy to the image>. - -copy-files.description=\ -If files to copy are not absolute path, JDK home dir is used.\n\ -e.g.: /home/me/myfile.txt=somewhere/conf.txt - dedup-legal-notices.argument=[error-if-not-same-content] dedup-legal-notices.description=\ --- old/src/jdk.jlink/share/classes/module-info.java 2016-12-14 22:23:01.000000000 +0530 +++ new/src/jdk.jlink/share/classes/module-info.java 2016-12-14 22:23:01.000000000 +0530 @@ -36,7 +36,6 @@ jdk.tools.jlink.internal.Main.JlinkToolProvider; provides jdk.tools.jlink.plugin.Plugin with - jdk.tools.jlink.internal.plugins.FileCopierPlugin, jdk.tools.jlink.internal.plugins.StripDebugPlugin, jdk.tools.jlink.internal.plugins.ExcludePlugin, jdk.tools.jlink.internal.plugins.ExcludeFilesPlugin, --- old/test/tools/jlink/JLinkTest.java 2016-12-14 22:23:02.000000000 +0530 +++ new/test/tools/jlink/JLinkTest.java 2016-12-14 22:23:02.000000000 +0530 @@ -191,19 +191,6 @@ } { - // License files - Path file = Paths.get("LICENSE"); - Files.createFile(file); - String copied = "LICENSE"; - String[] arr = copied.split(","); - String[] copyFiles = new String[2]; - copyFiles[0] = "--copy-files"; - copyFiles[1] = file.toAbsolutePath().toString(); - Path imageDir = helper.generateDefaultImage(copyFiles, "composite2").assertSuccess(); - helper.checkImage(imageDir, "composite2", null, null, arr); - } - - { // List plugins StringWriter writer = new StringWriter(); PrintWriter pw = new PrintWriter(writer); --- old/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/FileCopierPlugin.java 2016-12-14 22:23:03.000000000 +0530 +++ /dev/null 2016-12-14 22:23:03.000000000 +0530 @@ -1,263 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.tools.jlink.internal.plugins; - -import java.io.File; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.file.FileVisitResult; -import java.nio.file.FileVisitor; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import jdk.tools.jlink.internal.PathResourcePoolEntry; -import jdk.tools.jlink.plugin.PluginException; -import jdk.tools.jlink.plugin.ResourcePool; -import jdk.tools.jlink.plugin.ResourcePoolBuilder; -import jdk.tools.jlink.plugin.ResourcePoolEntry; -import jdk.tools.jlink.plugin.Plugin; -import jdk.tools.jlink.internal.Utils; - -/** - * - * Copy files to image from various locations. - */ -public class FileCopierPlugin implements Plugin { - - public static final String NAME = "copy-files"; - - private static final class CopiedFile { - - Path source; - Path target; - } - private final List files = new ArrayList<>(); - - /** - * Symbolic link to another path. - */ - public static abstract class SymImageFile extends PathResourcePoolEntry { - - private final String targetPath; - - public SymImageFile(String targetPath, String module, String path, - ResourcePoolEntry.Type type, Path file) { - super(module, path, type, file); - this.targetPath = targetPath; - } - - public String getTargetPath() { - return targetPath; - } - } - - private static final class SymImageFileImpl extends SymImageFile { - - public SymImageFileImpl(String targetPath, Path file, String module, - String path, ResourcePoolEntry.Type type) { - super(targetPath, module, path, type, file); - } - } - - private static final class DirectoryCopy implements FileVisitor { - - private final Path source; - private final ResourcePoolBuilder pool; - private final String targetDir; - private final List symlinks = new ArrayList<>(); - - DirectoryCopy(Path source, ResourcePoolBuilder pool, String targetDir) { - this.source = source; - this.pool = pool; - this.targetDir = targetDir; - } - - @Override - public FileVisitResult preVisitDirectory(Path dir, - BasicFileAttributes attrs) throws IOException { - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFile(Path file, - BasicFileAttributes attrs) throws IOException { - Objects.requireNonNull(file); - Objects.requireNonNull(attrs); - String path = targetDir + "/" + source.relativize(file); - if (attrs.isSymbolicLink()) { - Path symTarget = Files.readSymbolicLink(file); - if (!Files.exists(symTarget)) { - // relative to file parent? - Path parent = file.getParent(); - if (parent != null) { - symTarget = parent.resolve(symTarget); - } - } - if (!Files.exists(symTarget)) { - System.err.println("WARNING: Skipping sym link, target " - + Files.readSymbolicLink(file) + "not found"); - return FileVisitResult.CONTINUE; - } - SymImageFileImpl impl = new SymImageFileImpl(symTarget.toString(), - file, path, Objects.requireNonNull(file.getFileName()).toString(), - ResourcePoolEntry.Type.OTHER); - symlinks.add(impl); - } else { - addFile(pool, file, path); - } - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) - throws IOException { - if (exc != null) { - throw exc; - } - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFileFailed(Path file, IOException exc) - throws IOException { - throw exc; - } - } - - private static void addFile(ResourcePoolBuilder pool, Path file, String path) - throws IOException { - Objects.requireNonNull(pool); - Objects.requireNonNull(file); - Objects.requireNonNull(path); - ResourcePoolEntry impl = ResourcePoolEntry.create( - "/java.base/other/" + path, - ResourcePoolEntry.Type.OTHER, file); - try { - pool.add(impl); - } catch (Exception ex) { - throw new IOException(ex); - } - } - - @Override - public void configure(Map config) { - List arguments = Utils.parseList(config.get(NAME)); - if (arguments.isEmpty()) { - throw new RuntimeException("Invalid argument for " + NAME); - } - - String javahome = System.getProperty("java.home"); - for (String a : arguments) { - int i = a.indexOf("="); - CopiedFile cf = new CopiedFile(); - if (i == -1) { - Path file = Paths.get(a); - if (file.isAbsolute()) { - cf.source = file; - // The target is the image root directory. - cf.target = file.getFileName(); - } else { - file = new File(javahome, a).toPath(); - cf.source = file; - cf.target = Paths.get(a); - } - } else { - String target = a.substring(i + 1); - String f = a.substring(0, i); - Path file = Paths.get(f); - if (file.isAbsolute()) { - cf.source = file; - } else { - cf.source = new File(javahome, - file.toFile().getPath()).toPath(); - } - cf.target = Paths.get(target); - } - if (!Files.exists(cf.source)) { - System.err.println("Skipping file " + cf.source - + ", it doesn't exist"); - } else { - files.add(cf); - } - } - } - - @Override - public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) { - in.transformAndCopy((file) -> { - return file; - }, out); - - // Add new files. - try { - for (CopiedFile file : files) { - if (Files.isRegularFile(file.source)) { - addFile(out, file.source, file.target.toString()); - } else if (Files.isDirectory(file.source)) { - DirectoryCopy dc = new DirectoryCopy(file.source, - out, file.target.toString()); - Files.walkFileTree(file.source, dc); - // Add symlinks after actual content - for (SymImageFile imf : dc.symlinks) { - try { - out.add(imf); - } catch (Exception ex) { - throw new PluginException(ex); - } - } - } - } - } catch (IOException ex) { - throw new UncheckedIOException(ex); - } - - return out.build(); - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getDescription() { - return PluginsResourceBundle.getDescription(NAME); - } - - @Override - public boolean hasArguments() { - return true; - } - - @Override - public String getArgumentsDescription() { - return PluginsResourceBundle.getArgument(NAME); - } -} --- old/test/tools/jlink/plugins/FileCopierPluginTest.java 2016-12-14 22:23:03.000000000 +0530 +++ /dev/null 2016-12-14 22:23:03.000000000 +0530 @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @summary Test files copy plugin - * @author Jean-Francois Denise - * @modules jdk.jlink/jdk.tools.jlink.internal - * jdk.jlink/jdk.tools.jlink.builder - * jdk.jlink/jdk.tools.jlink.internal.plugins - * @run main FileCopierPluginTest - */ - -import java.io.File; -import java.net.URI; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import jdk.tools.jlink.internal.ResourcePoolManager; -import jdk.tools.jlink.builder.DefaultImageBuilder; - -import jdk.tools.jlink.internal.plugins.FileCopierPlugin; -import jdk.tools.jlink.plugin.PluginException; -import jdk.tools.jlink.plugin.ResourcePoolEntry; -import jdk.tools.jlink.plugin.ResourcePool; - -public class FileCopierPluginTest { - - public static void main(String[] args) throws Exception { - new FileCopierPluginTest().test(); - } - - /** - * 3 cases - Absolute, no target ==> copy in image root dir - Absolute and - * target ==> copy in image root dir/target - Relative ==> copy from JDK - * home dir. - * - * @throws Exception - */ - public void test() throws Exception { - FileCopierPlugin plug = new FileCopierPlugin(); - String content = "You \n should \n be \bthere.\n"; - String name = "sample.txt"; - File src = new File("src"); - src.mkdir(); - // Need a fake bin - File bin = new File("bin"); - bin.mkdir(); - - File txt = new File(src, name); - txt.createNewFile(); - - String target = "target" + File.separator + name; - Files.write(txt.toPath(), content.getBytes()); - File lic = new File(System.getProperty("java.home"), "LICENSE.txt"); - StringBuilder builder = new StringBuilder(); - int expected = lic.exists() ? 4 : 3; - if (lic.exists()) { - builder.append("LICENSE.txt,"); - } - builder.append(txt.getAbsolutePath()+","); - builder.append(txt.getAbsolutePath() + "=" + target+","); - builder.append(src.getAbsolutePath() + "=src2"); - - Map conf = new HashMap<>(); - conf.put(FileCopierPlugin.NAME, builder.toString()); - plug.configure(conf); - ResourcePoolManager poolMgr = new ResourcePoolManager(); - // java.base/module-info.class is used to add "release" file - // We read it from jrt-fs and add a ResourcePoolEntry - poolMgr.add( - ResourcePoolEntry.create("/java.base/module-info.class", - ResourcePoolEntry.Type.CLASS_OR_RESOURCE, getJavaBaseModuleInfo())); - expected++; - ResourcePool pool = plug.transform( - new ResourcePoolManager().resourcePool(), - poolMgr.resourcePoolBuilder()); - if (pool.entryCount() != expected) { - throw new AssertionError("Wrong number of added files"); - } - pool.entries().forEach(f -> { - if (!f.type().equals(ResourcePoolEntry.Type.OTHER) && - !f.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)) { - throw new AssertionError("Invalid type " + f.type() - + " for file " + f.path()); - } - if (f.content() == null) { - throw new AssertionError("Null stream for file " + f.path()); - } - }); - Path root = new File(".").toPath(); - DefaultImageBuilder imgbuilder = new DefaultImageBuilder(root); - imgbuilder.storeFiles(pool); - - if (lic.exists()) { - File license = new File(root.toFile(), "LICENSE.txt"); - if (!license.exists() || license.length() == 0) { - throw new AssertionError("Invalid license file " - + license.getAbsoluteFile()); - } - } - - File sample1 = new File(root.toFile(), txt.getName()); - if (!sample1.exists() || sample1.length() == 0) { - throw new AssertionError("Invalide sample1 file " - + sample1.getAbsoluteFile()); - } - if (!new String(Files.readAllBytes(sample1.toPath())).equals(content)) { - throw new AssertionError("Invalid Content in sample1"); - } - - File sample2 = new File(root.toFile(), target); - if (!sample2.exists() || sample2.length() == 0) { - throw new AssertionError("Invalide sample2 file " - + sample2.getAbsoluteFile()); - } - if (!new String(Files.readAllBytes(sample2.toPath())).equals(content)) { - throw new AssertionError("Invalid Content in sample2"); - } - - File src2 = new File(root.toFile(), "src2"); - if (!src2.exists() || src2.list().length != 1) { - throw new AssertionError("Invalide src2 dir " - + src2.getAbsoluteFile()); - } - File f = src2.listFiles()[0]; - if (!f.getName().equals(txt.getName())) { - throw new AssertionError("Invalide file name in src2 dir " - + f.getAbsoluteFile()); - } - if (!new String(Files.readAllBytes(f.toPath())).equals(content)) { - throw new AssertionError("Invalid Content in src2 dir"); - } - } - - // read java.base/module-info.class from jrt-fs - private static Path getJavaBaseModuleInfo() { - return Paths.get(URI.create("jrt:/modules/java.base/module-info.class")); - } -}