View Javadoc

1   /*
2    * EL4J, the Extension Library for the J2EE, adds incremental enhancements to
3    * the spring framework, http://el4j.sf.net
4    * Copyright (C) 2005 by ELCA Informatique SA, Av. de la Harpe 22-24,
5    * 1000 Lausanne, Switzerland, http://www.elca.ch
6    *
7    * EL4J is published under the GNU Lesser General Public License (LGPL)
8    * Version 2.1. See http://www.gnu.org/licenses/
9    *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13   * GNU Lesser General Public License for more details.
14   *
15   * For alternative licensing, please contact info@elca.ch
16   */
17  
18  package ch.elca.el4j.services.remoting;
19  
20  import java.io.Serializable;
21  import java.lang.reflect.InvocationHandler;
22  import java.lang.reflect.InvocationTargetException;
23  import java.lang.reflect.Method;
24  import java.util.Map;
25  
26  import org.slf4j.Logger;
27  import org.slf4j.LoggerFactory;
28  
29  import ch.elca.el4j.core.contextpassing.ImplicitContextPassingRegistry;
30  
31  /**
32   * This class passes the context additionally with every method call.
33   *
34   * @svnLink $Revision: 3883 $;$Date: 2009-08-04 15:35:01 +0200 (Di, 04. Aug 2009) $;$Author: swismer $;$URL: https://el4j.svn.sourceforge.net/svnroot/el4j/branches/el4j_3_1/el4j/framework/modules/remoting_core/src/main/java/ch/elca/el4j/services/remoting/ServerContextInvocationHandler.java $
35   *
36   * @author Martin Zeltner (MZE)
37   */
38  public class ServerContextInvocationHandler
39  	implements InvocationHandler, Serializable {
40  	
41  	/**
42  	 * Private logger.
43  	 */
44  	private static Logger s_logger = LoggerFactory
45  			.getLogger(ServerContextInvocationHandler.class);
46  
47  	/**
48  	 * Is the implementation of the service which has to be called.
49  	 */
50  	private final Object m_service;
51  
52  	/**
53  	 * Is the service interface which is implemented by the service.
54  	 */
55  	private final Class m_serviceInterface;
56  
57  	/**
58  	 * Is the registry for the implicit context passing.
59  	 */
60  	private final ImplicitContextPassingRegistry
61  		m_implicitContextPassingRegistry;
62  
63  	/**
64  	 * Constructor.
65  	 *
66  	 * @param service
67  	 *              Is the real service which does the work.
68  	 * @param serviceInterface
69  	 *              Is the interface which the service has implemented.
70  	 * @param implicitContextPassingRegistry
71  	 *              Is the implicit context passing registry.
72  	 */
73  	public ServerContextInvocationHandler(Object service,
74  			Class serviceInterface,
75  			ImplicitContextPassingRegistry implicitContextPassingRegistry) {
76  		m_service = service;
77  		m_serviceInterface = serviceInterface;
78  		m_implicitContextPassingRegistry = implicitContextPassingRegistry;
79  		if (m_implicitContextPassingRegistry == null) {
80  			s_logger.warn("No ImplicitContextPassingRegistry defined! "
81  					+ "Context will not be passed through.");
82  		}
83  	}
84  	
85  	/**
86  	 * {@inheritDoc}
87  	 */
88  	public Object invoke(Object proxy, Method method, Object[] args)
89  		throws Throwable {
90  		Method m;
91  		Object[] newArgs;
92  		String methodName = method.getName();
93  		Class[] methodParametersTypes = method.getParameterTypes();
94  		Class declaringClass = method.getDeclaringClass();
95  		
96  		/* HACK Here we should ensure that the declaring class is the interface
97  		 *      which the proxy was created for (and not just testing whether
98  		 *      the method is declared in an (arbitrary) interface). But this
99  		 *      resulted in a very strange behaviour in EJB containers, which
100 		 *      weren't able anymore to reactivate passivated beans (i.e. they
101 		 *      threw a ClassNotFoundException).
102 		 */
103 		if (declaringClass.isInterface()) {
104 			Class[] methodParametersTypesWithoutContext
105 				= new Class[methodParametersTypes.length - 1];
106 			for (int i = 0;
107 				i < methodParametersTypesWithoutContext.length; i++) {
108 				methodParametersTypesWithoutContext[i]
109 					= methodParametersTypes[i];
110 			}
111 	
112 			m = m_serviceInterface.getMethod(methodName,
113 					methodParametersTypesWithoutContext);
114 	
115 			newArgs = new Object[args.length - 1];
116 			for (int i = 0; i < newArgs.length; i++) {
117 				newArgs[i] = args[i];
118 			}
119 			Map map = (Map) args[args.length - 1];
120 			if (m_implicitContextPassingRegistry != null) {
121 				m_implicitContextPassingRegistry.pushAssembledImplicitContext(
122 					map);
123 			}
124 		} else {
125 			m = declaringClass.getMethod(methodName, methodParametersTypes);
126 			newArgs = args;
127 		}
128 
129 		try {
130 			return m.invoke(m_service, newArgs);
131 		} catch (InvocationTargetException e) {
132 			throw e.getTargetException();
133 		}
134 	}
135 }