001: /**************************************************************************************
002: * Copyright (c) Jonas BonŽr, Alexandre Vasseur. All rights reserved. *
003: * http://aspectwerkz.codehaus.org *
004: * ---------------------------------------------------------------------------------- *
005: * The software in this package is published under the terms of the LGPL license *
006: * a copy of which has been included with this distribution in the license.txt file. *
007: **************************************************************************************/package org.codehaus.aspectwerkz.hook.impl;
008:
009: import org.codehaus.aspectwerkz.hook.ClassPreProcessor;
010:
011: import java.io.File;
012: import java.io.IOException;
013: import java.net.MalformedURLException;
014: import java.net.URL;
015: import java.util.ArrayList;
016: import java.util.Collections;
017: import java.util.Enumeration;
018: import java.util.Hashtable;
019: import java.util.Iterator;
020: import java.util.List;
021: import java.util.Map;
022: import java.util.WeakHashMap;
023:
024: /**
025: * A simple implementation of class preprocessor. <p/>It does not modify the bytecode. It just prints on stdout some
026: * messages.
027: *
028: * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
029: */
030: public class StdoutPreProcessor implements ClassPreProcessor {
031: /**
032: * Classloaders repository, based on a synchronized weak hashmap key = classloader value = List of URL[]
033: * representing the local search path for .class files of the classloader value is completed at each class loading
034: */
035: private static Map classloaders;
036:
037: /**
038: * ms interval betwee classloader hierarchy printing
039: */
040: private static final long stepms = 15000;
041:
042: private static transient long lastPrinted = 0;
043:
044: private void log(String s) {
045: System.out.println(Thread.currentThread().getName()
046: + ": StdoutPreProcessor: " + s);
047: }
048:
049: public void initialize() {
050: log("initialize");
051: log("loaded by " + this .getClass().getClassLoader());
052: classloaders = Collections.synchronizedMap(new WeakHashMap());
053:
054: // register the classloader - except bootstrapCL
055: registerClassLoader(this .getClass().getClassLoader(), this
056: .getClass().getName());
057: }
058:
059: public byte[] preProcess(String klass, byte[] abyte,
060: ClassLoader caller) {
061: // emulate a -verbose:class mode
062: klass = klass.replace('.', '/') + ".class";
063: URL u = caller.getResource(klass);
064: log("> " + klass + " [" + ((u == null) ? "?" : u.toString())
065: + "] [" + caller + "]");
066:
067: /*
068: * URL uRoot = null; if (u!=null) { // u =
069: * jar:file:/C:/bea/weblogic81/server/lib/weblogic.jar!/weblogic/t3/srvr/T3Srvr.class // getPath =
070: * file:/C:/bea/weblogic81/server/lib/weblogic.jar!/weblogic/t3/srvr/T3Srvr.class // getFile =
071: * file:/C:/bea/weblogic81/server/lib/weblogic.jar!/weblogic/t3/srvr/T3Srvr.class int i =
072: * u.toString().indexOf('!'); if (i > 0) { try { uRoot = new URL(u.toString().substring(0, i)+"!/"); } catch
073: * (MalformedURLException e) { ; } } }
074: */
075: // register the classloader
076: registerClassLoader(caller, klass);
077:
078: // complete the url path of the classloader
079: registerSearchPath(caller, klass);
080:
081: // dump the hierarchy if needed
082: if (System.currentTimeMillis() > (lastPrinted + stepms)) {
083: lastPrinted = System.currentTimeMillis();
084: log("*******************************");
085: log("size=" + classloaders.size());
086: dumpHierarchy(null, "");
087: log("*******************************");
088: }
089: return abyte;
090: }
091:
092: /**
093: * Register a weak reference on the classloader Looks for META-INF/manifest.mf resource and log a line
094: *
095: * @param loader
096: * @param firstClassLoaded
097: */
098: private void registerClassLoader(ClassLoader loader,
099: String firstClassLoaded) {
100: if (loader != null) {
101: if (!classloaders.containsKey(loader)) {
102: // register the loader and the parent hierarchy if not already registered
103: registerClassLoader(loader.getParent(), loader
104: .getClass().getName());
105: registerSearchPath(loader.getParent(), loader
106: .getClass().getName());
107: URL u = null;
108:
109: // *** THIS IS NOT WORKING for other than .class files
110: // *** since manifest.mf can be several time
111: // *** but getResource follow parent first delegation model
112: // try to locate the first META-INF/manifest.mf (should be the aw.xml)
113: // case sensitive of META-INF, meta-inf, Meta-Inf, Meta-inf ? YES IT IS
114: //u = loader.getResource("META-INF/MANIFEST.MF");
115: // *** THIS could be enough for early registration
116: // add resources in some struct, allow multiple deploy of same resource
117: // if in parallel CL hierarchy - got it ?
118: try {
119: //@todo - case sensitive stuff is dangerous
120: // we could merge all aw.xml in META-INF and WEB-INF and meta-inf ...
121: Enumeration ue = loader
122: .getResources("META-INF/MANIFEST.MF");
123: if (ue.hasMoreElements()) {
124: log("--- in scope for " + loader);
125: }
126: while (ue.hasMoreElements()) {
127: log("--- " + ue.nextElement().toString());
128: }
129: } catch (IOException e) {
130: ;
131: }
132:
133: // register this loader
134: log("****" + loader + " ["
135: + ((u == null) ? "?" : u.toString()) + "] ["
136: + firstClassLoaded + ']');
137: classloaders.put(loader, new ArrayList());
138: }
139:
140: // register search path based on firstClassLoaded
141: }
142: }
143:
144: /**
145: * Dumps on stdout the registered classloader hierarchy child of "parent" Using the depth to track recursivity level
146: */
147: private void dumpHierarchy(ClassLoader parent, String depth) {
148: // do a copy of the registered CL to allow access on classloaders structure
149: List cl = new ArrayList(classloaders.keySet());
150: ClassLoader current = null;
151: for (Iterator i = cl.iterator(); i.hasNext();) {
152: current = (ClassLoader) i.next();
153: if (current.getParent() == parent) {
154: log(depth + current + '[' + classloaders.get(current));
155:
156: // handcheck for duplicate path (?)
157: List path = (List) classloaders.get(current);
158: ClassLoader currentParent = current.getParent();
159: while (currentParent != null) {
160: for (Iterator us = path.iterator(); us.hasNext();) {
161: URL u = (URL) us.next();
162: if (((List) classloaders.get(currentParent))
163: .contains(u)) {
164: log("!!!! duplicate detected for " + u
165: + " in " + current);
166: }
167: }
168: currentParent = currentParent.getParent();
169: }
170: dumpHierarchy(current, depth + " ");
171: }
172: }
173: }
174:
175: private void registerSearchPath(final ClassLoader loader,
176: final String klass) {
177: // bootCL
178: if (loader == null) {
179: return;
180: }
181:
182: // locate the klass
183: String klassFile = klass.replace('.', '/') + ".class";
184: URL uKlass = loader.getResource(klassFile);
185: if (uKlass == null) {
186: return;
187: }
188:
189: // retrieve the location root (jar/zip or directory)
190: URL uRoot = null;
191: int i = uKlass.toString().indexOf('!');
192: if (i > 0) {
193: // jar/zip
194: try {
195: // remove the jar: zip: prefix
196: //@todo !! zip: seems to be BEA specific
197: uRoot = (new File(uKlass.toString().substring(4, i)))
198: .getCanonicalFile().toURL();
199:
200: //uRoot = new URL(uKlass.toString().substring(0, i)+"!/");
201: } catch (MalformedURLException e) {
202: e.printStackTrace();
203: return;
204: } catch (IOException e2) {
205: e2.printStackTrace();
206: return;
207: }
208: } else {
209: // directory
210: i = uKlass.toString().indexOf(klassFile);
211: try {
212: uRoot = (new File(uKlass.toString().substring(0, i)))
213: .getCanonicalFile().toURL();
214: } catch (MalformedURLException e) {
215: e.printStackTrace();
216: return;
217: } catch (IOException e2) {
218: e2.printStackTrace();
219: return;
220: }
221: }
222:
223: // check if the location is not in a parent
224: ClassLoader parent = loader.getParent();
225: while (parent != null) {
226: if (((List) classloaders.get(parent)).contains(uRoot)) {
227: return;
228: }
229: parent = parent.getParent();
230: }
231:
232: // add the location if not already registered
233: // @todo !! not thread safe
234: List path = (List) classloaders.get(loader);
235: if (!path.contains(uRoot)) {
236: log("adding path " + uRoot + " to " + loader);
237: path.add(uRoot);
238: }
239: }
240:
241: public static void main(String[] args) throws Exception {
242: URL u = new URL(
243: "jar:file:/C:/bea/user_projects/domains/mydomain/myserver/.wlnotdelete/gallery/gallery-rar.jar!/");
244:
245: // differ from a "/./"
246: URL u2 = new URL(
247: "jar:file:/C:/bea/user_projects/domains/mydomain/./myserver/.wlnotdelete/gallery/gallery-rar.jar!/");
248: if (u.sameFile(u2)) {
249: System.out.println("same");
250: } else {
251: System.out.println("differ");
252: }
253: }
254: }
|