< prev index next >

src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java

Print this page




 113         public Set<String> getModules() {
 114             return modules;
 115         }
 116 
 117         @Override
 118         public List<String> getExecutionArgs() {
 119             return args;
 120         }
 121 
 122         @Override
 123         public void storeLaunchArgs(List<String> args) {
 124             try {
 125                 patchScripts(this, args);
 126             } catch (IOException ex) {
 127                 throw new UncheckedIOException(ex);
 128             }
 129         }
 130     }
 131 
 132     private final Path root;

 133     private final Path mdir;
 134     private final Set<String> modules = new HashSet<>();
 135     private String targetOsName;
 136 
 137     /**
 138      * Default image builder constructor.
 139      *
 140      * @param root The image root directory.
 141      * @throws IOException
 142      */
 143     public DefaultImageBuilder(Path root) throws IOException {
 144         Objects.requireNonNull(root);
 145 
 146         this.root = root;
 147         this.mdir = root.resolve("lib");
 148         Files.createDirectories(mdir);
 149     }
 150 
 151     @Override
 152     public void storeFiles(ResourcePool files) {
 153         try {
 154             // populate targetOsName field up-front because it's used elsewhere.
 155             Optional<ResourcePoolModule> javaBase = files.moduleView().findModule("java.base");
 156             javaBase.ifPresent(mod -> {
 157                 // fill release information available from transformed "java.base" module!
 158                 ModuleDescriptor desc = mod.descriptor();
 159                 desc.osName().ifPresent(s -> {
 160                     this.targetOsName = s;
 161                 });
 162             });
 163 
 164             if (this.targetOsName == null) {
 165                 throw new PluginException("TargetPlatform attribute is missing for java.base module");
 166             }


 218                 Path lib = root.resolve(LIB_DIRNAME);
 219                 if (Files.isDirectory(lib)) {
 220                     Files.find(lib, 2, (path, attrs) -> {
 221                         return path.getFileName().toString().equals("jspawnhelper")
 222                                 || path.getFileName().toString().equals("jexec");
 223                     }).forEach(this::setExecutable);
 224                 }
 225 
 226                 // read-only legal notices/license files
 227                 Path legal = root.resolve(LEGAL_DIRNAME);
 228                 if (Files.isDirectory(legal)) {
 229                     Files.find(legal, 2, (path, attrs) -> {
 230                         return attrs.isRegularFile();
 231                     }).forEach(this::setReadOnly);
 232                 }
 233             }
 234 
 235             // If native files are stripped completely, <root>/bin dir won't exist!
 236             // So, don't bother generating launcher scripts.
 237             if (Files.isDirectory(bin)) {
 238                  prepareApplicationFiles(files, modules);
 239             }
 240         } catch (IOException ex) {
 241             throw new PluginException(ex);
 242         }
 243     }
 244 
 245     /**
 246      * Generates launcher scripts.
 247      *
 248      * @param imageContent The image content.
 249      * @param modules The set of modules that the runtime image contains.
 250      * @throws IOException
 251      */
 252     protected void prepareApplicationFiles(ResourcePool imageContent, Set<String> modules) throws IOException {
 253         // generate launch scripts for the modules with a main class
 254         for (String module : modules) {













 255             String path = "/" + module + "/module-info.class";
 256             Optional<ResourcePoolEntry> res = imageContent.findEntry(path);
 257             if (!res.isPresent()) {
 258                 throw new IOException("module-info.class not found for " + module + " module");
 259             }
 260             Optional<String> mainClass;
 261             ByteArrayInputStream stream = new ByteArrayInputStream(res.get().contentBytes());
 262             mainClass = ModuleDescriptor.read(stream).mainClass();
 263             if (mainClass.isPresent()) {
 264                 Path cmd = root.resolve("bin").resolve(module);











 265                 // generate shell script for Unix platforms
 266                 StringBuilder sb = new StringBuilder();
 267                 sb.append("#!/bin/sh")
 268                         .append("\n");
 269                 sb.append("JLINK_VM_OPTIONS=")
 270                         .append("\n");
 271                 sb.append("DIR=`dirname $0`")
 272                         .append("\n");
 273                 sb.append("$DIR/java $JLINK_VM_OPTIONS -m ")
 274                         .append(module).append('/')
 275                         .append(mainClass.get())
 276                         .append(" $@\n");
 277 
 278                 try (BufferedWriter writer = Files.newBufferedWriter(cmd,
 279                         StandardCharsets.ISO_8859_1,
 280                         StandardOpenOption.CREATE_NEW)) {
 281                     writer.write(sb.toString());
 282                 }
 283                 if (root.resolve("bin").getFileSystem()
 284                         .supportedFileAttributeViews().contains("posix")) {
 285                     setExecutable(cmd);
 286                 }
 287                 // generate .bat file for Windows
 288                 if (isWindows()) {
 289                     Path bat = root.resolve(BIN_DIRNAME).resolve(module + ".bat");
 290                     sb = new StringBuilder();
 291                     sb.append("@echo off")
 292                             .append("\r\n");
 293                     sb.append("set JLINK_VM_OPTIONS=")
 294                             .append("\r\n");
 295                     sb.append("set DIR=%~dp0")
 296                             .append("\r\n");
 297                     sb.append("\"%DIR%\\java\" %JLINK_VM_OPTIONS% -m ")
 298                             .append(module).append('/')
 299                             .append(mainClass.get())
 300                             .append(" %*\r\n");
 301 
 302                     try (BufferedWriter writer = Files.newBufferedWriter(bat,
 303                             StandardCharsets.ISO_8859_1,
 304                             StandardOpenOption.CREATE_NEW)) {
 305                         writer.write(sb.toString());
 306                     }
 307                 }


 308             }
 309         }
 310     }
 311 
 312     @Override
 313     public DataOutputStream getJImageOutputStream() {
 314         try {
 315             Path jimageFile = mdir.resolve(BasicImageWriter.MODULES_IMAGE_NAME);
 316             OutputStream fos = Files.newOutputStream(jimageFile);
 317             BufferedOutputStream bos = new BufferedOutputStream(fos);
 318             return new DataOutputStream(bos);
 319         } catch (IOException ex) {
 320             throw new UncheckedIOException(ex);
 321         }
 322     }
 323 
 324     /**
 325      * Returns the file name of this entry
 326      */
 327     private String entryToFileName(ResourcePoolEntry entry) {




 113         public Set<String> getModules() {
 114             return modules;
 115         }
 116 
 117         @Override
 118         public List<String> getExecutionArgs() {
 119             return args;
 120         }
 121 
 122         @Override
 123         public void storeLaunchArgs(List<String> args) {
 124             try {
 125                 patchScripts(this, args);
 126             } catch (IOException ex) {
 127                 throw new UncheckedIOException(ex);
 128             }
 129         }
 130     }
 131 
 132     private final Path root;
 133     private final Map<String, String> launchers;
 134     private final Path mdir;
 135     private final Set<String> modules = new HashSet<>();
 136     private String targetOsName;
 137 
 138     /**
 139      * Default image builder constructor.
 140      *
 141      * @param root The image root directory.
 142      * @throws IOException
 143      */
 144     public DefaultImageBuilder(Path root, Map<String, String> launchers) throws IOException {
 145         this.root = Objects.requireNonNull(root);
 146         this.launchers = Objects.requireNonNull(launchers);

 147         this.mdir = root.resolve("lib");
 148         Files.createDirectories(mdir);
 149     }
 150 
 151     @Override
 152     public void storeFiles(ResourcePool files) {
 153         try {
 154             // populate targetOsName field up-front because it's used elsewhere.
 155             Optional<ResourcePoolModule> javaBase = files.moduleView().findModule("java.base");
 156             javaBase.ifPresent(mod -> {
 157                 // fill release information available from transformed "java.base" module!
 158                 ModuleDescriptor desc = mod.descriptor();
 159                 desc.osName().ifPresent(s -> {
 160                     this.targetOsName = s;
 161                 });
 162             });
 163 
 164             if (this.targetOsName == null) {
 165                 throw new PluginException("TargetPlatform attribute is missing for java.base module");
 166             }


 218                 Path lib = root.resolve(LIB_DIRNAME);
 219                 if (Files.isDirectory(lib)) {
 220                     Files.find(lib, 2, (path, attrs) -> {
 221                         return path.getFileName().toString().equals("jspawnhelper")
 222                                 || path.getFileName().toString().equals("jexec");
 223                     }).forEach(this::setExecutable);
 224                 }
 225 
 226                 // read-only legal notices/license files
 227                 Path legal = root.resolve(LEGAL_DIRNAME);
 228                 if (Files.isDirectory(legal)) {
 229                     Files.find(legal, 2, (path, attrs) -> {
 230                         return attrs.isRegularFile();
 231                     }).forEach(this::setReadOnly);
 232                 }
 233             }
 234 
 235             // If native files are stripped completely, <root>/bin dir won't exist!
 236             // So, don't bother generating launcher scripts.
 237             if (Files.isDirectory(bin)) {
 238                  prepareApplicationFiles(files);
 239             }
 240         } catch (IOException ex) {
 241             throw new PluginException(ex);
 242         }
 243     }
 244 
 245     /**
 246      * Generates launcher scripts.
 247      *
 248      * @param imageContent The image content.

 249      * @throws IOException
 250      */
 251     protected void prepareApplicationFiles(ResourcePool imageContent) throws IOException {
 252         // generate launch scripts for the modules with a main class
 253         for (Map.Entry<String, String> entry : launchers.entrySet()) {
 254             String launcherEntry = entry.getValue();
 255             int slashIdx = launcherEntry.indexOf("/");
 256             String module, mainClassName;
 257             if (slashIdx == -1) {
 258                 module = launcherEntry;
 259                 mainClassName = null;
 260             } else {
 261                 module = launcherEntry.substring(0, slashIdx);
 262                 assert !module.isEmpty();
 263                 mainClassName = launcherEntry.substring(slashIdx + 1);
 264                 assert !mainClassName.isEmpty();
 265             }
 266 
 267             String path = "/" + module + "/module-info.class";
 268             Optional<ResourcePoolEntry> res = imageContent.findEntry(path);
 269             if (!res.isPresent()) {
 270                 throw new IOException("module-info.class not found for " + module + " module");
 271             }

 272             ByteArrayInputStream stream = new ByteArrayInputStream(res.get().contentBytes());
 273             Optional<String> mainClass = ModuleDescriptor.read(stream).mainClass();
 274             if (mainClassName == null && mainClass.isPresent()) {
 275                 mainClassName = mainClass.get();
 276             }
 277 
 278             if (mainClassName != null) {
 279                 // make sure main class exists!
 280                 if (!imageContent.findEntry("/" + module + "/" +
 281                         mainClassName.replace('.', '/') + ".class").isPresent()) {
 282                     throw new RuntimeException(module + " does not have main class: " + mainClassName);
 283                 }
 284 
 285                 String launcherFile = entry.getKey();
 286                 Path cmd = root.resolve("bin").resolve(launcherFile);
 287                 // generate shell script for Unix platforms
 288                 StringBuilder sb = new StringBuilder();
 289                 sb.append("#!/bin/sh")
 290                         .append("\n");
 291                 sb.append("JLINK_VM_OPTIONS=")
 292                         .append("\n");
 293                 sb.append("DIR=`dirname $0`")
 294                         .append("\n");
 295                 sb.append("$DIR/java $JLINK_VM_OPTIONS -m ")
 296                         .append(module).append('/')
 297                         .append(mainClassName)
 298                         .append(" $@\n");
 299 
 300                 try (BufferedWriter writer = Files.newBufferedWriter(cmd,
 301                         StandardCharsets.ISO_8859_1,
 302                         StandardOpenOption.CREATE_NEW)) {
 303                     writer.write(sb.toString());
 304                 }
 305                 if (root.resolve("bin").getFileSystem()
 306                         .supportedFileAttributeViews().contains("posix")) {
 307                     setExecutable(cmd);
 308                 }
 309                 // generate .bat file for Windows
 310                 if (isWindows()) {
 311                     Path bat = root.resolve(BIN_DIRNAME).resolve(launcherFile + ".bat");
 312                     sb = new StringBuilder();
 313                     sb.append("@echo off")
 314                             .append("\r\n");
 315                     sb.append("set JLINK_VM_OPTIONS=")
 316                             .append("\r\n");
 317                     sb.append("set DIR=%~dp0")
 318                             .append("\r\n");
 319                     sb.append("\"%DIR%\\java\" %JLINK_VM_OPTIONS% -m ")
 320                             .append(module).append('/')
 321                             .append(mainClassName)
 322                             .append(" %*\r\n");
 323 
 324                     try (BufferedWriter writer = Files.newBufferedWriter(bat,
 325                             StandardCharsets.ISO_8859_1,
 326                             StandardOpenOption.CREATE_NEW)) {
 327                         writer.write(sb.toString());
 328                     }
 329                 }
 330             } else {
 331                 throw new IllegalArgumentException(module + " doesn't contain main class & main not specified in command line");
 332             }
 333         }
 334     }
 335 
 336     @Override
 337     public DataOutputStream getJImageOutputStream() {
 338         try {
 339             Path jimageFile = mdir.resolve(BasicImageWriter.MODULES_IMAGE_NAME);
 340             OutputStream fos = Files.newOutputStream(jimageFile);
 341             BufferedOutputStream bos = new BufferedOutputStream(fos);
 342             return new DataOutputStream(bos);
 343         } catch (IOException ex) {
 344             throw new UncheckedIOException(ex);
 345         }
 346     }
 347 
 348     /**
 349      * Returns the file name of this entry
 350      */
 351     private String entryToFileName(ResourcePoolEntry entry) {


< prev index next >