001: package tide.jaranalysis;
002:
003: import snow.utils.storage.*;
004: import tide.sources.LibFileItem;
005: import tide.classsyntax.SingleClassLoader;
006: import tide.editor.MainEditorFrame;
007: import snow.utils.storage.FileUtils;
008: import java.util.zip.*;
009: import java.io.*;
010: import java.util.*;
011:
012: /** Scans bytecode of all classes in a lib.
013: * Now: search and remember
014: * -interfaces, annotations.
015: * Should be ran lazilly once for each new libs and stored (persistent).
016: * Is used to offer annotation completion.
017: * Currently ignores internal classes (no need now...)
018: */
019: public final class LibClassesInfo {
020: final static boolean ignoreInternalClasses = true; //TODO later if more needed.
021: //Map<String, ZipEntry> entryForName = new HashMap<String, ZipEntry>();
022: Set<String> interfaces = new HashSet<String>();
023: Set<String> annotations = new HashSet<String>();
024: //ZipFile zf = null;
025: String libID = "?";
026:
027: // Static for the whole update
028: static int totSuccess = 0;
029: static int totFails = 0;
030:
031: // for one instance
032: int success = 0;
033: int fails = 0;
034:
035: public LibClassesInfo(ZipFile file, SingleClassLoader cl)
036: throws Exception {
037: libID = getUNiqueIDForFile(file);
038: scan(file, cl);
039: }
040:
041: public LibClassesInfo(StorageVector srep) {
042: create(srep);
043: }
044:
045: @SuppressWarnings("unchecked")
046: public void create(StorageVector srep) {
047: // int version = (Integer) srep.get(0);
048: libID = (String) srep.get(1);
049:
050: interfaces.clear();
051: interfaces.addAll((List<String>) srep.get(2));
052:
053: annotations.clear();
054: annotations.addAll((List<String>) srep.get(3));
055:
056: if (srep.size() > 4) {
057: success = (Integer) srep.get(4);
058: }
059: if (srep.size() > 5) {
060: fails = (Integer) srep.get(5);
061: }
062: }
063:
064: public StorageVector getRep() {
065: StorageVector srep = new StorageVector();
066: srep.add(1); //int version
067: srep.add(libID);
068: srep.add(new ArrayList<String>(interfaces));
069: srep.add(new ArrayList<String>(annotations));
070: srep.add(success);
071: srep.add(fails);
072: return srep;
073: }
074:
075: private void scan(ZipFile zf, SingleClassLoader cl)
076: throws Exception {
077: System.out.println("Scanning " + zf.getName());
078: success = 0;
079: fails = 0;
080: // scan all entries
081: Enumeration<? extends ZipEntry> entries = zf.entries();
082: wl: while (entries.hasMoreElements()) {
083: ZipEntry ze = entries.nextElement();
084: if (ze.getName().toLowerCase().endsWith(".class")) {
085: String name = ze.getName();
086: name = name.substring(0, name.length() - 6).replace(
087: '/', '.');
088:
089: if (name.indexOf('$') > 0) {
090: //System.out.println("ics: "+name);
091: if (ignoreInternalClasses) {
092: continue wl;
093: }
094: }
095:
096: //debug: System.out.println(""+name);
097: try {
098: Class cla = cl.findClass(name);
099: if (cla != null) {
100: if (cla.isAnnotation()) {
101: annotations.add(name);
102: } else if (cla.isInterface()) // ELSE is important here !, because an annotation is also an interface.
103: {
104: interfaces.add(name);
105: }
106: success++;
107: } else {
108: System.out.println("Cannot classload " + name); //+" in "+zf);
109: fails++;
110: }
111: } catch (Exception e1) {
112: fails++;
113: } catch (Error e2) {
114: fails++;
115: }
116: }
117: }
118:
119: totSuccess += success;
120: totFails += fails;
121:
122: //System.out.println("fails: "+fails+", success: "+success);
123: }
124:
125: @Override
126: public final String toString() {
127: StringBuilder sb = new StringBuilder("" + libID + ": "
128: + annotations.size() + " annotations, "
129: + interfaces.size() + " interfaces found. " + success
130: + " success, " + fails + " fails.");
131: return sb.toString();
132: }
133:
134: public static boolean hasInfo(File f) {
135: // use as unique ID: name and length
136: String fid = getUNiqueIDForFileName(f);
137: File fidLoc = new File(System.getProperty("user.home"),
138: "/.tide_global/" + fid);
139: return fidLoc.exists();
140: }
141:
142: /** Should only be created if not hasInfo(f)...
143: * stores the newly created info
144: * @param scl if null a new will be created.
145: */
146: private static LibClassesInfo createInfo(ZipFile zf,
147: SingleClassLoader scl) throws Exception {
148: File zfile = new File(zf.getName());
149: String fid = getUNiqueIDForFileName(zfile);
150: File fold = new File(System.getProperty("user.home"),
151: "/.tide_global/");
152: if (!fold.exists()) {
153: fold.mkdirs();
154: }
155:
156: File fidLoc = new File(fold, fid);
157:
158: boolean innerSCL = false;
159: if (scl == null) {
160: innerSCL = true;
161: scl = SingleClassLoader.createSingleClassLoader(false);
162: }
163: LibClassesInfo lci = new LibClassesInfo(zf, scl);
164:
165: if (innerSCL) {
166: scl.terminate();
167: }
168:
169: StorageVector sr = lci.getRep();
170: FileUtils.saveZippedVectorToFile(fidLoc, sr);
171:
172: return lci;
173: }
174:
175: private static LibClassesInfo loadStoredInfo(ZipFile zf)
176: throws Exception {
177: File zfile = new File(zf.getName());
178: String fid = getUNiqueIDForFileName(zfile);
179: File fold = new File(System.getProperty("user.home"),
180: "/.tide_global/");
181: File fidLoc = new File(fold, fid);
182: return new LibClassesInfo(FileUtils
183: .loadZippedVectorFromFile3(fidLoc));
184: }
185:
186: /** Simple name + length
187: */
188: public static String getUNiqueIDForFileName(File f) {
189: return f.getName() + "_" + f.length();
190: }
191:
192: /** Simple name + length
193: */
194: public static String getUNiqueIDForFile(ZipFile zf) {
195: File f = new File(zf.getName());
196: return f.getName() + "_" + f.length();
197: }
198:
199: /** Call this with minimum priority...
200: * Updates the infos about known interfaces and annotations in the libraries.
201: */
202: public static void update_(List<LibFileItem> allLibs) {
203: totFails = 0;
204: totSuccess = 0;
205: long t0 = System.currentTimeMillis();
206: System.out.println("Analysing " + allLibs.size()
207: + " libraries class contents");
208: try {
209: SingleClassLoader scl = SingleClassLoader
210: .createSingleClassLoader(true);
211:
212: fl: for (LibFileItem fi : allLibs) {
213: //System.out.println("\nAnalysing "+fi);
214: if (fi.isIgnored())
215: continue fl;
216:
217: if (fi instanceof LibFileItem.LibFileRoot) {
218: LibFileItem.LibFileRoot lfr = (LibFileItem.LibFileRoot) fi;
219:
220: ZipFile zf = lfr.file;
221: File zfile = new File(zf.getName());
222: final LibClassesInfo lci;
223: if (!hasInfo(zfile)) {
224: lci = createInfo(zf, null); // and also stores !. null => recreates one at each lib...
225: System.out.println("" + lci);
226: } else {
227: lci = loadStoredInfo(zf);
228: }
229:
230: // Register...
231: MainEditorFrame.instance.librariesPanel
232: .getTreeModel().knownAnnotations
233: .addAll(lci.annotations);
234: MainEditorFrame.instance.librariesPanel
235: .getTreeModel().knownInterfaces
236: .addAll(lci.interfaces);
237: } else {
238: // TODO: generalize (name + _ + timestamp) no problem...
239: System.out.println("Cannot analyse: " + fi);
240: }
241: }
242:
243: scl.terminate();
244:
245: if (totFails + totSuccess > 0) {
246: System.out
247: .println("Total for new analysis (not for loaded):: fails: "
248: + totFails
249: + ", success: "
250: + totSuccess
251: + " ("
252: + (System.currentTimeMillis() - t0)
253: + " ms)");
254: MainEditorFrame.instance.outputPanels.tideOutputPanel.doc
255: .appendLine("New lib classes scanned: fails: "
256: + totFails + ", success: " + totSuccess);
257:
258: // 1.6.0_01
259: // Total for new analysis (not for loaded):: fails: 1652, success: 12687
260: // Total for new analysis (not for loaded):: fails: 777, success: 13562 // when loading sun and com.sun from system.
261: // 1.5 New lib classes scanned: fails: 1365, success: 10616
262: // 1.7 New lib classes scanned: fails: 893, success: 12457
263:
264: // using syst and if not ok, passing to normal:
265: // 1.6 New lib classes scanned: fails: 92, success: 12331
266: // 1.5 New lib classes scanned: fails: 172, success: 11809
267: // 1.7 New lib classes scanned: fails: 98, success: 14214
268:
269: // 1.6.0_05
270: // Total for new analysis (not for loaded):: fails: 2, success: 12030
271:
272: }
273: } catch (Exception e) {
274: // todo...
275: e.printStackTrace();
276: }
277: }
278: }
|