001 package org.extendj.ast; 002 003 import java.util.HashSet; 004 import java.io.File; 005 import java.util.Set; 006 import java.util.Collections; 007 import java.util.Collection; 008 import java.util.ArrayList; 009 import beaver.*; 010 import java.util.*; 011 import java.io.ByteArrayOutputStream; 012 import java.io.PrintStream; 013 import java.lang.reflect.InvocationTargetException; 014 import java.lang.reflect.Method; 015 import org.jastadd.util.*; 016 import java.util.zip.*; 017 import java.io.*; 018 import org.jastadd.util.PrettyPrintable; 019 import org.jastadd.util.PrettyPrinter; 020 import java.io.FileNotFoundException; 021 import java.io.BufferedInputStream; 022 import java.io.DataInputStream; 023 /** 024 * @ast class 025 * @aspect PathPart 026 * @declaredat /home/jesper/git/extendj/java4/frontend/PathPart.jadd:46 027 */ 028 public abstract class ClassSource extends java.lang.Object { 029 030 protected final PathPart sourcePath; 031 032 033 034 /** 035 * Used to represent an non-existent compilation unit source file. 036 * 037 * <p>This class source should never be used to attempt to load a class, it 038 * is simply used as a marker to indicate failure to find a compilation 039 * unit. 040 */ 041 public static final ClassSource NONE = new ClassSource(null) { 042 @Override 043 public long lastModified() { 044 return 0; 045 } 046 @Override 047 public InputStream openInputStream() { 048 throw new UnsupportedOperationException( 049 "ClassSource.NONE can not open an input stream!"); 050 } 051 @Override 052 public String pathName() { 053 return "<Unknown Source>"; 054 } 055 }; 056 057 058 059 public ClassSource(PathPart sourcePath) { 060 this.sourcePath = sourcePath; 061 } 062 063 064 065 public PathPart getSourcePath() { 066 return sourcePath; 067 } 068 069 070 071 /** 072 * @return Last modification time of the class source. 073 */ 074 abstract public long lastModified(); 075 076 077 078 /** 079 * @return Input stream pointing to the class source. 080 */ 081 abstract public InputStream openInputStream() throws IOException; 082 083 084 085 /** 086 * It is sufficient to only overload pathName if sourceName=pathName 087 * @return the full name of the class source (e.g. file path). 088 */ 089 public String sourceName() { 090 return pathName(); 091 } 092 093 094 095 /** 096 * @return the path to the source file or the enclosing jar file 097 */ 098 abstract public String pathName(); 099 100 101 102 /** 103 * It is sufficient to only overload pathName if relativeName = pathName 104 * @return the path to the source file, or the path to the file inside a 105 * jar file 106 */ 107 public String relativeName() { 108 return pathName(); 109 } 110 111 112 113 @Override 114 public String toString() { 115 return sourceName(); 116 } 117 118 119 120 /** 121 * Parses the compilation unit from this class source. 122 * 123 * NB only call this once! The input stream is closed after the compilation 124 * unit is parsed. 125 * 126 * @return parsed compilation unit, or {@code null} if something failed 127 */ 128 public CompilationUnit parseCompilationUnit(Program program) throws IOException { 129 InputStream is = openInputStream(); 130 try { 131 if (program.options().verbose()) { 132 System.out.print("Loading " + sourceName()); 133 } 134 135 long start = System.nanoTime(); 136 CompilationUnit u = program.javaParser.parse(is, sourceName()); 137 long elapsed = System.nanoTime() - start; 138 program.javaParseTime += elapsed; 139 program.numJavaFiles += 1; 140 141 u.setFromSource(true); 142 u.setClassSource(this); 143 144 if (program.options().verbose()) { 145 System.out.println(" in " + (elapsed / 1000000) + " ms"); 146 } 147 return u; 148 } catch (Exception e) { 149 System.err.println("Unexpected error of kind " + e.getClass().getName()); 150 throw new Error(sourceName() + ": " + e.getMessage(), e); 151 } finally { 152 if (is != null) { 153 try { 154 is.close(); 155 } catch (IOException e) { 156 } 157 } 158 } 159 } 160 161 162 }