1 16 17 package de.gulden.util.javasource; 18 19 import de.gulden.util.javasource.sourclet.Sourclet; 20 import de.gulden.util.javasource.jjt.Node; 21 import de.gulden.util.javasource.jjt.*; 22 import javax.xml.parsers.*; 23 import org.w3c.dom.*; 24 import org.xml.sax.SAXException ; 25 import java.io.*; 26 import java.util.*; 27 28 40 public class SourceParser implements ParserTreeConstants { 41 42 46 49 public static final String VERSION = "1.1"; 50 51 54 protected static final String workaroundUnicodeSingleCharMarker = "-" + "unicodechar" + "-"; 55 56 57 61 64 public static String nl = System.getProperty("line.separator"); 65 66 70 public static boolean includeXMLDoctype = false; 71 72 76 public static boolean validateXML = false; 77 78 81 public static boolean verbose = false; 82 83 86 public static LogPerformer logPerformer = LogPerformer.DEFAULT; 87 88 92 protected static DocumentBuilder documentBuilder; 93 94 95 99 105 public static Package parse(File file, ProgressTracker pt) throws IOException, ParseException { 106 return parse(new File[] {file}, pt); 107 } 108 109 116 public static Package parse(File[] files, ProgressTracker pt) throws IOException, ParseException { 117 Package base=new Package (); 118 parse(files, base, pt); 119 return base; 120 } 121 122 127 public static void parse(File[] files, Package basePackage, ProgressTracker pt) throws IOException, ParseException { 128 parsePass1(basePackage ,files,pt); 129 analysePass2(basePackage ,pt); 130 } 131 132 137 public static void parse(File file, Package basePackage, ProgressTracker pt) throws IOException, ParseException { 138 parse(new File[] {file},basePackage, pt); 139 } 140 141 147 public static Package parse(String [] filenames, ProgressTracker pt) throws IOException, ParseException { 148 File[] f=new File[filenames.length]; 149 for (int i=0;i<filenames.length;i++) { 150 f[i]=new File(filenames[i]); 151 } 152 return parse(f,pt); 153 } 154 155 163 public static Package parseXML(InputStream in) throws IOException, SAXException { 164 Document doc=getDocumentBuilder().parse(in); 165 Package p=new Package (); 166 Element e=doc.getDocumentElement(); 167 p.initFromXML(e); return p; 169 } 170 171 178 public static Document buildXML(Package p) { 179 DOMImplementation domImplementation=getDocumentBuilder().getDOMImplementation(); 180 DocumentType doctype; 181 if (includeXMLDoctype) { 182 doctype=domImplementation.createDocumentType("xjava",null,"xjava.dtd"); 183 } else { 184 doctype=null; 185 } 186 Document doc=domImplementation.createDocument(null,"xjava",doctype); 187 Element root=doc.getDocumentElement(); 188 Element xml=p.buildXML(doc); 189 if (root!=xml) { root.appendChild(xml); 191 } 192 root.setAttribute("version", VERSION); 193 return doc; 194 } 195 196 205 public static void buildSource(Package p, File dir, File[] sources, Sourclet sourclet) throws IOException { 206 NamedIterator it=p.getClasses(); 208 while (it.hasMore()) { 209 Class c=(Class )it.next(); 210 if ( (sources == null) || (c.getSource()==null) || isInSources(new File(c.getSource()), sources) ) { String classname=c.getUnqualifiedName(); 212 File file=new File(dir,classname+".java"); 213 log("writing "+file.getPath()); 214 FileOutputStream f=new FileOutputStream(file); 215 BufferedOutputStream buf = new BufferedOutputStream(f); sourclet.buildSource(buf,c); 217 buf.close(); 218 } 219 } 220 221 it=p.getInnerPackages(); 223 while (it.hasMore()) { 224 Package pp=(Package )it.next(); 225 String pname=pp.getUnqualifiedName(); 226 File indir=new File(dir,pname); 227 boolean created=indir.mkdir(); 228 if (created) { 229 log("directory "+indir.getPath()+" created"); 230 } 231 buildSource(pp,indir,sources, sourclet); 232 } 233 } 234 235 238 public static String indent(String s, int depth) { 239 StringBuffer sb=new StringBuffer (); 240 StringTokenizer st=new StringTokenizer(s,"\n"); 241 while (st.hasMoreTokens()) { 242 sb.append(repeat(" ",depth)+st.nextToken()+(st.hasMoreTokens()?"\n":"")); 243 } 244 return sb.toString(); 245 } 246 247 250 public static String repeat(String s, int c) { 251 if (c>0) { 252 StringBuffer sb=new StringBuffer (s); 253 for (int i=1;i<c;i++) { 254 sb.append(s); 255 } 256 return sb.toString(); 257 } 258 else { 259 return ""; 260 } 261 } 262 263 266 public static String replace(String s, String old, String neu) { 267 int pos=s.indexOf(old); 268 if (pos!=-1) { 269 return s.substring(0,pos)+neu+replace(s.substring(pos+old.length()),old,neu); 270 } 271 else { 272 return s; 273 } 274 } 275 276 285 public static String workaroundRestoreUnicodeSingleChar(String s) { 286 int pos = s.indexOf("\"" + workaroundUnicodeSingleCharMarker); 287 int l = workaroundUnicodeSingleCharMarker.length(); 288 if (pos != -1) { 289 return s.substring(0, pos) + "'\\u" + s.substring(pos+(l+1), pos+(l+5)) + "'" + workaroundRestoreUnicodeSingleChar(s.substring(pos+(l+6))); 290 } else { 291 return s; 292 } 293 } 294 295 298 protected static DocumentBuilder getDocumentBuilder() { 299 if (documentBuilder==null) { 300 DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance(); 302 dbf.setIgnoringComments(true); 303 dbf.setExpandEntityReferences(validateXML); 304 dbf.setValidating(validateXML); try { 306 documentBuilder=dbf.newDocumentBuilder(); 307 } 308 catch (ParserConfigurationException pce) { 309 System.out.println("ERROR: cannot initialize XML parser - "+pce.getMessage()); 310 } 312 } 313 return documentBuilder; 314 } 315 316 320 protected static void parsePass1(Package basePackage, File[] files, ProgressTracker pt) throws IOException, ParseException { 321 Vector todoFiles=new Vector(); 322 for (int i=0;i<files.length;i++) { 323 if (files[i].exists()) { 324 if (files[i].isFile()) { 325 String filename=files[i].getName(); 326 if (filename.endsWith(".java")) { 327 if (pt!=null) { 328 pt.todo(4); 329 } 330 todoFiles.addElement(files[i]); 331 } 332 else { 333 } 335 } 336 else if (files[i].isDirectory()) { 337 String [] list=files[i].list(); 338 File[] ff=new File[list.length]; 339 for (int j=0;j<list.length;j++) { 340 File ffile=new File(files[i],list[j]); 341 ff[j]=ffile; 342 } 343 parsePass1(basePackage,ff,pt); } 345 } 346 else { 347 warning("warning: can't find input file/directory "+files[i].getPath()+", ignoring"); 348 } 349 } 350 351 for (Enumeration e=todoFiles.elements();e.hasMoreElements();) { 352 File f=(File)e.nextElement(); 353 log("parsing pass 1: "+f.getPath()); 354 String code = readFile(f); 355 code = code.replace('\r', ' '); 357 code = workaroundAvoidUnicodeSingleChar(code) + nl; 362 InputStream in = new StringBufferInputStream(code); 363 analysePass1(basePackage, in, f.getAbsolutePath(), pt); 364 } 365 } 366 367 375 protected static void analysePass1(Package basePackage, InputStream in, String source, ProgressTracker pt) throws IOException, ParseException { 376 Node rootnode; 377 Node[] nodes; 378 379 rootnode=Parser.parse(in,source); 381 382 if (pt!=null) { 383 pt.done(3); } 385 386 388 Package pakkage; 390 Node pak=rootnode.getChild(JJT_PACKAGE); 391 if (pak!=null) { 392 pakkage=new Package (); 393 pakkage.initFromAST(pak); 394 } 395 else { 396 pakkage=basePackage; 397 } 398 399 nodes=rootnode.getChildren(JJT_IMPORT); 401 Vector imports=new Vector(); 402 for (int i=0;i<nodes.length;i++) { 403 imports.addElement(Import.createFromAST(basePackage,nodes[i])); 404 } 405 406 nodes=rootnode.getChildren(JJT_INTERFACE); 408 for (int i=0;i<nodes.length;i++) { 409 Class c=new Class (); 410 c.setPackage(pakkage); 411 NamedIterator it=c.getImports(); 412 for (Enumeration e=imports.elements();e.hasMoreElements();) { 413 Import im=(Import)e.nextElement(); 414 it.add(im); 415 } 416 c.setInterface(true); 417 c.initFromAST(nodes[i]); } 419 420 nodes=rootnode.getChildren(JJT_CLASS); 422 for (int i=0;i<nodes.length;i++) { 423 Class c=new Class (); 424 c.setPackage(pakkage); 425 NamedIterator it=c.getImports(); 426 for (Enumeration e=imports.elements();e.hasMoreElements();) { 427 Import im=(Import)e.nextElement(); 428 it.add(im); 429 } 430 c.initFromAST(nodes[i]); } 432 433 basePackage.add(pakkage); 434 } 435 436 445 protected static void analysePass2(Package pack, ProgressTracker pt) throws IOException, ParseException { 446 NamedIterator it; 447 it=pack.getClasses(); 448 while (it.hasMore()) { 449 Class c=(Class )it.next(); 450 if (!c.pass2) { log("parsing pass 2: " + c.getName()); 452 c.initFromASTPass2(); 453 } 454 if (pt!=null) { 455 pt.done(1); } 457 } 458 it=pack.getInnerPackages(); 460 while (it.hasMore()) { 461 Package p=(Package )it.next(); 462 analysePass2(p,pt); 463 } 464 } 465 466 476 protected static String workaroundAvoidUnicodeSingleChar(String s) { 477 int pos = s.indexOf("'\\u"); 478 if (pos != -1) { 479 int linestart = s.lastIndexOf(nl, pos) + 1; char q = endsQuoted(s.substring(linestart, pos)); 482 if (q ==(char)0) { 483 return s.substring(0, pos) + "\"" + workaroundUnicodeSingleCharMarker + s.substring(pos+3, pos+7) + "\"" + workaroundAvoidUnicodeSingleChar(s.substring(pos+8)); 484 } else { 485 int qe = quoteEnd(s, pos, q); 486 return s.substring(0, qe+1) + workaroundAvoidUnicodeSingleChar(s.substring(qe+1)); 487 } 488 } else { 489 return s; 490 } 491 } 492 493 497 protected static String readFile(File f) throws IOException { 498 FileReader r = new FileReader(f); 499 char[] c = new char[(int)f.length()]; 500 r.read(c); 501 r.close(); 502 return new String (c); 503 } 504 505 protected static char endsQuoted(String s) { 506 char[] cc = new char[s.length()]; 507 s.getChars(0, cc.length, cc, 0); 508 boolean escaped = false; 509 char quoted = (char)0; 510 511 for (int i=0; i<cc.length;i++) { 512 char c = cc[i]; 513 if (escaped) { 514 escaped = false; 515 } else { 516 switch (c) { 517 case '\\': escaped = true; 518 break; 519 case '\"': switch (quoted) { 520 case '\'': break; 521 case '\"': quoted = (char)0; break; 523 default: quoted = '\"'; 524 break; 525 } 526 break; 527 case '\'': switch (quoted) { 528 case '\"': break; 529 case '\'': quoted = (char)0; break; 531 default: quoted = '\''; 532 break; 533 } 534 break; 535 } 536 } 537 } 538 return quoted; 539 } 540 541 protected static int quoteEnd(String s, int pos, char quoteChar) { 542 boolean escaped = false; 543 while (pos < s.length()) { 544 if (escaped) { 545 escaped = false; 546 } else { 547 char c = s.charAt(pos); 548 if (c == quoteChar) { 549 return pos; 550 } else if (c == '\\') { 551 escaped = true; 552 } 553 } 554 pos++; 555 } 556 return -1; 557 } 558 559 564 protected static void log(String msg) { 565 if (verbose) { 566 logPerformer.log(msg); 567 } 568 } 569 570 575 protected static void warning(String msg) { 576 logPerformer.log(msg); 577 } 578 579 private static boolean isInSources(File f, File[] sources) { 580 try { 581 String fc = f.getCanonicalPath(); 582 for (int i=0; i<sources.length; i++) { 583 String ffc = sources[i].getCanonicalPath(); 584 if (fc.startsWith(ffc)) { return true; 586 } 587 } 588 return false; 589 } catch (IOException ioe) { 590 return false; 591 } 592 } 593 594 } | Popular Tags |