1 /* 2 * Copyright (c) 1996, 2011, 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 /* 27 */ 28 29 /* 30 Currently javac and load() method in java.util.Properties 31 supports only Latin1 encoding input. 32 But in Asian platforms programmer or message translator 33 uses the editor which support othere than latin1 encoding 34 to specify their native language string. 35 So if programmer or message translator wants to use other than 36 Latin1 character in his/her program source or properties file 37 they must convert the file to ASCII plus \udddd notation. 38 (javac/load() modification is not appropriate due to 39 time constraints for JDK1.1) 40 This utility is for the purpose of that conversion. 41 42 NAME 43 native2ascii - convert native encoding file to ascii file 44 include \udddd Unicode notation 45 46 SYNOPSIS 47 native2ascii [options] [inputfile [outputfile]] 48 49 DESCRIPTION 50 If outputfile is not described standard output is used as 51 output file, and if inputfile is not also described 52 stardard input is used as input file. 53 54 Options 55 56 -reverse 57 convert ascii with \udddd notation to native encoding 58 59 -encoding encoding_name 60 Specify the encoding name which is used by conversion. 61 8859_[1 - 9], JIS, EUCJIS, SJIS is currently supported. 62 Default encoding is taken from System property "file.encoding". 63 64 */ 65 66 package sun.tools.native2ascii; 67 68 import java.io.*; 69 import java.util.*; 70 import java.text.MessageFormat; 71 import java.nio.charset.CharsetEncoder; 72 import java.nio.charset.Charset; 73 import java.nio.charset.IllegalCharsetNameException; 74 import java.io.UnsupportedEncodingException; 75 import java.nio.charset.UnsupportedCharsetException; 76 import sun.tools.native2ascii.A2NFilter; 77 import sun.tools.native2ascii.N2AFilter; 78 79 /** 80 * Main program of the native2ascii 81 */ 82 83 public class Main { 84 85 String inputFileName = null; 86 String outputFileName = null; 87 File tempFile = null; 88 boolean reverse = false; 89 static String encodingString = null; 90 static String defaultEncoding = null; 91 static CharsetEncoder encoder = null; 92 93 /** 94 * Run the converter 95 */ 96 public synchronized boolean convert(String argv[]){ 97 List<String> v = new ArrayList<>(2); 98 File outputFile = null; 99 boolean createOutputFile = false; 100 101 // Parse arguments 102 for (int i = 0; i < argv.length; i++) { 103 if (argv[i].equals("-encoding")) { 104 if ((i + 1) < argv.length){ 105 encodingString = argv[++i]; 106 } else { 107 error(getMsg("err.bad.arg")); 108 usage(); 109 return false; 110 } 111 } else if (argv[i].equals("-reverse")){ 112 reverse = true; 113 } else { 114 if (v.size() > 1) { 115 usage(); 116 return false; 117 } 118 v.add(argv[i]); 119 } 120 } 121 if (encodingString == null) 122 defaultEncoding = Charset.defaultCharset().name(); 123 124 char[] lineBreak = System.getProperty("line.separator").toCharArray(); 125 try { 126 initializeConverter(); 127 128 if (v.size() == 1) 129 inputFileName = v.get(0); 130 131 if (v.size() == 2) { 132 inputFileName = v.get(0); 133 outputFileName = v.get(1); 134 createOutputFile = true; 135 } 136 137 if (createOutputFile) { 138 outputFile = new File(outputFileName); 139 if (outputFile.exists() && !outputFile.canWrite()) { 140 throw new Exception(formatMsg("err.cannot.write", outputFileName)); 141 } 142 } 143 144 if (reverse){ 145 BufferedReader reader = getA2NInput(inputFileName); 146 Writer osw = getA2NOutput(outputFileName); 147 String line; 148 149 while ((line = reader.readLine()) != null) { 150 osw.write(line.toCharArray()); 151 osw.write(lineBreak); 152 if (outputFileName == null) { // flush stdout 153 osw.flush(); 154 } 155 } 156 reader.close(); // Close the stream. 157 osw.close(); 158 } else { 159 //N2A 160 String inLine; 161 BufferedReader in = getN2AInput(inputFileName); 162 BufferedWriter out = getN2AOutput(outputFileName); 163 164 while ((inLine = in.readLine()) != null) { 165 out.write(inLine.toCharArray()); 166 out.write(lineBreak); 167 if (outputFileName == null) { // flush stdout 168 out.flush(); 169 } 170 } 171 out.close(); 172 } 173 // Since we are done rename temporary file to desired output file 174 if (createOutputFile) { 175 if (outputFile.exists()) { 176 // Some win32 platforms can't handle atomic 177 // rename if source and target file paths are 178 // identical. To make things simple we just unconditionally 179 // delete the target file before calling renameTo() 180 outputFile.delete(); 181 } 182 tempFile.renameTo(outputFile); 183 } 184 185 } catch(Exception e){ 186 error(e.toString()); 187 return false; 188 } 189 190 return true; 191 } 192 193 private void error(String msg){ 194 System.out.println(msg); 195 } 196 197 private void usage(){ 198 System.out.println(getMsg("usage")); 199 } 200 201 202 private BufferedReader getN2AInput(String inFile) throws Exception { 203 204 InputStream forwardIn; 205 if (inFile == null) 206 forwardIn = System.in; 207 else { 208 File f = new File(inFile); 209 if (!f.canRead()){ 210 throw new Exception(formatMsg("err.cannot.read", f.getName())); 211 } 212 213 try { 214 forwardIn = new FileInputStream(inFile); 215 } catch (IOException e) { 216 throw new Exception(formatMsg("err.cannot.read", f.getName())); 217 } 218 } 219 220 BufferedReader r = (encodingString != null) ? 221 new BufferedReader(new InputStreamReader(forwardIn, 222 encodingString)) : 223 new BufferedReader(new InputStreamReader(forwardIn)); 224 return r; 225 } 226 227 228 private BufferedWriter getN2AOutput(String outFile) throws Exception { 229 Writer output; 230 BufferedWriter n2aOut; 231 232 if (outFile == null) 233 output = new OutputStreamWriter(System.out,"US-ASCII"); 234 235 else { 236 File f = new File(outFile); 237 238 File tempDir = f.getParentFile(); 239 240 if (tempDir == null) 241 tempDir = new File(System.getProperty("user.dir")); 242 243 tempFile = File.createTempFile("_N2A", 244 ".TMP", 245 tempDir); 246 tempFile.deleteOnExit(); 247 248 try { 249 output = new FileWriter(tempFile); 250 } catch (IOException e){ 251 throw new Exception(formatMsg("err.cannot.write", tempFile.getName())); 252 } 253 } 254 255 n2aOut = new BufferedWriter(new N2AFilter(output)); 256 return n2aOut; 257 } 258 259 private BufferedReader getA2NInput(String inFile) throws Exception { 260 Reader in; 261 BufferedReader reader; 262 263 if (inFile == null) 264 in = new InputStreamReader(System.in, "US-ASCII"); 265 else { 266 File f = new File(inFile); 267 if (!f.canRead()){ 268 throw new Exception(formatMsg("err.cannot.read", f.getName())); 269 } 270 271 try { 272 in = new FileReader(inFile); 273 } catch (Exception e) { 274 throw new Exception(formatMsg("err.cannot.read", f.getName())); 275 } 276 } 277 278 reader = new BufferedReader(new A2NFilter(in)); 279 return reader; 280 } 281 282 private Writer getA2NOutput(String outFile) throws Exception { 283 284 OutputStreamWriter w = null; 285 OutputStream output = null; 286 287 if (outFile == null) 288 output = System.out; 289 else { 290 File f = new File(outFile); 291 292 File tempDir = f.getParentFile(); 293 if (tempDir == null) 294 tempDir = new File(System.getProperty("user.dir")); 295 tempFile = File.createTempFile("_N2A", 296 ".TMP", 297 tempDir); 298 tempFile.deleteOnExit(); 299 300 try { 301 output = new FileOutputStream(tempFile); 302 } catch (IOException e){ 303 throw new Exception(formatMsg("err.cannot.write", tempFile.getName())); 304 } 305 } 306 307 w = (encodingString != null) ? 308 new OutputStreamWriter(output, encodingString) : 309 new OutputStreamWriter(output); 310 311 return (w); 312 } 313 314 private static Charset lookupCharset(String csName) { 315 if (Charset.isSupported(csName)) { 316 try { 317 return Charset.forName(csName); 318 } catch (UnsupportedCharsetException x) { 319 throw new Error(x); 320 } 321 } 322 return null; 323 } 324 325 public static boolean canConvert(char ch) { 326 return (encoder != null && encoder.canEncode(ch)); 327 } 328 329 private static void initializeConverter() throws UnsupportedEncodingException { 330 Charset cs = null; 331 332 try { 333 cs = (encodingString == null) ? 334 lookupCharset(defaultEncoding): 335 lookupCharset(encodingString); 336 337 encoder = (cs != null) ? 338 cs.newEncoder() : 339 null; 340 } catch (IllegalCharsetNameException e) { 341 throw new Error(e); 342 } 343 } 344 345 private static ResourceBundle rsrc; 346 347 static { 348 try { 349 rsrc = ResourceBundle.getBundle( 350 "sun.tools.native2ascii.resources.MsgNative2ascii"); 351 } catch (MissingResourceException e) { 352 throw new Error("Missing message file."); 353 } 354 } 355 356 private String getMsg(String key) { 357 try { 358 return (rsrc.getString(key)); 359 } catch (MissingResourceException e) { 360 throw new Error("Error in message file format."); 361 } 362 } 363 364 private String formatMsg(String key, String arg) { 365 String msg = getMsg(key); 366 return MessageFormat.format(msg, arg); 367 } 368 369 370 /** 371 * Main program 372 */ 373 public static void main(String argv[]){ 374 Main converter = new Main(); 375 System.exit(converter.convert(argv) ? 0 : 1); 376 } 377 }