Path: blob/master/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileProperties.java
41175 views
/*1* Copyright (c) 2012, 2016, 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*/2425package com.sun.tools.sjavac;2627import java.io.BufferedWriter;28import java.io.File;29import java.io.FileInputStream;30import java.io.FileOutputStream;31import java.io.IOException;32import java.io.OutputStreamWriter;33import java.io.PrintStream;34import java.io.Writer;35import java.net.URI;36import java.text.MessageFormat;37import java.util.ArrayList;38import java.util.Collections;39import java.util.HashSet;40import java.util.Iterator;41import java.util.List;42import java.util.Map;43import java.util.Properties;44import java.util.Set;4546import com.sun.tools.sjavac.comp.CompilationService;47import com.sun.tools.sjavac.options.Options;48import com.sun.tools.sjavac.pubapi.PubApi;4950/**51* Compile properties transform a properties file into a Java source file.52* Java has built in support for reading properties from either a text file53* in the source or a compiled java source file.54*55* <p><b>This is NOT part of any supported API.56* If you write code that depends on this, you do so at your own risk.57* This code and its internal interfaces are subject to change or58* deletion without notice.</b>59*/60public class CompileProperties implements Transformer {61// Any extra information passed from the command line, for example if:62// -tr .proppp=com.sun.tools.javac.smart.CompileProperties,sun.util.resources.LocaleNamesBundle63// then extra will be "sun.util.resources.LocaleNamesBundle"64String extra;6566public void setExtra(String e) {67extra = e;68}6970public void setExtra(Options a) {71}7273public boolean transform(CompilationService compilationService,74Map<String,Set<URI>> pkgSrcs,75Set<URI> visibleSrcs,76Map<String,Set<String>> oldPackageDependents,77URI destRoot,78Map<String,Set<URI>> packageArtifacts,79Map<String,Map<String, Set<String>>> packageDependencies,80Map<String,Map<String, Set<String>>> packageCpDependencies,81Map<String, PubApi> packagePublicApis,82Map<String, PubApi> dependencyPublicApis,83int debugLevel,84boolean incremental,85int numCores) {86boolean rc = true;87for (String pkgName : pkgSrcs.keySet()) {88String pkgNameF = Util.toFileSystemPath(pkgName);89for (URI u : pkgSrcs.get(pkgName)) {90File src = new File(u);91boolean r = compile(pkgName, pkgNameF, src, new File(destRoot), debugLevel,92packageArtifacts);93if (r == false) {94rc = false;95}96}97}98return rc;99}100101boolean compile(String pkgName, String pkgNameF, File src, File destRoot, int debugLevel,102Map<String,Set<URI>> packageArtifacts)103{104String superClass = "java.util.ListResourceBundle";105106if (extra != null) {107superClass = extra;108}109// Load the properties file.110Properties p = new Properties();111try {112p.load(new FileInputStream(src));113} catch (IOException e) {114Log.error("Error reading file "+src.getPath());115return false;116}117118// Calculate the name of the Java source file to be generated.119int dp = src.getName().lastIndexOf(".");120String classname = src.getName().substring(0,dp);121122// Sort the properties in increasing key order.123List<String> sortedKeys = new ArrayList<>();124for (Object key : p.keySet()) {125sortedKeys.add((String)key);126}127Collections.sort(sortedKeys);128Iterator<String> keys = sortedKeys.iterator();129130// Collect the properties into a string buffer.131StringBuilder data = new StringBuilder();132while (keys.hasNext()) {133String key = keys.next();134data.append(" { \"" + escape(key) + "\", \"" +135escape((String)p.get(key)) + "\" },\n");136}137138// Create dest file name. It is derived from the properties file name.139String destFilename = destRoot.getPath()+File.separator+pkgNameF+File.separator+classname+".java";140File dest = new File(destFilename);141142// Make sure the dest directories exist.143if (!dest.getParentFile().isDirectory()) {144if (!dest.getParentFile().mkdirs()) {145Log.error("Could not create the directory "+dest.getParentFile().getPath());146return false;147}148}149150Set<URI> as = packageArtifacts.get(pkgName);151if (as == null) {152as = new HashSet<>();153packageArtifacts.put(pkgName, as);154}155as.add(dest.toURI());156157if (dest.exists() && dest.lastModified() > src.lastModified()) {158// A generated file exists, and its timestamp is newer than the source.159// Assume that we do not need to regenerate the dest file!160// Thus we are done.161return true;162}163164String packageString = "package " + pkgNameF.replace(File.separatorChar,'.') + ";\n\n";165166Log.info("Compiling property file "+pkgNameF+File.separator+src.getName());167try (Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(dest)))) {168MessageFormat format = new MessageFormat(FORMAT);169writer.write(format.format(new Object[] { packageString, classname, superClass, data }));170} catch ( IOException e ) {171Log.error("Could not write file "+dest.getPath());172return false;173}174return true;175}176177private static final String FORMAT =178"{0}" +179"public final class {1} extends {2} '{'\n" +180" protected final Object[][] getContents() '{'\n" +181" return new Object[][] '{'\n" +182"{3}" +183" };\n" +184" }\n" +185"}\n";186187public static String escape(String theString) {188int len = theString.length();189StringBuilder outBuffer = new StringBuilder(len*2);190191for(int x=0; x<len; x++) {192char aChar = theString.charAt(x);193switch(aChar) {194case '\\':outBuffer.append('\\'); outBuffer.append('\\');195break;196case '\t':outBuffer.append('\\'); outBuffer.append('t');197break;198case '\n':outBuffer.append('\\'); outBuffer.append('n');199break;200case '\r':outBuffer.append('\\'); outBuffer.append('r');201break;202case '\f':outBuffer.append('\\'); outBuffer.append('f');203break;204default:205if ((aChar < 0x0020) || (aChar > 0x007e)) {206outBuffer.append('\\');207outBuffer.append('u');208outBuffer.append(toHex((aChar >> 12) & 0xF));209outBuffer.append(toHex((aChar >> 8) & 0xF));210outBuffer.append(toHex((aChar >> 4) & 0xF));211outBuffer.append(toHex( aChar & 0xF));212} else {213if (aChar == '"') {214outBuffer.append('\\');215}216outBuffer.append(aChar);217}218}219}220return outBuffer.toString();221}222223private static char toHex(int nibble) {224return hexDigit[(nibble & 0xF)];225}226227private static final char[] hexDigit = {228'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'229};230}231232233