001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.aop.deployment;
023:
024: import java.io.File;
025: import java.lang.ref.WeakReference;
026: import java.net.URL;
027: import java.util.Iterator;
028:
029: import org.jboss.aop.AspectManager;
030: import org.jboss.aop.classpool.AOPClassPool;
031: import org.jboss.aop.classpool.AOPClassPoolRepository;
032: import org.jboss.aop.deployment.LoaderRepositoryUrlUtil.UrlInfo;
033: import org.jboss.mx.loading.HeirarchicalLoaderRepository3;
034: import org.jboss.mx.loading.LoaderRepository;
035: import org.jboss.mx.loading.RepositoryClassLoader;
036:
037: import javassist.ClassPool;
038: import javassist.CtClass;
039: import javassist.NotFoundException;
040: import javassist.scopedpool.ScopedClassPoolRepository;
041:
042: /**
043: * A classpool in JBoss backed by a scoped (HierarchicalLoaderRepository) loader repository
044: *
045: * @author <a href="kabir.khan@jboss.com">Kabir Khan</a>
046: * @version $Revision: 1.1 $
047: */
048: public class ScopedJBossClassPool extends JBossClassPool {
049: final static LoaderRepositoryUrlUtil LOADER_REPOSITORY_UTIL = new LoaderRepositoryUrlUtil();
050:
051: WeakReference repository = null;
052: UrlInfo urlInfo;
053: ThreadLocal lastPool = new ThreadLocal();
054:
055: protected ScopedJBossClassPool(ClassLoader cl, ClassPool src,
056: ScopedClassPoolRepository repository, File tmp, URL tmpURL) {
057: super (cl, src, repository, tmp, tmpURL);
058:
059: boolean parentFirst = false;
060: LoaderRepository loaderRepository = null;
061: ClassLoader prnt = cl;
062: while (prnt != null) {
063: if (prnt instanceof RepositoryClassLoader) {
064: loaderRepository = ((RepositoryClassLoader) prnt)
065: .getLoaderRepository();
066: if (loaderRepository instanceof HeirarchicalLoaderRepository3) {
067: parentFirst = ((HeirarchicalLoaderRepository3) loaderRepository)
068: .getUseParentFirst();
069: }
070: break;
071: }
072: prnt = cl.getParent();
073: }
074:
075: super .childFirstLookup = !parentFirst;
076: }
077:
078: private HeirarchicalLoaderRepository3 getRepository() {
079: //FIXME - Once Javassist > 3.3.0 is out use getClassLoader0() and get rid of try/catch
080: ClassLoader cl = null;
081: try {
082: cl = getClassLoader();
083: } catch (RuntimeException e) {
084: //Ignore, the ScopedClassPoll throws an exception if pool is not associated with a cl
085: }
086: if (cl != null) {
087: return (HeirarchicalLoaderRepository3) ((RepositoryClassLoader) cl)
088: .getLoaderRepository();
089: }
090: return null;
091: }
092:
093: private URL getResourceUrlForClass(String resourcename) {
094: HeirarchicalLoaderRepository3 repo = getRepository();
095: return repo.getResource(resourcename, super .getClassLoader());
096: }
097:
098: private boolean isMine(URL url) {
099: HeirarchicalLoaderRepository3 repo = getRepository();
100: if (repo != null) {
101: //The URL of the class loaded with my scoped classloader
102: if (url != null) {
103: urlInfo = LOADER_REPOSITORY_UTIL.getURLInfo(
104: getRepository(), urlInfo);
105:
106: URL[] myUrls = urlInfo.getLocalUrls();
107: String resource = url.toString();
108: for (int i = 0; i < myUrls.length; i++) {
109: if (resource.indexOf(myUrls[i].toString()) >= 0) {
110: return true;
111: }
112: }
113: return false;
114: }
115: }
116: return true;
117: }
118:
119: public CtClass getCached(String classname) {
120: if (classname == null) {
121: return null;
122: }
123:
124: if (generatedClasses.get(classname) != null) {
125: //It is a new class, and this callback is probably coming from the frozen check when creating a new nested class
126: return super .getCached(classname);
127: }
128:
129: //Is this from the scoped classloader itself of from the parent?
130: String resourcename = getResourceName(classname);
131: URL url = getResourceUrlForClass(resourcename);
132: boolean isMine = isMine(url);
133:
134: if (isMine) {
135: if (super .childFirstLookup) {
136: //Parent delegation is false, attempt to get this class out of ourselves
137: CtClass clazz = super .getCachedLocally(classname);
138: if (clazz == null) {
139: clazz = createCtClass(classname, false);
140: if (clazz != null) {
141: lockInCache(clazz);
142: }
143: }
144: if (clazz != null) {
145: return clazz;
146: }
147: }
148: return super .getCached(classname);
149: }
150:
151: try {
152: ClassPool pool = getCorrectPoolForResource(url);
153: if (pool != lastPool.get()) {
154: lastPool.set(pool);
155: return pool.get(classname);
156: }
157: } catch (NotFoundException e) {
158: } catch (StackOverflowError e) {
159: throw e;
160: } finally {
161: lastPool.set(null);
162: }
163:
164: return null;
165: }
166:
167: private ClassPool getCorrectPoolForResource(URL url) {
168: synchronized (AspectManager.getRegisteredCLs()) {
169: for (Iterator it = AspectManager.getRegisteredCLs()
170: .values().iterator(); it.hasNext();) {
171: AOPClassPool candidate = (AOPClassPool) it.next();
172: if (candidate.isUnloadedClassLoader()) {
173: AspectManager.instance().unregisterClassLoader(
174: candidate.getClassLoader());
175: continue;
176: }
177:
178: if (candidate.getClassLoader() instanceof RepositoryClassLoader) {
179: //Sometimes the ClassLoader is a proxy for MBeanProxyExt?!
180: RepositoryClassLoader rcl = (RepositoryClassLoader) candidate
181: .getClassLoader();
182: URL[] urls = rcl.getClasspath();
183: String resource = url.toString();
184: for (int i = 0; i < urls.length; i++) {
185: if (resource.indexOf(urls[i].toString()) >= 0) {
186: return candidate;
187: }
188: }
189: }
190: }
191: }
192:
193: return AOPClassPool.createAOPClassPool(ClassPool.getDefault(),
194: AOPClassPoolRepository.getInstance());
195: }
196: }
|