blob: 45b1476b1519ba411eade79ba7e0c15bbf123d37 [file] [log] [blame]
/**
*
* Copyright 2005 the original author or authors.
*
* Licensed 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.gbean.proxy;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import javax.management.ObjectName;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.CallbackFilter;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.NoOp;
import org.gbean.kernel.Kernel;
import org.gbean.kernel.ServiceName;
import org.gbean.kernel.ServiceNotFoundException;
import org.gbean.reflect.ServiceInvoker;
import org.gbean.reflect.ServiceInvokerManager;
/**
* @version $Rev$ $Date$
*/
public class ProxyManager {
private static ObjectName PROXY_MANAGER_QUERY = ServiceName.createName("*:j2eeType=ProxyManager,*");
public static ProxyManager findProxyManager(Kernel kernel) throws ServiceNotFoundException {
Set names = kernel.listServiceNames(PROXY_MANAGER_QUERY);
if (names.isEmpty()) {
throw new IllegalStateException("Proxy mananger could not be found in kernel: " + PROXY_MANAGER_QUERY);
}
if (names.size() > 1) {
throw new IllegalStateException("More then one proxy manangers were found in kernel: " + PROXY_MANAGER_QUERY);
}
ObjectName proxyManagerName = (ObjectName) names.iterator().next();
return (ProxyManager) kernel.getService(proxyManagerName);
}
private final ServiceInvokerManager serviceInvokerManager;
private final Map interceptors = new WeakHashMap();
public ProxyManager(ServiceInvokerManager serviceInvokerManager) {
this.serviceInvokerManager = serviceInvokerManager;
}
public synchronized ProxyFactory createProxyFactory(Class type) {
assert type != null: "type is null";
return new FastProxyFactory(type);
}
public synchronized Object createProxy(ObjectName target, Class type) throws ServiceNotFoundException {
return createProxy(target, type, null);
}
public synchronized Object createProxy(ObjectName target, Class type, Object data) throws ServiceNotFoundException {
assert type != null: "type is null";
assert target != null: "target is null";
return new FastProxyFactory(type).createProxy(target, data);
}
public boolean isProxy(Object proxy) {
return interceptors.containsKey(proxy);
}
public synchronized ObjectName getProxyTarget(Object proxy) {
ProxyMethodInterceptor methodInterceptor = (ProxyMethodInterceptor) interceptors.get(proxy);
if (methodInterceptor == null) {
return null;
}
return methodInterceptor.getObjectName();
}
public synchronized Object getProxyData(Object proxy) {
ProxyMethodInterceptor methodInterceptor = (ProxyMethodInterceptor) interceptors.get(proxy);
if (methodInterceptor == null) {
return null;
}
return methodInterceptor.getData();
}
private class FastProxyFactory implements ProxyFactory {
private final Class type;
private final Enhancer enhancer;
public FastProxyFactory(Class type) {
enhancer = new Enhancer();
enhancer.setSuperclass(type);
enhancer.setCallbackTypes(new Class[]{NoOp.class, MethodInterceptor.class});
enhancer.setCallbackFilter(FILTER);
enhancer.setUseFactory(false);
this.type = enhancer.createClass();
}
public synchronized Object createProxy(ObjectName target) throws ServiceNotFoundException {
return createProxy(target, null);
}
public synchronized Object createProxy(ObjectName target, Object data) throws ServiceNotFoundException {
assert target != null: "target is null";
ServiceInvoker serviceInvoker = serviceInvokerManager.getServiceInvoker(target);
ProxyMethodInterceptor interceptor = new ProxyMethodInterceptor(type, serviceInvoker, target, data);
// @todo trap CodeGenerationException indicating missing no-arg ctr
enhancer.setCallbacks(new Callback[]{NoOp.INSTANCE, interceptor});
Object proxy = enhancer.create();
interceptors.put(proxy, interceptor);
return proxy;
}
}
private static final CallbackFilter FILTER = new CallbackFilter() {
public int accept(Method method) {
if (method.getName().equals("finalize") &&
method.getParameterTypes().length == 0 &&
method.getReturnType() == Void.TYPE) {
return 0;
}
return 1;
}
};
}