From 9dc27b3f428b8be215e57863642879dfaa5bb0b2 Mon Sep 17 00:00:00 2001 From: erik Date: Thu, 22 Jul 2010 08:47:42 +0000 Subject: [PATCH] --- .../ThreadSpecificInvocationHandler.java | 80 +++++++++++++++++++ .../general/ThreadSpecificProxyFactory.java | 56 ++----------- .../wamblee/reflection/AnnotationUtils.java | 1 - 3 files changed, 87 insertions(+), 50 deletions(-) create mode 100644 support/general/src/main/java/org/wamblee/general/ThreadSpecificInvocationHandler.java diff --git a/support/general/src/main/java/org/wamblee/general/ThreadSpecificInvocationHandler.java b/support/general/src/main/java/org/wamblee/general/ThreadSpecificInvocationHandler.java new file mode 100644 index 00000000..49c2e177 --- /dev/null +++ b/support/general/src/main/java/org/wamblee/general/ThreadSpecificInvocationHandler.java @@ -0,0 +1,80 @@ +/* + * Copyright 2005-2010 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.wamblee.general; + +import java.io.Serializable; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Invocation handler for thread-specific proxies. + * + * @author Erik Brakkee + * + * @param + */ +class ThreadSpecificInvocationHandler implements InvocationHandler, Serializable { + + /** + * We store a map of unique ids of invocation handlers to thread local storage of the + * service. In this way, serialiability of the generated proxy is obtained (required by + * framweorks such as wicket). Also, different factories will still be separate and never + * use the same threadlocal storage. + */ + private static Map STORAGE = initializeThreadLocal(); + + private static AtomicInteger COUNTER = new AtomicInteger(); + + private static Map initializeThreadLocal() { + Map map = new ConcurrentHashMap(); + return map; + } + + + private int id; + private Class clazz; + + /** + * Constructs the handler. + * @param aSvc Thread local for the service. + * @param aClass Service interface class. + */ + public ThreadSpecificInvocationHandler(ThreadLocal aSvc, Class aClass) { + id = COUNTER.incrementAndGet(); + clazz = aClass; + STORAGE.put(id, aSvc); + } + + @Override + public Object invoke(Object aProxy, Method aMethod, Object[] aArgs) + throws Throwable { + + ThreadLocal local = STORAGE.get(id); + T actualSvc = local.get(); + if ( aMethod.getName().equals("toString") && actualSvc == null) { + return "Thread-specific proxy for '" + clazz.getName() + "' id = " + id; + } + try { + return aMethod.invoke(actualSvc, aArgs); + } catch (InvocationTargetException e) { + throw e.getCause(); + } + } +} \ No newline at end of file diff --git a/support/general/src/main/java/org/wamblee/general/ThreadSpecificProxyFactory.java b/support/general/src/main/java/org/wamblee/general/ThreadSpecificProxyFactory.java index 036a6828..e3b687df 100644 --- a/support/general/src/main/java/org/wamblee/general/ThreadSpecificProxyFactory.java +++ b/support/general/src/main/java/org/wamblee/general/ThreadSpecificProxyFactory.java @@ -15,14 +15,8 @@ */ package org.wamblee.general; -import java.io.Serializable; import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.lang.reflect.Proxy; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; /** * Thread-specific proxy is used to create implementations of interfaces that @@ -39,48 +33,18 @@ import java.util.UUID; * * This class is mostly used by infrastructure code (utilities) and test tools. * + * Care has been taken so that the invocation handler is serializable. + * However, it is only serializable within one virtual machine. It cannot be used in a distributed context + * where it can be sent to another JVM. + * * @param T * Interface to proxy. * @author Erik Brakkee * */ public class ThreadSpecificProxyFactory { + - /** - * We store a map of unique ids of invocation handlers to thread local storage of the - * service. In this way, serialiability of the generated proxy is obtained (required by - * framweorks such as wicket). Also, different factories will still be separate and never - * use the same threadlocal storage. - */ - private static Map STORAGE = - initializeThreadLocal(); - - private static class ThreadSpecificInvocationHandler implements InvocationHandler, Serializable { - - private String id; - private Class clazz; - - public ThreadSpecificInvocationHandler(String aId, Class aClass) { - id = aId; - clazz = aClass; - } - - @Override - public Object invoke(Object aProxy, Method aMethod, Object[] aArgs) - throws Throwable { - ThreadLocal local = STORAGE.get(id); - T actualSvc = local.get(); - if ( aMethod.getName().equals("toString") && actualSvc == null) { - return "Thread-specific proxy for '" + clazz.getName() + "'"; - } - try { - return aMethod.invoke(actualSvc, aArgs); - } catch (InvocationTargetException e) { - throw e.getCause(); - } - } - } - private ThreadLocal svc; private Class clazz; private T proxy; @@ -99,11 +63,7 @@ public class ThreadSpecificProxyFactory { svc = new ThreadLocal(); clazz = aClass; proxy = createProxy(); - } - - private static Map initializeThreadLocal() { - Map map = new HashMap(); - return map; + } /** @@ -137,9 +97,7 @@ public class ThreadSpecificProxyFactory { } private T createProxy() { - String id = UUID.randomUUID().toString(); - STORAGE.put(id, svc); - InvocationHandler handler = new ThreadSpecificInvocationHandler(id, clazz); + InvocationHandler handler = new ThreadSpecificInvocationHandler(svc, clazz); Class proxyClass = Proxy.getProxyClass(clazz.getClassLoader(), new Class[] { clazz }); T proxyObj; diff --git a/support/general/src/main/java/org/wamblee/reflection/AnnotationUtils.java b/support/general/src/main/java/org/wamblee/reflection/AnnotationUtils.java index 5ea776b3..dad07b5f 100644 --- a/support/general/src/main/java/org/wamblee/reflection/AnnotationUtils.java +++ b/support/general/src/main/java/org/wamblee/reflection/AnnotationUtils.java @@ -38,7 +38,6 @@ public class AnnotationUtils { * Annotation that must be present. * @return List of accessors. Empty list is returned if no match is found. */ - // TODO move generic analysis part to the reflection package. public static List analyse(Class aClass, Class aAnnotation) { List result = new ArrayList(); -- 2.31.1