src/share/classes/com/sun/tools/sjavac/CompileProperties.java

changeset 1570
f91144b7da75
parent 1504
22e417cdddee
child 2227
998b10c43157
equal deleted inserted replaced
1569:475eb15dfdad 1570:f91144b7da75
1 /*
2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.tools.sjavac;
27
28 import java.io.*;
29 import java.net.URI;
30 import java.text.MessageFormat;
31 import java.util.ArrayList;
32 import java.util.Collections;
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.Properties;
36 import java.util.Set;
37 import java.util.HashSet;
38 import java.util.Map;
39
40 /**
41 * Compile properties transform a properties file into a Java source file.
42 * Java has built in support for reading properties from either a text file
43 * in the source or a compiled java source file.
44 *
45 * <p><b>This is NOT part of any supported API.
46 * If you write code that depends on this, you do so at your own
47 * risk. This code and its internal interfaces are subject to change
48 * or deletion without notice.</b></p>
49 */
50 public class CompileProperties implements Transformer
51 {
52 // Any extra information passed from the command line, for example if:
53 // -tr .proppp=com.sun.tools.javac.smart.CompileProperties,sun.util.resources.LocaleNamesBundle
54 // then extra will be "sun.util.resources.LocaleNamesBundle"
55 String extra;
56
57 public void setExtra(String e) {
58 extra = e;
59 }
60
61 public void setExtra(String[] a) {
62 }
63
64 public boolean transform(Map<String,Set<URI>> pkgSrcs,
65 Set<URI> visibleSrcs,
66 Map<URI,Set<String>> visibleClasses,
67 Map<String,Set<String>> oldPackageDependents,
68 URI destRoot,
69 Map<String,Set<URI>> packageArtifacts,
70 Map<String,Set<String>> packageDependencies,
71 Map<String,String> packagePublicApis,
72 int debugLevel,
73 boolean incremental,
74 int numCores,
75 PrintStream out,
76 PrintStream err) {
77 boolean rc = true;
78 for (String pkgName : pkgSrcs.keySet()) {
79 String pkgNameF = Util.toFileSystemPath(pkgName);
80 for (URI u : pkgSrcs.get(pkgName)) {
81 File src = new File(u);
82 boolean r = compile(pkgName, pkgNameF, src, new File(destRoot), debugLevel,
83 packageArtifacts);
84 if (r == false) {
85 rc = false;
86 }
87 }
88 }
89 return rc;
90 }
91
92 boolean compile(String pkgName, String pkgNameF, File src, File destRoot, int debugLevel,
93 Map<String,Set<URI>> packageArtifacts)
94 {
95 String superClass = "java.util.ListResourceBundle";
96
97 if (extra != null) {
98 superClass = extra;
99 }
100 // Load the properties file.
101 Properties p = new Properties();
102 try {
103 p.load(new FileInputStream(src));
104 } catch (IOException e) {
105 Log.error("Error reading file "+src.getPath());
106 return false;
107 }
108
109 // Calculate the name of the Java source file to be generated.
110 int dp = src.getName().lastIndexOf(".");
111 String classname = src.getName().substring(0,dp);
112
113 // Sort the properties in increasing key order.
114 List<String> sortedKeys = new ArrayList<String>();
115 for (Object key : p.keySet()) {
116 sortedKeys.add((String)key);
117 }
118 Collections.sort(sortedKeys);
119 Iterator<String> keys = sortedKeys.iterator();
120
121 // Collect the properties into a string buffer.
122 StringBuilder data = new StringBuilder();
123 while (keys.hasNext()) {
124 String key = keys.next();
125 data.append(" { \"" + escape(key) + "\", \"" +
126 escape((String)p.get(key)) + "\" },\n");
127 }
128
129 // Create dest file name. It is derived from the properties file name.
130 String destFilename = destRoot.getPath()+File.separator+pkgNameF+File.separator+classname+".java";
131 File dest = new File(destFilename);
132
133 // Make sure the dest directories exist.
134 if (!dest.getParentFile().isDirectory()) {
135 if (!dest.getParentFile().mkdirs()) {
136 Log.error("Could not create the directory "+dest.getParentFile().getPath());
137 return false;
138 }
139 }
140
141 Set<URI> as = packageArtifacts.get(pkgName);
142 if (as == null) {
143 as = new HashSet<URI>();
144 packageArtifacts.put(pkgName, as);
145 }
146 as.add(dest.toURI());
147
148 if (dest.exists() && dest.lastModified() > src.lastModified()) {
149 // A generated file exists, and its timestamp is newer than the source.
150 // Assume that we do not need to regenerate the dest file!
151 // Thus we are done.
152 return true;
153 }
154
155 String packageString = "package " + pkgNameF.replace(File.separatorChar,'.') + ";\n\n";
156
157 Log.info("Compiling property file "+pkgNameF+File.separator+src.getName());
158 try (Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(dest)))) {
159 MessageFormat format = new MessageFormat(FORMAT);
160 writer.write(format.format(new Object[] { packageString, classname, superClass, data }));
161 } catch ( IOException e ) {
162 Log.error("Could not write file "+dest.getPath());
163 return false;
164 }
165 return true;
166 }
167
168 private static final String FORMAT =
169 "{0}" +
170 "public final class {1} extends {2} '{'\n" +
171 " protected final Object[][] getContents() '{'\n" +
172 " return new Object[][] '{'\n" +
173 "{3}" +
174 " };\n" +
175 " }\n" +
176 "}\n";
177
178 public static String escape(String theString) {
179 int len = theString.length();
180 StringBuilder outBuffer = new StringBuilder(len*2);
181
182 for(int x=0; x<len; x++) {
183 char aChar = theString.charAt(x);
184 switch(aChar) {
185 case '\\':outBuffer.append('\\'); outBuffer.append('\\');
186 break;
187 case '\t':outBuffer.append('\\'); outBuffer.append('t');
188 break;
189 case '\n':outBuffer.append('\\'); outBuffer.append('n');
190 break;
191 case '\r':outBuffer.append('\\'); outBuffer.append('r');
192 break;
193 case '\f':outBuffer.append('\\'); outBuffer.append('f');
194 break;
195 default:
196 if ((aChar < 0x0020) || (aChar > 0x007e)) {
197 outBuffer.append('\\');
198 outBuffer.append('u');
199 outBuffer.append(toHex((aChar >> 12) & 0xF));
200 outBuffer.append(toHex((aChar >> 8) & 0xF));
201 outBuffer.append(toHex((aChar >> 4) & 0xF));
202 outBuffer.append(toHex( aChar & 0xF));
203 } else {
204 if (aChar == '"') {
205 outBuffer.append('\\');
206 }
207 outBuffer.append(aChar);
208 }
209 }
210 }
211 return outBuffer.toString();
212 }
213
214 private static char toHex(int nibble) {
215 return hexDigit[(nibble & 0xF)];
216 }
217
218 private static final char[] hexDigit = {
219 '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
220 };
221 }

mercurial