2
* JBoss, Home of Professional Open Source
3
* Copyright 2005, JBoss Inc., and individual contributors as indicated
4
* by the @authors tag. See the copyright.txt in the distribution for a
5
* full listing of individual contributors.
7
* This is free software; you can redistribute it and/or modify it
8
* under the terms of the GNU Lesser General Public License as
9
* published by the Free Software Foundation; either version 2.1 of
10
* the License, or (at your option) any later version.
12
* This software is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this software; if not, write to the Free
19
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
23
package org.jboss.remoting.marshal;
25
import java.io.ByteArrayOutputStream;
26
import java.io.IOException;
27
import java.io.InputStream;
29
import java.util.Iterator;
30
import java.util.List;
32
import javax.management.MBeanServer;
33
import org.jboss.logging.Logger;
34
import org.jboss.remoting.InvocationRequest;
35
import org.jboss.remoting.InvokerLocator;
36
import org.jboss.remoting.ServerInvocationHandler;
37
import org.jboss.remoting.ServerInvoker;
38
import org.jboss.remoting.callback.InvokerCallbackHandler;
39
import org.jboss.remoting.loading.ClassBytes;
40
import org.jboss.remoting.loading.ClassUtil;
43
* The invocation handler that receives requests for getting marshallers/unmarshallers and
44
* loading of these and any related classes to remoting client.
46
* @author <a href="mailto:tom@jboss.org">Tom Elrod</a>
48
public class MarshallerLoaderHandler implements ServerInvocationHandler, MarshallerLoaderConstants
50
private ServerInvoker invoker = null;
51
private MBeanServer server = null;
52
private List classLoaders;
54
protected final static Logger log = Logger.getLogger(MarshallerLoaderHandler.class);
56
public MarshallerLoaderHandler(List classLoaders)
58
this.classLoaders = classLoaders;
62
* set the mbean server that the handler can reference
66
public void setMBeanServer(MBeanServer server)
72
* set the invoker that owns this handler
76
public void setInvoker(ServerInvoker invoker)
78
this.invoker = invoker;
82
* called to handle a specific invocation. Please take care to make sure implementations are thread safe and can,
83
* and often will, receive concurrent calls on this method.
89
public Object invoke(InvocationRequest invocation)
94
Object param = invocation.getParameter();
95
Map metadMap = invocation.getRequestPayload();
98
throw new RuntimeException("Can not load class as invocation request metadat map is null.");
101
String dataType = (String) metadMap.get(InvokerLocator.DATATYPE);
103
log.debug("MarshallerLoaderHandler received invocation with param of " + param + " and data type of " + dataType);
105
if(GET_MARSHALLER_METHOD.equals(param))
107
ret = MarshalFactory.getMarshaller(dataType, invoker.getSerializationType());
109
else if(GET_UNMARSHALLER_METHOD.equals(param))
111
ret = MarshalFactory.getUnMarshaller(dataType, invoker.getSerializationType());
113
else if(LOAD_CLASS_METHOD.equals(param))
115
String className = (String) metadMap.get(CLASSNAME);
116
log.debug("MarshallerLoaderHandler: loading class: " + className);
117
if(className != null)
119
ret = loadClassBytes(className, invoker.getClassLoader());
120
log.debug("MarshallerLoaderHandler: returning class: " + className + ": " + ret);
124
log.error("Received invocation " + param + " to load class, but metadata map key " + CLASSNAME +
125
" contains a null value for the class name to load.");
128
else if(LOAD_MARSHALLER_METHOD.equals(param))
130
// load based on data type
131
Marshaller marshaller = MarshalFactory.getMarshaller(dataType, invoker.getSerializationType());
132
if(marshaller != null)
134
String className = marshaller.getClass().getName();
135
ret = loadClassBytes(className, invoker.getClassLoader());
139
log.warn("Could not find registered marshaller for data type: " + dataType);
142
else if(LOAD_UNMARSHALLER_METHOD.equals(param))
144
UnMarshaller unmarshaller = MarshalFactory.getUnMarshaller(dataType, invoker.getSerializationType());
145
if(unmarshaller != null)
147
String className = unmarshaller.getClass().getName();
148
ret = loadClassBytes(className, invoker.getClassLoader());
152
log.warn("Could not find registered unmarshaller for data type: " + dataType);
157
log.warn("Received invocation with unknown parameter request: " + param);
164
private Object loadClassBytes(String className, ClassLoader classLoader)
166
ClassBytes classBytes = null;
168
if(className != null)
170
byte[] classDefinition = ClassUtil.getClassBytes(className, classLoader);
172
if (classDefinition == null && classLoaders != null)
174
Iterator it = classLoaders.iterator();
177
ClassLoader cl = (ClassLoader) it.next();
178
log.debug("trying classLoader " + cl);
179
classDefinition = ClassUtil.getClassBytes(className, cl);
180
if (classDefinition != null)
187
if (classDefinition == null)
189
log.debug("unable to load class " + className);
191
classBytes = new ClassBytes(className, classDefinition);
197
* Adds a callback handler that will listen for callbacks from the server invoker handler.
199
* @param callbackHandler
201
public void addListener(InvokerCallbackHandler callbackHandler)
203
//NO OP as don't won't allow listeners
207
* Removes the callback handler that was listening for callbacks from the server invoker handler.
209
* @param callbackHandler
211
public void removeListener(InvokerCallbackHandler callbackHandler)
213
//NO OP as don't won't allow listeners
217
* Adapted from org.jboss.mx.loading.RepositoryClassLoader.
222
* @throws ClassNotFoundException
223
* @throws IOException
225
protected byte[] loadByteCode(ClassLoader cl, String classname)
226
throws ClassNotFoundException, IOException
228
byte[] bytecode = null;
229
URL classURL = getClassURL(cl, classname);
231
// Load the class bytecode
232
InputStream is = null;
235
is = classURL.openStream();
236
ByteArrayOutputStream baos = new ByteArrayOutputStream();
237
byte[] tmp = new byte[1024];
239
while( (read = is.read(tmp)) > 0 )
241
baos.write(tmp, 0, read);
243
bytecode = baos.toByteArray();
255
* Adapted from org.jboss.mx.loading.RepositoryClassLoader.
260
* @throws ClassNotFoundException
262
private URL getClassURL(ClassLoader cl, String classname) throws ClassNotFoundException
264
String classRsrcName = classname.replace('.', '/') + ".class";
265
URL classURL = cl.getResource(classRsrcName);
266
if( classURL == null )
268
String msg = "Failed to find: "+classname+" as resource: "+classRsrcName;
269
throw new ClassNotFoundException(msg);