1 /* 2 * Copyright (c) 1996, 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 /* 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.nio.file.Files; 75 import java.io.UnsupportedEncodingException; 76 import java.nio.charset.UnsupportedCharsetException; 77 import sun.tools.native2ascii.A2NFilter; 78 import sun.tools.native2ascii.N2AFilter; 79 80 /** 81 * Main program of the native2ascii 82 */ 83 84 public class Main { 85 86 String inputFileName = null; 87 String outputFileName = null; 88 File tempFile = null; 89 boolean reverse = false; 90 static String encodingString = null; 91 static String defaultEncoding = null; 92 static CharsetEncoder encoder = null; 93 94 /** 95 * Run the converter 96 */ 97 public synchronized boolean convert(String argv[]){ 98 List<String> v = new ArrayList<>(2); 99 File outputFile = null; 100 boolean createOutputFile = false; 101 102 // Parse arguments 103 for (int i = 0; i < argv.length; i++) { 104 if (argv[i].equals("-encoding")) { 105 if ((i + 1) < argv.length){ 106 encodingString = argv[++i]; 107 } else { 108 error(getMsg("err.bad.arg")); 109 usage(); 110 return false; 111 } 112 } else if (argv[i].equals("-reverse")){ 113 reverse = true; 114 } else { 115 if (v.size() > 1) { 116 usage(); 117 return false; 118 } 119 v.add(argv[i]); 120 } 121 } 122 if (encodingString == null) 123 defaultEncoding = Charset.defaultCharset().name(); 124 125 char[] lineBreak = System.getProperty("line.separator").toCharArray(); 126 try { 127 initializeConverter(); 128 129 if (v.size() == 1) 130 inputFileName = v.get(0); 131 132 if (v.size() == 2) { 133 inputFileName = v.get(0); 134 outputFileName = v.get(1); 135 createOutputFile = true; 136 } 137 138 if (createOutputFile) { 139 outputFile = new File(outputFileName); 140 if (outputFile.exists() && !outputFile.canWrite()) { 141 throw new Exception(formatMsg("err.cannot.write", outputFileName)); 142 } 143 } 144 145 if (reverse){ 146 BufferedReader reader = getA2NInput(inputFileName); 147 Writer osw = getA2NOutput(outputFileName); 148 String line; 149 150 while ((line = reader.readLine()) != null) { 151 osw.write(line.toCharArray()); 152 osw.write(lineBreak); 153 if (outputFileName == null) { // flush stdout 154 osw.flush(); 155 } 156 } 157 reader.close(); // Close the stream. 158 osw.close(); 159 } else { 160 //N2A 161 String inLine; 162 BufferedReader in = getN2AInput(inputFileName); 163 BufferedWriter out = getN2AOutput(outputFileName); 164 165 while ((inLine = in.readLine()) != null) { 166 out.write(inLine.toCharArray()); 167 out.write(lineBreak); 168 if (outputFileName == null) { // flush stdout 169 out.flush(); 170 } 171 } 172 out.close(); 173 } 174 // Since we are done rename temporary file to desired output file 175 if (createOutputFile) { 176 if (outputFile.exists()) { 177 // Some win32 platforms can't handle atomic 178 // rename if source and target file paths are 179 // identical. To make things simple we just unconditionally 180 // delete the target file before calling renameTo() 181 outputFile.delete(); 182 } 183 tempFile.renameTo(outputFile); 184 } 185 186 } catch(Exception e){ 187 error(e.toString()); 188 return false; 189 } 190 191 return true; 192 } 193 194 private void error(String msg){ 195 System.out.println(msg); 196 } 197 198 private void usage(){ 199 System.out.println(getMsg("usage")); 200 } 201 202 203 private BufferedReader getN2AInput(String inFile) throws Exception { 204 205 InputStream forwardIn; 206 if (inFile == null) 207 forwardIn = System.in; 208 else { 209 File f = new File(inFile); 210 if (!f.canRead()){ 211 throw new Exception(formatMsg("err.cannot.read", f.getName())); 212 } 213 214 try { 215 forwardIn = new FileInputStream(inFile); 216 } catch (IOException e) { 217 throw new Exception(formatMsg("err.cannot.read", f.getName())); 218 } 219 } 220 221 BufferedReader r = (encodingString != null) ? 222 new BufferedReader(new InputStreamReader(forwardIn, 223 encodingString)) : 224 new BufferedReader(new InputStreamReader(forwardIn)); 225 return r; 226 } 227 228 229 private BufferedWriter getN2AOutput(String outFile) throws Exception { 230 Writer output; 231 BufferedWriter n2aOut; 232 233 if (outFile == null) 234 output = new OutputStreamWriter(System.out,"US-ASCII"); 235 236 else { 237 File f = new File(outFile); 238 239 File tempDir = f.getParentFile(); 240 241 if (tempDir == null) 242 tempDir = new File(System.getProperty("user.dir")); 243 244 tempFile = File.createTempFile("_N2A", 245 ".TMP", 246 tempDir); 247 tempFile.deleteOnExit(); 248 249 try { 250 output = new FileWriter(tempFile); 251 } catch (IOException e){ 252 throw new Exception(formatMsg("err.cannot.write", tempFile.getName())); 253 } 254 } 255 256 n2aOut = new BufferedWriter(new N2AFilter(output)); 257 return n2aOut; 258 } 259 260 private BufferedReader getA2NInput(String inFile) throws Exception { 261 Reader in; 262 BufferedReader reader; 263 264 if (inFile == null) 265 in = new InputStreamReader(System.in, "US-ASCII"); 266 else { 267 File f = new File(inFile); 268 if (!f.canRead()){ 269 throw new Exception(formatMsg("err.cannot.read", f.getName())); 270 } 271 272 try { 273 in = new FileReader(inFile); 274 } catch (Exception e) { 275 throw new Exception(formatMsg("err.cannot.read", f.getName())); 276 } 277 } 278 279 reader = new BufferedReader(new A2NFilter(in)); 280 return reader; 281 } 282 283 private Writer getA2NOutput(String outFile) throws Exception { 284 285 OutputStreamWriter w = null; 286 OutputStream output = null; 287 288 if (outFile == null) 289 output = System.out; 290 else { 291 File f = new File(outFile); 292 293 File tempDir = f.getParentFile(); 294 if (tempDir == null) 295 tempDir = new File(System.getProperty("user.dir")); 296 tempFile = File.createTempFile("_N2A", 297 ".TMP", 298 tempDir); 299 tempFile.deleteOnExit(); 300 301 try { 302 output = new FileOutputStream(tempFile); 303 } catch (IOException e){ 304 throw new Exception(formatMsg("err.cannot.write", tempFile.getName())); 305 } 306 } 307 308 w = (encodingString != null) ? 309 new OutputStreamWriter(output, encodingString) : 310 new OutputStreamWriter(output); 311 312 return (w); 313 } 314 315 private static Charset lookupCharset(String csName) { 316 if (Charset.isSupported(csName)) { 317 try { 318 return Charset.forName(csName); 319 } catch (UnsupportedCharsetException x) { 320 throw new Error(x); 321 } 322 } 323 return null; 324 } 325 326 public static boolean canConvert(char ch) { 327 return (encoder != null && encoder.canEncode(ch)); 328 } 329 330 private static void initializeConverter() throws UnsupportedEncodingException { 331 Charset cs = null; 332 333 try { 334 cs = (encodingString == null) ? 335 lookupCharset(defaultEncoding): 336 lookupCharset(encodingString); 337 338 encoder = (cs != null) ? 339 cs.newEncoder() : 340 null; 341 } catch (IllegalCharsetNameException e) { 342 throw new Error(e); 343 } 344 } 345 346 private static ResourceBundle rsrc; 347 348 static { 349 try { 350 rsrc = ResourceBundle.getBundle( 351 "sun.tools.native2ascii.resources.MsgNative2ascii"); 352 } catch (MissingResourceException e) { 353 throw new Error("Missing message file."); 354 } 355 } 356 357 private String getMsg(String key) { 358 try { 359 return (rsrc.getString(key)); 360 } catch (MissingResourceException e) { 361 throw new Error("Error in message file format."); 362 } 363 } 364 365 private String formatMsg(String key, String arg) { 366 String msg = getMsg(key); 367 return MessageFormat.format(msg, arg); 368 } 369 370 371 /** 372 * Main program 373 */ 374 public static void main(String argv[]){ 375 Main converter = new Main(); 376 System.exit(converter.convert(argv) ? 0 : 1); 377 } 378 }