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.transport.servlet;
25
import org.jboss.remoting.InvocationRequest;
26
import org.jboss.remoting.InvocationResponse;
27
import org.jboss.remoting.InvokerLocator;
28
import org.jboss.remoting.Remoting;
29
import org.jboss.remoting.marshal.MarshalFactory;
30
import org.jboss.remoting.marshal.Marshaller;
31
import org.jboss.remoting.marshal.UnMarshaller;
32
import org.jboss.remoting.marshal.VersionedMarshaller;
33
import org.jboss.remoting.marshal.VersionedUnMarshaller;
34
import org.jboss.remoting.marshal.http.HTTPMarshaller;
35
import org.jboss.remoting.marshal.http.HTTPUnMarshaller;
36
import org.jboss.remoting.transport.http.HTTPMetadataConstants;
37
import org.jboss.remoting.transport.web.WebServerInvoker;
38
import org.jboss.remoting.transport.web.WebUtil;
39
import org.jboss.remoting.util.SecurityUtility;
40
import org.jboss.logging.Logger;
42
import javax.servlet.ServletException;
43
import javax.servlet.ServletInputStream;
44
import javax.servlet.ServletOutputStream;
45
import javax.servlet.http.HttpServletRequest;
46
import javax.servlet.http.HttpServletResponse;
47
import java.io.ByteArrayInputStream;
48
import java.io.ByteArrayOutputStream;
49
import java.io.IOException;
50
import java.net.InetAddress;
51
import java.net.UnknownHostException;
52
import java.security.AccessController;
53
import java.security.PrivilegedActionException;
54
import java.security.PrivilegedExceptionAction;
55
import java.util.Enumeration;
56
import java.util.HashMap;
59
import java.util.Iterator;
62
* The servlet based server invoker that receives the original http request
63
* from the ServerInvokerServlet.
65
* @author <a href="mailto:tom.elrod@jboss.com">Tom Elrod</a>
67
public class ServletServerInvoker extends WebServerInvoker implements ServletServerInvokerMBean
69
public static final String UNWRAP_SINGLETON_ARRAYS = "unwrapSingletonArrays";
71
private static final Logger log = Logger.getLogger(ServletServerInvoker.class);
73
private boolean unwrapSingletonArrays;
75
private boolean useRemotingContentType;
77
public ServletServerInvoker(InvokerLocator locator)
83
public ServletServerInvoker(InvokerLocator locator, Map configuration)
85
super(locator, configuration);
89
protected String getDefaultDataType()
91
return HTTPMarshaller.DATATYPE;
96
Object val = configuration.get(UNWRAP_SINGLETON_ARRAYS);
101
unwrapSingletonArrays = Boolean.valueOf((String)val).booleanValue();
102
log.debug(this + " setting unwrapSingletonArrays to " + unwrapSingletonArrays);
106
log.warn(this + " could not convert " +
107
UNWRAP_SINGLETON_ARRAYS + " value of " +
108
val + " to a boolean value.");
112
val = configuration.get(HTTPMetadataConstants.USE_REMOTING_CONTENT_TYPE);
113
if (val instanceof String)
115
useRemotingContentType = Boolean.valueOf((String) val).booleanValue();
117
else if (val != null)
119
log.warn(HTTPMetadataConstants.USE_REMOTING_CONTENT_TYPE + " value should be a String: " + val);
121
log.debug(this + " useRemotingContentType: " + useRemotingContentType);
124
public void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
126
Map metadata = new HashMap();
128
Enumeration enumer = request.getHeaderNames();
129
while(enumer.hasMoreElements())
131
Object obj = enumer.nextElement();
132
String headerKey = (String) obj;
133
String headerValue = request.getHeader(headerKey);
134
metadata.put(headerKey, headerValue);
137
Map urlParams = request.getParameterMap();
138
if (unwrapSingletonArrays)
140
Iterator it = urlParams.keySet().iterator();
143
Object key = it.next();
144
Object value = urlParams.get(key);
145
String[] valueArray = (String[]) value;
146
if (valueArray.length == 1)
148
value = valueArray[0];
150
metadata.put(key, value);
155
metadata.putAll(urlParams);
158
if(log.isTraceEnabled())
160
log.trace("metadata:");
161
Iterator it = metadata.keySet().iterator();
164
Object key = it.next();
165
log.trace(" " + key + ": " + metadata.get(key));
169
// UnMarshaller may not be an HTTPUnMarshaller, in which case it
170
// can ignore this parameter.
171
Object o = configuration.get(HTTPUnMarshaller.PRESERVE_LINES);
174
if (o instanceof String[])
176
metadata.put(HTTPUnMarshaller.PRESERVE_LINES, ((String[]) o)[0]);
180
metadata.put(HTTPUnMarshaller.PRESERVE_LINES, o);
184
String requestContentType = request.getContentType();
189
Object invocationResponse = null;
191
ServletInputStream inputStream = request.getInputStream();
192
UnMarshaller unmarshaller = MarshalFactory.getUnMarshaller(HTTPUnMarshaller.DATATYPE, getSerializationType());
194
if (unmarshaller instanceof VersionedUnMarshaller)
195
obj = ((VersionedUnMarshaller)unmarshaller).read(inputStream, metadata, getVersion());
197
obj = unmarshaller.read(inputStream, metadata);
200
InvocationRequest invocationRequest = null;
202
if(obj instanceof InvocationRequest)
204
invocationRequest = (InvocationRequest) obj;
208
if(WebUtil.isBinary(requestContentType))
210
invocationRequest = getInvocationRequest(metadata, obj);
214
invocationRequest = createNewInvocationRequest(metadata, obj);
218
String remoteAddressString = request.getRemoteAddr();
219
InetAddress remoteAddress = getAddressByName(remoteAddressString);
220
Map requestPayload = invocationRequest.getRequestPayload();
222
if (requestPayload == null)
224
requestPayload = new HashMap();
225
invocationRequest.setRequestPayload(requestPayload);
228
requestPayload.put(Remoting.CLIENT_ADDRESS, remoteAddress);
232
// call transport on the subclass, get the result to handback
233
invocationResponse = invoke(invocationRequest);
237
log.debug("Error thrown calling invoke on server invoker.", ex);
238
invocationResponse = null;
239
response.sendError(500, "Error processing invocation request. " + ex.getMessage());
242
if(invocationResponse != null)
244
if (isInvalidContentType(requestContentType))
246
log.warn("Ignoring invalid content-type from client: " + requestContentType);
250
response.setContentType(requestContentType);
252
int iContentLength = getContentLength(invocationResponse);
253
response.setContentLength(iContentLength);
254
ServletOutputStream outputStream = response.getOutputStream();
255
Marshaller marshaller = MarshalFactory.getMarshaller(HTTPMarshaller.DATATYPE, getSerializationType());
256
if (marshaller instanceof VersionedMarshaller)
257
((VersionedMarshaller) marshaller).write(invocationResponse, outputStream, getVersion());
259
marshaller.write(invocationResponse, outputStream);
260
outputStream.close();
264
catch(ClassNotFoundException e)
266
log.error("Error processing invocation request due to class not being found.", e);
267
response.sendError(500, "Error processing invocation request due to class not being found. " + e.getMessage());
273
public byte[] processRequest(HttpServletRequest request, byte[] requestByte,
274
HttpServletResponse response)
275
throws ServletException, IOException
277
byte[] retval = new byte[0];
279
// Check if client is HTTPClientInvoker
280
boolean isRemotingUserAgent = false;
281
String userAgent = request.getHeader(HTTPMetadataConstants.REMOTING_USER_AGENT);
282
if (userAgent != null)
284
isRemotingUserAgent = userAgent.startsWith("JBossRemoting");
287
Map metadata = new HashMap();
289
Enumeration enumer = request.getHeaderNames();
290
while(enumer.hasMoreElements())
292
Object obj = enumer.nextElement();
293
String headerKey = (String) obj;
294
String headerValue = request.getHeader(headerKey);
295
metadata.put(headerKey, headerValue);
298
Map urlParams = request.getParameterMap();
299
if (unwrapSingletonArrays)
301
Iterator it = urlParams.keySet().iterator();
304
Object key = it.next();
305
Object value = urlParams.get(key);
306
String[] valueArray = (String[]) value;
307
if (valueArray.length == 1)
309
value = valueArray[0];
311
metadata.put(key, value);
316
metadata.putAll(urlParams);
319
metadata.put(HTTPMetadataConstants.METHODTYPE, request.getMethod());
321
// UnMarshaller may not be an HTTPUnMarshaller, in which case it
322
// can ignore this parameter.
323
Object o = configuration.get(HTTPUnMarshaller.PRESERVE_LINES);
326
if (o instanceof String[])
328
metadata.put(HTTPUnMarshaller.PRESERVE_LINES, ((String[]) o)[0]);
332
metadata.put(HTTPUnMarshaller.PRESERVE_LINES, o);
336
String path = request.getPathTranslated();
338
metadata.put(HTTPMetadataConstants.PATH, path);
340
metadata.put(HTTPMetadataConstants.USE_REMOTING_CONTENT_TYPE, Boolean.toString(useRemotingContentType));
341
String remotingContentType = (String) metadata.get(HTTPMetadataConstants.REMOTING_CONTENT_TYPE);
342
if (remotingContentType == null)
344
remotingContentType = (String) metadata.get(HTTPMetadataConstants.REMOTING_CONTENT_TYPE_LC);
347
String requestContentType = request.getContentType();
352
InvocationRequest invocationRequest = null;
353
Object responseObject = null;
354
boolean isError = false;
356
String method = request.getMethod();
357
if (method.equals("GET") || method.equals("HEAD") || (method.equals("OPTIONS") && request.getContentLength() <= 0))
359
invocationRequest = createNewInvocationRequest(metadata, null);
363
ServletInputStream inputStream = request.getInputStream();
364
UnMarshaller unmarshaller = getUnMarshaller();
366
if (unmarshaller instanceof VersionedUnMarshaller)
367
obj = ((VersionedUnMarshaller)unmarshaller).read(new ByteArrayInputStream(requestByte), metadata, getVersion());
369
obj = unmarshaller.read(new ByteArrayInputStream(requestByte), metadata);
372
if(obj instanceof InvocationRequest)
374
invocationRequest = (InvocationRequest) obj;
376
Map requestMap = invocationRequest.getRequestPayload();
377
if (requestMap == null)
379
invocationRequest.setRequestPayload(metadata);
383
requestMap.putAll(metadata);
388
if((useRemotingContentType && HTTPMetadataConstants.REMOTING_CONTENT_TYPE_NON_STRING.equalsIgnoreCase(remotingContentType))
389
|| (!useRemotingContentType && WebUtil.isBinary(requestContentType)))
391
invocationRequest = getInvocationRequest(metadata, obj);
395
invocationRequest = createNewInvocationRequest(metadata, obj);
400
String remoteAddressString = request.getRemoteAddr();
401
InetAddress remoteAddress = getAddressByName(remoteAddressString);
402
Map requestPayload = invocationRequest.getRequestPayload();
404
if (requestPayload == null)
406
requestPayload = new HashMap();
407
invocationRequest.setRequestPayload(requestPayload);
410
requestPayload.put(Remoting.CLIENT_ADDRESS, remoteAddress);
415
// call transport on the subclass, get the result to handback
416
responseObject = invoke(invocationRequest);
420
log.debug("Error thrown calling invoke on server invoker.", ex);
422
if (checkForNoExceptionReturn(metadata))
424
log.trace("Returning error message instead of Exception");
425
response.addHeader(HTTPMetadataConstants.REMOTING_CONTENT_TYPE, HTTPMetadataConstants.REMOTING_CONTENT_TYPE_STRING);
426
response.sendError(500, "Error occurred processing invocation request. ");
437
if(responseObject != null)
446
if (!isRemotingUserAgent || "HEAD".equals(request.getMethod()))
452
// extract response code/message if exists
453
Map responseMap = invocationRequest.getReturnPayload();
454
if(responseMap != null)
456
Integer handlerStatus = (Integer) responseMap.remove(HTTPMetadataConstants.RESPONSE_CODE);
457
if(handlerStatus != null)
459
status = handlerStatus.intValue();
462
// add any response map headers
463
Set entries = responseMap.entrySet();
464
Iterator itr = entries.iterator();
467
Map.Entry entry = (Map.Entry)itr.next();
468
response.addHeader(entry.getKey().toString(), entry.getValue().toString());
474
// can't set message anymore as is deprecated
475
response.setStatus(status);
477
if (isRemotingUserAgent && !(invocationRequest instanceof CreatedInvocationRequest))
479
responseObject = new InvocationResponse(invocationRequest.getSessionId(),
480
responseObject, isError, responseMap);
483
if(responseObject != null)
485
String responseContentType = null;
486
if (responseMap != null)
488
responseContentType = (String) responseMap.get("Content-Type");
491
if (responseContentType != null)
493
if (isInvalidContentType(responseContentType))
495
log.warn("Ignoring invalid content-type from ServerInvocationHandler: " + responseContentType);
496
responseContentType = WebUtil.getContentType(responseObject);
501
responseContentType = WebUtil.getContentType(responseObject);
503
response.setContentType(responseContentType);
504
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
505
Marshaller marshaller = getMarshaller();
506
if (marshaller instanceof VersionedMarshaller)
507
((VersionedMarshaller) marshaller).write(responseObject, outputStream, getVersion());
509
marshaller.write(responseObject, outputStream);
510
retval = outputStream.toByteArray();
511
response.setContentLength(retval.length);
514
if (responseObject instanceof String)
516
response.addHeader(HTTPMetadataConstants.REMOTING_CONTENT_TYPE, HTTPMetadataConstants.REMOTING_CONTENT_TYPE_STRING);
520
response.addHeader(HTTPMetadataConstants.REMOTING_CONTENT_TYPE, HTTPMetadataConstants.REMOTING_CONTENT_TYPE_NON_STRING);
523
catch(ClassNotFoundException e)
525
log.error("Error processing invocation request due to class not being found.", e);
526
response.sendError(500, "Error processing invocation request due to class not being found. " + e.getMessage());
532
static private boolean isInvalidContentType(String contentType)
534
return contentType.indexOf('\n') + contentType.indexOf('\r') > -2;
537
private boolean checkForNoExceptionReturn(Map headers)
539
boolean flag = false;
543
Object val = headers.get(HTTPMetadataConstants.DONT_RETURN_EXCEPTION);
546
if (val instanceof String)
548
flag = Boolean.valueOf((String) val).booleanValue();
550
else if (val instanceof String[])
552
String param = ((String[]) val)[0];
553
flag = Boolean.valueOf(param).booleanValue();
561
static private InetAddress getAddressByName(final String host) throws UnknownHostException
563
if (SecurityUtility.skipAccessControl())
565
return InetAddress.getByName(host);
570
return (InetAddress)AccessController.doPrivileged( new PrivilegedExceptionAction()
572
public Object run() throws IOException
574
return InetAddress.getByName(host);
578
catch (PrivilegedActionException e)
580
throw (UnknownHostException) e.getCause();
b'\\ No newline at end of file'