001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.geronimo.corba.util;
017:
018: import net.sf.cglib.core.NamingPolicy;
019: import net.sf.cglib.core.Predicate;
020: import net.sf.cglib.proxy.Callback;
021: import net.sf.cglib.proxy.CallbackFilter;
022: import net.sf.cglib.proxy.Enhancer;
023: import net.sf.cglib.proxy.FixedValue;
024: import net.sf.cglib.proxy.MethodInterceptor;
025: import net.sf.cglib.proxy.NoOp;
026: import org.apache.commons.logging.Log;
027: import org.apache.commons.logging.LogFactory;
028: import org.apache.geronimo.gbean.GBeanLifecycle;
029:
030: import java.lang.reflect.Method;
031: import java.lang.reflect.Modifier;
032:
033: /**
034: * @version $Revision: 451417 $ $Date: 2006-09-29 13:13:22 -0700 (Fri, 29 Sep 2006) $
035: */
036: public class DynamicStubClassLoader extends ClassLoader implements
037: GBeanLifecycle {
038: private final static Log log = LogFactory
039: .getLog(DynamicStubClassLoader.class);
040: private final static String PACKAGE_PREFIX = "org.omg.stub.";
041:
042: private boolean stopped = true;
043:
044: public synchronized Class loadClass(final String name)
045: throws ClassNotFoundException {
046: if (stopped) {
047: throw new ClassNotFoundException(
048: "DynamicStubClassLoader is stopped");
049: }
050:
051: if (log.isDebugEnabled()) {
052: log.debug("Load class " + name);
053: }
054:
055: ClassLoader classLoader = Thread.currentThread()
056: .getContextClassLoader();
057:
058: // check if the stub already exists first
059: try {
060: return classLoader.loadClass(name);
061: } catch (ClassNotFoundException e) {
062: if (log.isDebugEnabled()) {
063: log
064: .debug("Unable to load class from the context class loader");
065: }
066: }
067:
068: // if this is not a class from the org.omb.stub name space don't attempt to generate
069: if (!name.startsWith(PACKAGE_PREFIX)) {
070: if (log.isDebugEnabled()) {
071: log.debug("Could not load class: " + name);
072: }
073: throw new ClassNotFoundException("Could not load class: "
074: + name);
075: }
076:
077: // load the interfaces class we are attempting to create a stub for
078: Class iface = loadStubInterfaceClass(name, classLoader);
079:
080: // create the stub builder
081: try {
082: Enhancer enhancer = new Enhancer();
083: enhancer.setSuperclass(ClientContextHolderStub.class);
084: enhancer.setInterfaces(new Class[] { iface });
085: enhancer.setCallbackFilter(FILTER);
086: enhancer.setCallbackTypes(new Class[] { NoOp.class,
087: MethodInterceptor.class, FixedValue.class });
088: enhancer.setUseFactory(false);
089: enhancer.setClassLoader(classLoader);
090: enhancer.setNamingPolicy(new NamingPolicy() {
091: public String getClassName(String s, String s1,
092: Object o, Predicate predicate) {
093: return name;
094: }
095: });
096:
097: // generate the class
098: Class result = enhancer.createClass();
099: assert result != null;
100:
101: StubMethodInterceptor interceptor = new StubMethodInterceptor(
102: iface);
103: Ids ids = new Ids(iface);
104: Enhancer.registerStaticCallbacks(result, new Callback[] {
105: NoOp.INSTANCE, interceptor, ids });
106:
107: if (log.isDebugEnabled()) {
108: log.debug("result: " + result.getName());
109: }
110: return result;
111: } catch (RuntimeException e) {
112: log.error("Unable to generate stub: " + name, e);
113: throw e;
114: } catch (Error e) {
115: log.error("Unable to generate stub: " + name, e);
116: throw e;
117: }
118: }
119:
120: private Class loadStubInterfaceClass(String name,
121: ClassLoader classLoader) throws ClassNotFoundException {
122: try {
123: int begin = name.lastIndexOf('.') + 1;
124: String iPackage = name.substring(13, begin);
125: String iName = iPackage
126: + name.substring(begin + 1, name.length() - 5);
127:
128: return classLoader.loadClass(iName);
129: } catch (ClassNotFoundException e) {
130: // don't log exceptions from CosNaming because it attempts to load every
131: // class bound into the name server
132: boolean shouldLog = true;
133: StackTraceElement[] stackTrace = e.getStackTrace();
134: for (int i = 0; i < stackTrace.length; i++) {
135: StackTraceElement stackTraceElement = stackTrace[i];
136: if (stackTraceElement.getClassName().equals(
137: "org.omg.CosNaming.NamingContextExtPOA")
138: && stackTraceElement.getMethodName().equals(
139: "_invoke")) {
140: shouldLog = false;
141: break;
142: }
143: }
144: if (shouldLog) {
145: log.error("Unable to generate stub", e);
146: }
147:
148: throw new ClassNotFoundException("Unable to generate stub",
149: e);
150: }
151: }
152:
153: private static final CallbackFilter FILTER = new CallbackFilter() {
154: public int accept(Method method) {
155: // we don't intercept non-public methods like finalize
156: if (!Modifier.isPublic(method.getModifiers())) {
157: return 0;
158: }
159:
160: if (method.getReturnType().equals(String[].class)
161: && method.getParameterTypes().length == 0
162: && method.getName().equals("_ids")) {
163: return 2;
164: }
165:
166: if (Modifier.isAbstract(method.getModifiers())) {
167: return 1;
168: }
169:
170: return 0;
171: }
172: };
173:
174: private static final class Ids implements FixedValue {
175: private final String[] typeIds;
176:
177: public Ids(Class type) {
178: typeIds = Util.createCorbaIds(type);
179: }
180:
181: public Object loadObject() throws Exception {
182: return typeIds;
183: }
184: }
185:
186: public synchronized void doStart() throws Exception {
187: UtilDelegateImpl.setClassLoader(this );
188: stopped = false;
189: }
190:
191: public synchronized void doStop() throws Exception {
192: stopped = true;
193: log.debug("Stopped");
194: }
195:
196: public synchronized void doFail() {
197: stopped = true;
198: log.warn("Failed");
199: }
200:
201: }
|