ReleaseInfoPlugin.java revision 17000:fa3c4a60a616
1219820Sjeff/* 2219820Sjeff * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3219820Sjeff * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4219820Sjeff * 5219820Sjeff * This code is free software; you can redistribute it and/or modify it 6219820Sjeff * under the terms of the GNU General Public License version 2 only, as 7219820Sjeff * published by the Free Software Foundation. Oracle designates this 8219820Sjeff * particular file as subject to the "Classpath" exception as provided 9219820Sjeff * by Oracle in the LICENSE file that accompanied this code. 10219820Sjeff * 11219820Sjeff * This code is distributed in the hope that it will be useful, but WITHOUT 12219820Sjeff * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13219820Sjeff * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14219820Sjeff * version 2 for more details (a copy is included in the LICENSE file that 15219820Sjeff * accompanied this code). 16219820Sjeff * 17219820Sjeff * You should have received a copy of the GNU General Public License version 18219820Sjeff * 2 along with this work; if not, write to the Free Software Foundation, 19219820Sjeff * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20219820Sjeff * 21219820Sjeff * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22219820Sjeff * or visit www.oracle.com if you need additional information or have any 23219820Sjeff * questions. 24219820Sjeff */ 25219820Sjeffpackage jdk.tools.jlink.internal.plugins; 26219820Sjeff 27219820Sjeffimport java.io.ByteArrayOutputStream; 28219820Sjeffimport java.io.FileInputStream; 29219820Sjeffimport java.io.IOException; 30219820Sjeffimport java.io.PrintWriter; 31219820Sjeffimport java.io.UncheckedIOException; 32219820Sjeffimport java.lang.module.ModuleDescriptor; 33219820Sjeffimport java.util.EnumSet; 34219820Sjeffimport java.util.HashMap; 35219820Sjeffimport java.util.Map; 36219820Sjeffimport java.util.Optional; 37219820Sjeffimport java.util.Properties; 38219820Sjeffimport java.util.Set; 39219820Sjeffimport java.util.function.Function; 40219820Sjeffimport java.util.stream.Collectors; 41219820Sjeffimport jdk.tools.jlink.internal.ModuleSorter; 42219820Sjeffimport jdk.tools.jlink.internal.Utils; 43255932Salfredimport jdk.tools.jlink.plugin.ResourcePool; 44219820Sjeffimport jdk.tools.jlink.plugin.ResourcePoolBuilder; 45255932Salfredimport jdk.tools.jlink.plugin.ResourcePoolEntry; 46255932Salfredimport jdk.tools.jlink.plugin.ResourcePoolModule; 47255932Salfredimport jdk.tools.jlink.plugin.Plugin; 48255932Salfred 49255932Salfred/** 50255932Salfred * This plugin adds/deletes information for 'release' file. 51255932Salfred */ 52255932Salfredpublic final class ReleaseInfoPlugin implements Plugin { 53255932Salfred // option name 54255932Salfred public static final String NAME = "release-info"; 55255932Salfred public static final String KEYS = "keys"; 56255932Salfred private final Map<String, String> release = new HashMap<>(); 57255932Salfred 58255932Salfred @Override 59255932Salfred public Category getType() { 60255932Salfred return Category.METAINFO_ADDER; 61255932Salfred } 62255932Salfred 63255932Salfred @Override 64255932Salfred public String getName() { 65255932Salfred return NAME; 66255932Salfred } 67255932Salfred 68255932Salfred @Override 69255932Salfred public String getDescription() { 70255932Salfred return PluginsResourceBundle.getDescription(NAME); 71255932Salfred } 72255932Salfred 73255932Salfred @Override 74255932Salfred public Set<State> getState() { 75255932Salfred return EnumSet.of(State.AUTO_ENABLED, State.FUNCTIONAL); 76255932Salfred } 77255932Salfred 78255932Salfred @Override 79255932Salfred public boolean hasArguments() { 80255932Salfred return true; 81255932Salfred } 82255932Salfred 83255932Salfred @Override 84255932Salfred public String getArgumentsDescription() { 85219820Sjeff return PluginsResourceBundle.getArgument(NAME); 86255932Salfred } 87219820Sjeff 88219820Sjeff @Override 89255932Salfred public void configure(Map<String, String> config) { 90255932Salfred String operation = config.get(NAME); 91219820Sjeff if (operation == null) { 92219820Sjeff return; 93255932Salfred } 94219820Sjeff 95219820Sjeff switch (operation) { 96255932Salfred case "add": { 97255932Salfred // leave it to open-ended! source, java_version, java_full_version 98219820Sjeff // can be passed via this option like: 99255932Salfred // 100255932Salfred // --release-info add:build_type=fastdebug,source=openjdk,java_version=9 101255932Salfred // and put whatever value that was passed in command line. 102255932Salfred 103255932Salfred config.keySet().stream() 104255932Salfred .filter(s -> !NAME.equals(s)) 105255932Salfred .forEach(s -> release.put(s, config.get(s))); 106255932Salfred } 107255932Salfred break; 108255932Salfred 109255932Salfred case "del": { 110219820Sjeff // --release-info del:keys=openjdk,java_version 111219820Sjeff Utils.parseList(config.get(KEYS)).stream().forEach((k) -> { 112219820Sjeff release.remove(k); 113255932Salfred }); 114255932Salfred } 115255932Salfred break; 116219820Sjeff 117219820Sjeff default: { 118219820Sjeff // --release-info <file> 119219820Sjeff Properties props = new Properties(); 120219820Sjeff try (FileInputStream fis = new FileInputStream(operation)) { 121219820Sjeff props.load(fis); 122219820Sjeff } catch (IOException exp) { 123255932Salfred throw new UncheckedIOException(exp); 124255932Salfred } 125255932Salfred props.forEach((k, v) -> release.put(k.toString(), v.toString())); 126255932Salfred } 127255932Salfred break; 128255932Salfred } 129255932Salfred } 130255932Salfred 131255932Salfred @Override 132255932Salfred public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) { 133255932Salfred in.transformAndCopy(Function.identity(), out); 134255932Salfred 135255932Salfred Optional<ResourcePoolModule> javaBase = in.moduleView().findModule("java.base"); 136255932Salfred javaBase.ifPresent(mod -> { 137255932Salfred // fill release information available from transformed "java.base" module! 138219820Sjeff ModuleDescriptor desc = mod.descriptor(); 139255932Salfred desc.version().ifPresent(s -> release.put("JAVA_VERSION", 140255932Salfred quote(parseVersion(s.toString())))); 141255932Salfred desc.version().ifPresent(s -> release.put("JAVA_FULL_VERSION", 142255932Salfred quote(s.toString()))); 143255932Salfred 144255932Salfred release.put("OS_NAME", quote(mod.osName())); 145255932Salfred release.put("OS_ARCH", quote(mod.osArch())); 146255932Salfred }); 147255932Salfred 148255932Salfred // put topological sorted module names separated by space 149255932Salfred release.put("MODULES", new ModuleSorter(in.moduleView()) 150255932Salfred .sorted().map(ResourcePoolModule::name) 151255932Salfred .collect(Collectors.joining(" ", "\"", "\""))); 152255932Salfred 153255932Salfred // create a TOP level ResourcePoolEntry for "release" file. 154255932Salfred out.add(ResourcePoolEntry.create("/java.base/release", 155255932Salfred ResourcePoolEntry.Type.TOP, releaseFileContent())); 156255932Salfred return out.build(); 157255932Salfred } 158255932Salfred 159255932Salfred // Parse version string and return a string that includes only version part 160255932Salfred // leaving "pre", "build" information. See also: java.lang.Runtime.Version. 161255932Salfred private static String parseVersion(String str) { 162255932Salfred return Runtime.Version.parse(str) 163255932Salfred .version() 164255932Salfred .stream() 165255932Salfred .map(Object::toString) 166255932Salfred .collect(Collectors.joining(".")); 167255932Salfred } 168255932Salfred 169255932Salfred private static String quote(String str) { 170255932Salfred return "\"" + str + "\""; 171255932Salfred } 172255932Salfred 173255932Salfred private byte[] releaseFileContent() { 174255932Salfred ByteArrayOutputStream baos = new ByteArrayOutputStream(); 175255932Salfred try (PrintWriter pw = new PrintWriter(baos)) { 176255932Salfred release.entrySet().stream() 177255932Salfred .sorted(Map.Entry.comparingByKey()) 178255932Salfred .forEach(e -> pw.format("%s=%s%n", e.getKey(), e.getValue())); 179255932Salfred } 180255932Salfred return baos.toByteArray(); 181255932Salfred } 182255932Salfred} 183255932Salfred