Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/make/src/classes/build/tools/generatenimbus/Generator.java
32287 views
/*1* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package build.tools.generatenimbus;2526import java.io.*;27import java.util.HashMap;28import java.util.Map;29import javax.xml.bind.JAXBContext;30import javax.xml.bind.Unmarshaller;3132/**33* Generates the various Java artifacts based on a SynthModel.34* <p/>35* Generated source files are split up among two different locations. There are those source files that are meant to be36* edited (generally, only the LookAndFeel class itself) and those that are autogenerated (everything else).37* <p/>38* All autogenerated files are placed in "buildPackageRoot" and are package private. A LAF author (one who has access to39* the generated sources) will be able to access any of the generated classes. Those referencing the library, however,40* will only be able to access the main LookAndFeel class itself (since everything else is package private).41*42* @author Richard Bair43* @author Jasper Potts44*/45public class Generator {46private static Generator instance;4748/** A map of variables that are used for variable substitution in the template files. */49private Map<String, String> variables;50private boolean full = false;51private File buildPackageRoot;52private String packageNamePrefix;53private String lafName;54private SynthModel model;5556/**57* MAIN APPLICATION58* <p/>59* This is for using the generator as part of the java build process60*61* @param args The commandline arguments62*/63public static void main(String[] args) throws Exception {64if (args.length == 0 || (args.length % 2) != 0) {65System.out.println("Usage: generator [-options]\n" +66" -full <true|false> True if we should build the whole LAF or false for building just states and painters.\n" +67" -skinFile <value> Path to the skin.laf file for the LAF to be generated from.\n" +68" -buildDir <value> The directory beneath which the build-controlled artifacts (such as the Painters) should\n" +69" be placed. This is the root directory beneath which the necessary packages and source\n" +70" files will be created.\n" +71" -resourcesDir <value> The resources directory containing templates and images.\n" +72" -packagePrefix <value> The package name associated with this synth look and feel. For example,\n" +73" \"org.mypackage.mylaf\"\n" +74" -lafName <value> The name of the laf, such as \"MyLAF\".\n");75} else {76boolean full = false;77File skinFile = new File(System.getProperty("user.dir"));78File buildDir = new File(System.getProperty("user.dir"));79File resourcesDir = new File(System.getProperty("user.dir"));80String packagePrefix = "org.mypackage.mylaf";81String lafName = "MyLAF";82for (int i = 0; i < args.length; i += 2) {83String key = args[i].trim().toLowerCase();84String value = args[i + 1].trim();85if ("-full".equals(key)) {86full = Boolean.parseBoolean(value);87} else if ("-skinfile".equals(key)) {88skinFile = new File(value);89} else if ("-builddir".equals(key)) {90buildDir = new File(value);91} else if ("-resourcesdir".equals(key)) {92resourcesDir = new File(value);93} else if ("-packageprefix".equals(key)) {94packagePrefix = value;95} else if ("-lafname".equals(key)) {96lafName = value;97}98}99System.out.println("### GENERATING LAF CODE ################################");100System.out.println(" full :" + full);101System.out.println(" skinFile :" + skinFile.getAbsolutePath());102System.out.println(" buildDir :" + buildDir.getAbsolutePath());103System.out.println(" resourcesDir :" + resourcesDir.getAbsolutePath());104System.out.println(" packagePrefix :" +packagePrefix);105System.out.println(" lafName :" +lafName);106107JAXBContext ctx = JAXBContext.newInstance("build.tools.generatenimbus");108Unmarshaller u = ctx.createUnmarshaller();109SynthModel model = (SynthModel) u.unmarshal(skinFile);110Generator.init(full, buildDir, packagePrefix, lafName, model);111Generator.getInstance().generate();112}113}114115/**116* Creates a new Generator, capable of outputting the source code artifacts related to a given SynthModel. It is117* capable of generating the one-time artifacts in addition to the regeneration of build-controlled artifacts.118*119* @param full True if we should build the whole LAF or false for building just states and painters.120* @param buildDir The directory beneath which the build-controlled artifacts (such as the Painters) should121* be placed. This is the root directory beneath which the necessary packages and source122* files will be created.123* @param srcDir The directory beneath which the normal user-controlled artifacts (such as the core124* LookAndFeel file) should be placed. These are one-time generated files. This is the root125* directory beneath which the necessary packages and source files will be created.126* @param packageNamePrefix The package name associated with this synth look and feel. For example,127* org.mypackage.mylaf128* @param lafName The name of the laf, such as MyLAF.129* @param model The actual SynthModel to base these generated files on.130*/131private Generator(boolean full, File buildDir,132String packageNamePrefix, String lafName, SynthModel model) {133this.full = full;134//validate the input variables135if (packageNamePrefix == null) {136throw new IllegalArgumentException("You must specify a package name prefix");137}138if (buildDir == null) {139throw new IllegalArgumentException("You must specify the build directory");140}141if (model == null) {142throw new IllegalArgumentException("You must specify the SynthModel");143}144if (lafName == null) {145throw new IllegalArgumentException("You must specify the name of the look and feel");146}147148//construct the map which is used to do variable substitution of the template149//files150variables = new HashMap<String, String>();151variables.put("PACKAGE", packageNamePrefix);152variables.put("LAF_NAME", lafName);153154//generate and save references to the package-root directories.155//(That is, given the buildDir and srcDir, generate references to the156//org.mypackage.mylaf subdirectories)157buildPackageRoot = new File(buildDir, packageNamePrefix.replaceAll("\\.", "\\/"));158buildPackageRoot.mkdirs();159160//save the variables161this.packageNamePrefix = packageNamePrefix;162this.lafName = lafName;163this.model = model;164}165166public static void init(boolean full, File buildDir,167String packageNamePrefix, String lafName, SynthModel model) {168instance = new Generator(full, buildDir, packageNamePrefix, lafName, model);169model.initStyles();170}171172public static Generator getInstance() {173return instance;174}175176public static Map<String, String> getVariables() {177return new HashMap<String, String>(instance.variables);178}179180public void generate() {181if (full) {182//create the LookAndFeel file183writeSrcFileImpl("LookAndFeel", variables, lafName + "LookAndFeel");184185writeSrcFileImpl("AbstractRegionPainter", variables);186writeSrcFileImpl("BlendingMode", variables);187writeSrcFileImpl("SynthPainterImpl", variables);188writeSrcFileImpl("IconImpl", variables, lafName + "Icon.java");189writeSrcFileImpl("StyleImpl", variables, lafName + "Style.java");190writeSrcFileImpl("Effect", variables);191writeSrcFileImpl("EffectUtils", variables);192writeSrcFileImpl("ShadowEffect", variables);193writeSrcFileImpl("DropShadowEffect", variables);194writeSrcFileImpl("InnerShadowEffect", variables);195writeSrcFileImpl("InnerGlowEffect", variables);196writeSrcFileImpl("OuterGlowEffect", variables);197writeSrcFileImpl("State", variables);198writeSrcFileImpl("ImageCache", variables);199writeSrcFileImpl("ImageScalingHelper", variables);200}201//next, populate the first set of ui defaults based on what is in the202//various palettes of the synth model203StringBuilder defBuffer = new StringBuilder();204StringBuilder styleBuffer = new StringBuilder();205model.write(defBuffer, styleBuffer, packageNamePrefix);206207Map<String, String> vars = getVariables();208vars.put("UI_DEFAULT_INIT", defBuffer.toString());209vars.put("STYLE_INIT", styleBuffer.toString());210writeSrcFile("Defaults", vars, lafName + "Defaults");211}212213private void writeSrcFileImpl(String name, Map<String, String> variables) {214writeSrcFileImpl(name, variables, name);215}216217private void writeSrcFileImpl(String templateName,218Map<String, String> variables, String outputName) {219PrintWriter out = null;220try {221InputStream stream = getClass().getResourceAsStream(222"resources/" + templateName + ".template");223TemplateReader in = new TemplateReader(variables, stream);224225out = new PrintWriter(new File(buildPackageRoot, outputName + ".java"));226String line = in.readLine();227while (line != null) {228out.println(line);229line = in.readLine();230}231} catch (IOException e) {232throw new RuntimeException("IOException in writer", e);233} finally {234if (out != null) out.close();235}236}237238public static void writeSrcFile(String templateName,239Map<String, String> variables, String outputName) {240instance.writeSrcFileImpl(templateName, variables, outputName);241}242243/** A BufferedReader implementation that automatically performs244* string replacements as needed.245*/246private static final class TemplateReader extends BufferedReader {247private Map<String, String> variables;248249TemplateReader(Map<String, String> variables, InputStream template) {250super(new InputStreamReader(template));251this.variables = variables;252}253254@Override public String readLine() throws IOException {255return substituteVariables(super.readLine());256}257258private String substituteVariables(String input) {259if (input == null) return null;260for (Map.Entry<String, String> variable : variables.entrySet()) {261input = input.replace("${" + variable.getKey() + "}", variable.getValue());262}263return input;264}265}266}267268269