make/tools/compileproperties/CompileProperties.java

Mon, 03 Nov 2014 12:35:10 -0800

author
asaha
date
Mon, 03 Nov 2014 12:35:10 -0800
changeset 2661
05824e9d8171
parent 1305
9d47f4850714
child 2525
2eb010b6cb22
permissions
-rw-r--r--

Added tag jdk8u31-b07 for changeset 03b8ef4cf0c0

duke@1 1 /*
jjh@1305 2 * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
duke@1 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@1 4 *
duke@1 5 * This code is free software; you can redistribute it and/or modify it
duke@1 6 * under the terms of the GNU General Public License version 2 only, as
ohair@554 7 * published by the Free Software Foundation. Oracle designates this
duke@1 8 * particular file as subject to the "Classpath" exception as provided
ohair@554 9 * by Oracle in the LICENSE file that accompanied this code.
duke@1 10 *
duke@1 11 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@1 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@1 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@1 14 * version 2 for more details (a copy is included in the LICENSE file that
duke@1 15 * accompanied this code).
duke@1 16 *
duke@1 17 * You should have received a copy of the GNU General Public License version
duke@1 18 * 2 along with this work; if not, write to the Free Software Foundation,
duke@1 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@1 20 *
ohair@554 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@554 22 * or visit www.oracle.com if you need additional information or have any
ohair@554 23 * questions.
duke@1 24 */
duke@1 25
ohrstrom@1224 26 package compileproperties;
ohrstrom@1224 27
duke@1 28 import java.io.BufferedWriter;
duke@1 29 import java.io.File;
duke@1 30 import java.io.FileInputStream;
duke@1 31 import java.io.FileNotFoundException;
duke@1 32 import java.io.FileOutputStream;
duke@1 33 import java.io.IOException;
duke@1 34 import java.io.OutputStreamWriter;
duke@1 35 import java.io.Writer;
duke@1 36 import java.text.MessageFormat;
duke@1 37 import java.util.ArrayList;
duke@1 38 import java.util.Collections;
duke@1 39 import java.util.Iterator;
duke@1 40 import java.util.List;
duke@1 41 import java.util.Properties;
duke@1 42
duke@1 43 /** Translates a .properties file into a .java file containing the
duke@1 44 * definition of a java.util.Properties subclass which can then be
duke@1 45 * compiled with javac. <P>
duke@1 46 *
duke@1 47 * Usage: java CompileProperties [path to .properties file] [path to .java file to be output] [super class]
duke@1 48 *
duke@1 49 * Infers the package by looking at the common suffix of the two
duke@1 50 * inputs, eliminating "classes" from it.
duke@1 51 *
duke@1 52 * @author Scott Violet
duke@1 53 * @author Kenneth Russell
duke@1 54 */
duke@1 55
duke@1 56 public class CompileProperties {
duke@1 57
duke@1 58 public static void main(String[] args) {
duke@1 59 CompileProperties cp = new CompileProperties();
duke@1 60 boolean ok = cp.run(args);
duke@1 61 if ( !ok ) {
duke@1 62 System.exit(1);
duke@1 63 }
duke@1 64 }
duke@1 65
ohrstrom@1224 66 public static interface Log {
duke@1 67 void info(String msg);
duke@1 68 void verbose(String msg);
duke@1 69 void error(String msg, Exception e);
duke@1 70 }
duke@1 71
duke@1 72 private String propfiles[];
duke@1 73 private String outfiles[] ;
duke@1 74 private String supers[] ;
duke@1 75 private int compileCount = 0;
duke@1 76 private boolean quiet = false;
ohrstrom@1224 77 public Log log;
duke@1 78
duke@1 79 public void setLog(Log log) {
duke@1 80 this.log = log;
duke@1 81 }
duke@1 82
duke@1 83 public boolean run(String[] args) {
duke@1 84 if (log == null) {
duke@1 85 log = new Log() {
duke@1 86 public void error(String msg, Exception e) {
duke@1 87 System.err.println("ERROR: CompileProperties: " + msg);
duke@1 88 if ( e != null ) {
duke@1 89 System.err.println("EXCEPTION: " + e.toString());
duke@1 90 e.printStackTrace();
duke@1 91 }
duke@1 92 }
duke@1 93 public void info(String msg) {
duke@1 94 System.out.println(msg);
duke@1 95 }
duke@1 96 public void verbose(String msg) {
duke@1 97 if (!quiet)
duke@1 98 System.out.println(msg);
duke@1 99 }
duke@1 100 };
duke@1 101 }
duke@1 102
duke@1 103 boolean ok = true;
duke@1 104 /* Original usage */
duke@1 105 if (args.length == 2 && args[0].charAt(0) != '-' ) {
jjg@465 106 ok = createFile(args[0], args[1], "java.util.ListResourceBundle");
duke@1 107 } else if (args.length == 3) {
duke@1 108 ok = createFile(args[0], args[1], args[2]);
duke@1 109 } else if (args.length == 0) {
duke@1 110 usage(log);
duke@1 111 ok = false;
duke@1 112 } else {
duke@1 113 /* New batch usage */
duke@1 114 ok = parseOptions(args);
duke@1 115 if ( ok && compileCount == 0 ) {
duke@1 116 log.error("options parsed but no files to compile", null);
duke@1 117 ok = false;
duke@1 118 }
duke@1 119 /* Need at least one file. */
duke@1 120 if ( !ok ) {
duke@1 121 usage(log);
duke@1 122 } else {
duke@1 123 /* Process files */
duke@1 124 for ( int i = 0; i < compileCount && ok ; i++ ) {
duke@1 125 ok = createFile(propfiles[i], outfiles[i], supers[i]);
duke@1 126 }
duke@1 127 }
duke@1 128 }
duke@1 129 return ok;
duke@1 130 }
duke@1 131
duke@1 132 private boolean parseOptions(String args[]) {
duke@1 133 boolean ok = true;
duke@1 134 if ( compileCount > 0 ) {
duke@1 135 String new_propfiles[] = new String[compileCount + args.length];
duke@1 136 String new_outfiles[] = new String[compileCount + args.length];
duke@1 137 String new_supers[] = new String[compileCount + args.length];
duke@1 138 System.arraycopy(propfiles, 0, new_propfiles, 0, compileCount);
duke@1 139 System.arraycopy(outfiles, 0, new_outfiles, 0, compileCount);
duke@1 140 System.arraycopy(supers, 0, new_supers, 0, compileCount);
duke@1 141 propfiles = new_propfiles;
duke@1 142 outfiles = new_outfiles;
duke@1 143 supers = new_supers;
duke@1 144 } else {
duke@1 145 propfiles = new String[args.length];
duke@1 146 outfiles = new String[args.length];
duke@1 147 supers = new String[args.length];
duke@1 148 }
duke@1 149
duke@1 150 for ( int i = 0; i < args.length ; i++ ) {
duke@1 151 if ( "-compile".equals(args[i]) && i+3 < args.length ) {
duke@1 152 propfiles[compileCount] = args[++i];
duke@1 153 outfiles[compileCount] = args[++i];
duke@1 154 supers[compileCount] = args[++i];
duke@1 155 compileCount++;
duke@1 156 } else if ( "-optionsfile".equals(args[i]) && i+1 < args.length ) {
duke@1 157 String filename = args[++i];
duke@1 158 FileInputStream finput = null;
duke@1 159 byte contents[] = null;
duke@1 160 try {
duke@1 161 finput = new FileInputStream(filename);
duke@1 162 int byteCount = finput.available();
duke@1 163 if ( byteCount <= 0 ) {
duke@1 164 log.error("The -optionsfile file is empty", null);
duke@1 165 ok = false;
duke@1 166 } else {
duke@1 167 contents = new byte[byteCount];
duke@1 168 int bytesRead = finput.read(contents);
duke@1 169 if ( byteCount != bytesRead ) {
duke@1 170 log.error("Cannot read all of -optionsfile file", null);
duke@1 171 ok = false;
duke@1 172 }
duke@1 173 }
duke@1 174 } catch ( IOException e ) {
duke@1 175 log.error("cannot open " + filename, e);
duke@1 176 ok = false;
duke@1 177 }
duke@1 178 if ( finput != null ) {
duke@1 179 try {
duke@1 180 finput.close();
duke@1 181 } catch ( IOException e ) {
duke@1 182 ok = false;
duke@1 183 log.error("cannot close " + filename, e);
duke@1 184 }
duke@1 185 }
duke@1 186 if ( ok = true && contents != null ) {
duke@1 187 String tokens[] = (new String(contents)).split("\\s+");
duke@1 188 if ( tokens.length > 0 ) {
duke@1 189 ok = parseOptions(tokens);
duke@1 190 }
duke@1 191 }
duke@1 192 if ( !ok ) {
duke@1 193 break;
duke@1 194 }
duke@1 195 } else if ( "-quiet".equals(args[i]) ) {
duke@1 196 quiet = true;
duke@1 197 } else {
duke@1 198 log.error("argument error", null);
duke@1 199 ok = false;
duke@1 200 }
duke@1 201 }
duke@1 202 return ok;
duke@1 203 }
duke@1 204
duke@1 205 private boolean createFile(String propertiesPath, String outputPath,
duke@1 206 String superClass) {
duke@1 207 boolean ok = true;
duke@1 208 log.verbose("parsing: " + propertiesPath);
duke@1 209 Properties p = new Properties();
duke@1 210 try {
duke@1 211 p.load(new FileInputStream(propertiesPath));
duke@1 212 } catch ( FileNotFoundException e ) {
duke@1 213 ok = false;
duke@1 214 log.error("Cannot find file " + propertiesPath, e);
duke@1 215 } catch ( IOException e ) {
duke@1 216 ok = false;
duke@1 217 log.error("IO error on file " + propertiesPath, e);
duke@1 218 }
duke@1 219 if ( ok ) {
duke@1 220 String packageName = inferPackageName(propertiesPath, outputPath);
duke@1 221 log.verbose("inferred package name: " + packageName);
duke@1 222 List<String> sortedKeys = new ArrayList<String>();
duke@1 223 for ( Object key : p.keySet() ) {
duke@1 224 sortedKeys.add((String)key);
duke@1 225 }
duke@1 226 Collections.sort(sortedKeys);
jjg@1045 227 Iterator<String> keys = sortedKeys.iterator();
duke@1 228
duke@1 229 StringBuffer data = new StringBuffer();
duke@1 230
duke@1 231 while (keys.hasNext()) {
jjg@1045 232 String key = keys.next();
jjg@1045 233 data.append(" { \"" + escape(key) + "\", \"" +
duke@1 234 escape((String)p.get(key)) + "\" },\n");
duke@1 235 }
duke@1 236
duke@1 237 // Get class name from java filename, not the properties filename.
duke@1 238 // (zh_TW properties might be used to create zh_HK files)
duke@1 239 File file = new File(outputPath);
duke@1 240 String name = file.getName();
duke@1 241 int dotIndex = name.lastIndexOf('.');
duke@1 242 String className;
duke@1 243 if (dotIndex == -1) {
duke@1 244 className = name;
duke@1 245 } else {
duke@1 246 className = name.substring(0, dotIndex);
duke@1 247 }
duke@1 248
duke@1 249 String packageString = "";
duke@1 250 if (packageName != null && !packageName.equals("")) {
duke@1 251 packageString = "package " + packageName + ";\n\n";
duke@1 252 }
duke@1 253
duke@1 254 Writer writer = null;
duke@1 255 try {
duke@1 256 writer = new BufferedWriter(
duke@1 257 new OutputStreamWriter(new FileOutputStream(outputPath), "8859_1"));
duke@1 258 MessageFormat format = new MessageFormat(FORMAT);
duke@1 259 writer.write(format.format(new Object[] { packageString, className, superClass, data }));
duke@1 260 } catch ( IOException e ) {
duke@1 261 ok = false;
duke@1 262 log.error("IO error writing to file " + outputPath, e);
duke@1 263 }
duke@1 264 if ( writer != null ) {
duke@1 265 try {
duke@1 266 writer.flush();
duke@1 267 } catch ( IOException e ) {
duke@1 268 ok = false;
duke@1 269 log.error("IO error flush " + outputPath, e);
duke@1 270 }
duke@1 271 try {
duke@1 272 writer.close();
duke@1 273 } catch ( IOException e ) {
duke@1 274 ok = false;
duke@1 275 log.error("IO error close " + outputPath, e);
duke@1 276 }
duke@1 277 }
duke@1 278 log.verbose("wrote: " + outputPath);
duke@1 279 }
duke@1 280 return ok;
duke@1 281 }
duke@1 282
duke@1 283 private static void usage(Log log) {
duke@1 284 log.info("usage:");
duke@1 285 log.info(" java CompileProperties path_to_properties_file path_to_java_output_file [super_class]");
duke@1 286 log.info(" -OR-");
duke@1 287 log.info(" java CompileProperties {-compile path_to_properties_file path_to_java_output_file super_class} -or- -optionsfile filename");
duke@1 288 log.info("");
duke@1 289 log.info("Example:");
jjg@465 290 log.info(" java CompileProperties -compile test.properties test.java java.util.ListResourceBundle");
duke@1 291 log.info(" java CompileProperties -optionsfile option_file");
jjg@465 292 log.info("option_file contains: -compile test.properties test.java java.util.ListResourceBundle");
duke@1 293 }
duke@1 294
duke@1 295 private static String escape(String theString) {
duke@1 296 // This is taken from Properties.saveConvert with changes for Java strings
duke@1 297 int len = theString.length();
duke@1 298 StringBuffer outBuffer = new StringBuffer(len*2);
duke@1 299
duke@1 300 for(int x=0; x<len; x++) {
duke@1 301 char aChar = theString.charAt(x);
duke@1 302 switch(aChar) {
duke@1 303 case '\\':outBuffer.append('\\'); outBuffer.append('\\');
duke@1 304 break;
duke@1 305 case '\t':outBuffer.append('\\'); outBuffer.append('t');
duke@1 306 break;
duke@1 307 case '\n':outBuffer.append('\\'); outBuffer.append('n');
duke@1 308 break;
duke@1 309 case '\r':outBuffer.append('\\'); outBuffer.append('r');
duke@1 310 break;
duke@1 311 case '\f':outBuffer.append('\\'); outBuffer.append('f');
duke@1 312 break;
duke@1 313 default:
duke@1 314 if ((aChar < 0x0020) || (aChar > 0x007e)) {
duke@1 315 outBuffer.append('\\');
duke@1 316 outBuffer.append('u');
duke@1 317 outBuffer.append(toHex((aChar >> 12) & 0xF));
duke@1 318 outBuffer.append(toHex((aChar >> 8) & 0xF));
duke@1 319 outBuffer.append(toHex((aChar >> 4) & 0xF));
duke@1 320 outBuffer.append(toHex( aChar & 0xF));
duke@1 321 } else {
duke@1 322 if (specialSaveChars.indexOf(aChar) != -1) {
duke@1 323 outBuffer.append('\\');
duke@1 324 }
duke@1 325 outBuffer.append(aChar);
duke@1 326 }
duke@1 327 }
duke@1 328 }
duke@1 329 return outBuffer.toString();
duke@1 330 }
duke@1 331
duke@1 332 private static String inferPackageName(String inputPath, String outputPath) {
duke@1 333 // Normalize file names
duke@1 334 inputPath = new File(inputPath).getPath();
duke@1 335 outputPath = new File(outputPath).getPath();
duke@1 336 // Split into components
duke@1 337 String sep;
duke@1 338 if (File.separatorChar == '\\') {
duke@1 339 sep = "\\\\";
duke@1 340 } else {
duke@1 341 sep = File.separator;
duke@1 342 }
duke@1 343 String[] inputs = inputPath.split(sep);
duke@1 344 String[] outputs = outputPath.split(sep);
duke@1 345 // Match common names, eliminating first "classes" entry from
duke@1 346 // each if present
duke@1 347 int inStart = 0;
duke@1 348 int inEnd = inputs.length - 2;
duke@1 349 int outEnd = outputs.length - 2;
duke@1 350 int i = inEnd;
duke@1 351 int j = outEnd;
duke@1 352 while (i >= 0 && j >= 0) {
duke@1 353 if (!inputs[i].equals(outputs[j]) ||
duke@1 354 (inputs[i].equals("gensrc") && inputs[j].equals("gensrc"))) {
duke@1 355 ++i;
duke@1 356 ++j;
duke@1 357 break;
duke@1 358 }
duke@1 359 --i;
duke@1 360 --j;
duke@1 361 }
duke@1 362 String result;
duke@1 363 if (i < 0 || j < 0 || i >= inEnd || j >= outEnd) {
duke@1 364 result = "";
duke@1 365 } else {
duke@1 366 if (inputs[i].equals("classes") && outputs[j].equals("classes")) {
duke@1 367 ++i;
duke@1 368 }
duke@1 369 inStart = i;
duke@1 370 StringBuffer buf = new StringBuffer();
duke@1 371 for (i = inStart; i <= inEnd; i++) {
duke@1 372 buf.append(inputs[i]);
duke@1 373 if (i < inEnd) {
duke@1 374 buf.append('.');
duke@1 375 }
duke@1 376 }
duke@1 377 result = buf.toString();
duke@1 378 }
duke@1 379 return result;
duke@1 380 }
duke@1 381
duke@1 382 private static final String FORMAT =
duke@1 383 "{0}" +
duke@1 384 "public final class {1} extends {2} '{'\n" +
duke@1 385 " protected final Object[][] getContents() '{'\n" +
duke@1 386 " return new Object[][] '{'\n" +
duke@1 387 "{3}" +
duke@1 388 " };\n" +
duke@1 389 " }\n" +
duke@1 390 "}\n";
duke@1 391
duke@1 392 // This comes from Properties
duke@1 393 private static char toHex(int nibble) {
duke@1 394 return hexDigit[(nibble & 0xF)];
duke@1 395 }
duke@1 396
duke@1 397 // This comes from Properties
duke@1 398 private static final char[] hexDigit = {
duke@1 399 '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
duke@1 400 };
duke@1 401
duke@1 402 // Note: different from that in Properties
duke@1 403 private static final String specialSaveChars = "\"";
duke@1 404 }

mercurial