1 /* 2 * Copyright (c) 2001, 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 build.tools.stripproperties; 27 28 import java.io.BufferedInputStream; 29 import java.io.BufferedWriter; 30 import java.io.FileInputStream; 31 import java.io.FileNotFoundException; 32 import java.io.FileOutputStream; 33 import java.io.OutputStream; 34 import java.io.OutputStreamWriter; 35 import java.io.IOException; 36 import java.io.InputStream; 37 import java.util.ArrayList; 38 import java.util.Enumeration; 39 import java.util.Iterator; 40 import java.util.List; 41 import java.util.Properties; 42 43 /** 44 * Reads a properties file from standard input and writes an equivalent 45 * properties file without comments to standard output. 46 */ 47 public class StripPropertiesCorba { 48 49 private static void error(String msg, Exception e) { 50 System.err.println("ERROR: stripproperties: " + msg); 51 if ( e != null ) { 52 System.err.println("EXCEPTION: " + e.toString()); 53 e.printStackTrace(); 54 } 55 } 56 57 private static List<String> infiles = new ArrayList<String>(); 58 private static List<String> outfiles = new ArrayList<String>(); 59 60 private static boolean parseOptions(String args[]) { 61 boolean ok = true; 62 63 for ( int i = 0; i < args.length ; i++ ) { 64 if ( "-clean".equals(args[i]) && i+2 < args.length ) { 65 infiles.add(args[++i]); 66 outfiles.add(args[++i]); 67 } else if ( args[i].charAt(0)=='@') { 68 String filename = args[i].substring(1); 69 FileInputStream finput = null; 70 byte contents[] = null; 71 try { 72 finput = new FileInputStream(filename); 73 int byteCount = finput.available(); 74 if ( byteCount <= 0 ) { 75 error("The @file is empty", null); 76 ok = false; 77 } else { 78 contents = new byte[byteCount]; 79 int bytesRead = finput.read(contents); 80 if ( byteCount != bytesRead ) { 81 error("Cannot read all of @file", null); 82 ok = false; 83 } 84 } 85 } catch ( IOException e ) { 86 error("cannot open " + filename, e); 87 ok = false; 88 } 89 if ( finput != null ) { 90 try { 91 finput.close(); 92 } catch ( IOException e ) { 93 ok = false; 94 error("cannot close " + filename, e); 95 } 96 } 97 if ( ok && contents != null ) { 98 String tokens[] = (new String(contents)).split("\\s+"); 99 if ( tokens.length > 0 ) { 100 ok = parseOptions(tokens); 101 } 102 } 103 if ( !ok ) { 104 break; 105 } 106 } else { 107 infiles.add(args[i]); 108 outfiles.add(args[i]); 109 } 110 } 111 return ok; 112 } 113 114 private static boolean stripFiles(List<String> infiles, List<String> outfiles) { 115 boolean ok = true; 116 Iterator<String> inIter = infiles.iterator(); 117 Iterator<String> outIter = outfiles.iterator(); 118 119 for (; inIter.hasNext(); ) { 120 String infile = inIter.next(); 121 String outfile = outIter.next(); 122 123 Properties prop = new Properties(); 124 InputStream in = null; 125 try { 126 in = new BufferedInputStream(new FileInputStream(infile)); 127 prop.load(in); 128 } catch ( FileNotFoundException e ) { 129 error("Cannot access file " + infile, e); 130 ok = false; 131 } catch ( IOException e ) { 132 error("IO exception processing file " + infile, e); 133 ok = false; 134 } 135 if ( in != null ) { 136 try { 137 in.close(); 138 } catch ( IOException e ) { 139 error("IO exception closing file " + infile, e); 140 ok = false; 141 } 142 } 143 if ( !ok ) { 144 break; 145 } 146 147 OutputStream out = null; 148 try { 149 out = new FileOutputStream(outfile); 150 storeProperties(prop, out); 151 out.flush(); 152 } catch ( IOException e ) { 153 error("IO exception processing file " + outfile, e); 154 ok = false; 155 } 156 if ( out != null ) { 157 try { 158 out.close(); 159 } catch ( IOException e ) { 160 error("IO exception closing file " + outfile, e); 161 ok = false; 162 } 163 } 164 if ( !ok ) { 165 break; 166 } 167 168 } 169 return ok; 170 } 171 172 /** 173 * Strip the properties filenames supplied, replacing their contents. 174 * @param args Names of properties files to process and replace contents 175 */ 176 public static void main(String args[]) { 177 boolean ok = parseOptions(args); 178 if ( !ok || !stripFiles(infiles, outfiles) ) { 179 System.exit(1); 180 } 181 } 182 183 // --- code below here is adapted from java.util.Properties --- 184 185 private static final String specialSaveChars = "=: \t\r\n\f#!"; 186 187 /* 188 * Converts unicodes to encoded \uxxxx 189 * and writes out any of the characters in specialSaveChars 190 * with a preceding slash 191 */ 192 private static String saveConvert(String theString, boolean escapeSpace) { 193 int len = theString.length(); 194 StringBuffer outBuffer = new StringBuffer(len*2); 195 196 for(int x=0; x<len; x++) { 197 char aChar = theString.charAt(x); 198 switch(aChar) { 199 case ' ': 200 if (x == 0 || escapeSpace) { 201 outBuffer.append('\\'); 202 } 203 outBuffer.append(' '); 204 break; 205 case '\\': 206 outBuffer.append('\\'); 207 outBuffer.append('\\'); 208 break; 209 case '\t': 210 outBuffer.append('\\'); 211 outBuffer.append('t'); 212 break; 213 case '\n': 214 outBuffer.append('\\'); 215 outBuffer.append('n'); 216 break; 217 case '\r': 218 outBuffer.append('\\'); 219 outBuffer.append('r'); 220 break; 221 case '\f': 222 outBuffer.append('\\'); 223 outBuffer.append('f'); 224 break; 225 default: 226 if ((aChar < 0x0020) || (aChar == 0x007e) || (aChar > 0x00ff)) { 227 outBuffer.append('\\'); 228 outBuffer.append('u'); 229 outBuffer.append(toHex((aChar >> 12) & 0xF)); 230 outBuffer.append(toHex((aChar >> 8) & 0xF)); 231 outBuffer.append(toHex((aChar >> 4) & 0xF)); 232 outBuffer.append(toHex( aChar & 0xF)); 233 } else { 234 if (specialSaveChars.indexOf(aChar) != -1) { 235 outBuffer.append('\\'); 236 } 237 outBuffer.append(aChar); 238 } 239 } 240 } 241 return outBuffer.toString(); 242 } 243 244 /** 245 * Writes the content of <code>properties</code> to <code>out</code>. 246 * The format is that of Properties.store with the following modifications: 247 * <ul> 248 * <li>No header or date is written 249 * <li>Latin-1 characters are written as single bytes, not escape sequences 250 * <li>Line breaks are indicated by a single \n independent of platform 251 * <ul> 252 */ 253 private static void storeProperties(Properties properties, OutputStream out) 254 throws IOException { 255 BufferedWriter awriter; 256 awriter = new BufferedWriter(new OutputStreamWriter(out, "8859_1")); 257 for (Enumeration<Object> e = properties.keys(); e.hasMoreElements();) { 258 String key = (String)e.nextElement(); 259 String val = (String)properties.get(key); 260 key = saveConvert(key, true); 261 262 /* No need to escape embedded and trailing spaces for value, hence 263 * pass false to flag. 264 */ 265 val = saveConvert(val, false); 266 writeln(awriter, key + "=" + val); 267 } 268 awriter.flush(); 269 } 270 271 private static void writeln(BufferedWriter bw, String s) throws IOException { 272 bw.write(s); 273 bw.write("\n"); 274 } 275 276 /** 277 * Convert a nibble to a hex character 278 * @param nibble the nibble to convert. 279 */ 280 private static char toHex(int nibble) { 281 return hexDigit[(nibble & 0xF)]; 282 } 283 284 /** A table of hex digits */ 285 private static final char[] hexDigit = { 286 '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' 287 }; 288 }