/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.tuscany.sca.binding.ejb.corba;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import javax.rmi.CORBA.Stub;
import net.sf.cglib.core.NamingPolicy;
import net.sf.cglib.core.Predicate;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.CallbackFilter;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.FixedValue;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.NoOp;
/**
* @version $Revision: 665774 $ $Date: 2008-06-09 18:05:18 +0100 (Mon, 09 Jun 2008) $
*/
public class DynamicStubClassLoader extends ClassLoader {
private static final String PACKAGE_PREFIX = "org.omg.stub.";
@Override
public synchronized Class loadClass(final String name) throws ClassNotFoundException {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
// check if the stub already exists first
try {
return classLoader.loadClass(name);
} catch (ClassNotFoundException e) {
}
// if this is not a class from the org.omg.stub name space don't attempt to generate
if (!name.startsWith(PACKAGE_PREFIX)) {
throw new ClassNotFoundException("Could not load class: " + name);
}
// load the interfaces class we are attempting to create a stub for
Class iface = loadStubInterfaceClass(name, classLoader);
// create the stub builder
try {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Stub.class);
enhancer.setInterfaces(new Class[] {iface});
enhancer.setCallbackFilter(FILTER);
enhancer.setCallbackTypes(new Class[] {NoOp.class, MethodInterceptor.class, FixedValue.class});
enhancer.setUseFactory(false);
enhancer.setClassLoader(classLoader);
enhancer.setNamingPolicy(new NamingPolicy() {
public String getClassName(String s, String s1, Object o, Predicate predicate) {
return name;
}
});
// generate the class
Class result = enhancer.createClass();
assert result != null;
StubMethodInterceptor interceptor = new StubMethodInterceptor(iface);
Ids ids = new Ids(iface);
Enhancer.registerStaticCallbacks(result, new Callback[] {NoOp.INSTANCE, interceptor, ids});
return result;
} catch (RuntimeException e) {
throw e;
} catch (Error e) {
throw e;
}
}
private Class loadStubInterfaceClass(String name, ClassLoader classLoader) throws ClassNotFoundException {
try {
int begin = name.lastIndexOf('.') + 1;
String iPackage = name.substring(13, begin);
String iName = iPackage + name.substring(begin + 1, name.length() - 5);
return classLoader.loadClass(iName);
} catch (ClassNotFoundException e) {
// don't log exceptions from CosNaming because it attempts to load every
// class bound into the name server
//FIXME this variable is never read, can we remove the
// whole block of code??
//boolean shouldLog = true;
StackTraceElement[] stackTrace = e.getStackTrace();
for (int i = 0; i < stackTrace.length; i++) {
StackTraceElement stackTraceElement = stackTrace[i];
if (stackTraceElement.getClassName().equals("org.omg.CosNaming.NamingContextExtPOA") && stackTraceElement
.getMethodName().equals("_invoke")) {
//shouldLog = false;
break;
}
}
throw new ClassNotFoundException("Unable to generate stub", e);
}
}
private static final CallbackFilter FILTER = new CallbackFilter() {
public int accept(Method method) {
// we don't intercept non-public methods like finalize
if (!Modifier.isPublic(method.getModifiers())) {
return 0;
}
if (method.getReturnType().equals(String[].class) && method.getParameterTypes().length == 0
&& method.getName().equals("_ids")) {
return 2;
}
if (Modifier.isAbstract(method.getModifiers())) {
return 1;
}
return 0;
}
};
private static final class Ids implements FixedValue {
private final String[] typeIds;
public Ids(Class type) {
typeIds = Java2IDLUtil.createCorbaIds(type);
}
public Object loadObject() throws Exception {
return typeIds;
}
}
}