~ubuntu-branches/ubuntu/oneiric/libjboss-remoting-java/oneiric

« back to all changes in this revision

Viewing changes to src/main/org/jboss/remoting/transport/servlet/ServletServerInvoker.java

  • Committer: Package Import Robot
  • Author(s): Torsten Werner
  • Date: 2011-09-09 14:01:03 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: package-import@ubuntu.com-20110909140103-hqokx61534tas9rg
Tags: 2.5.3.SP1-1
* Newer but not newest upstream release. Do not build samples.
* Change debian/watch to upstream's svn repo.
* Add patch to fix compile error caused by tomcat update.
  (Closes: #628303)
* Switch to source format 3.0.
* Switch to debhelper level 7.
* Remove useless Depends.
* Update Standards-Version: 3.9.2.
* Update README.source.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
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.
 
6
*
 
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.
 
11
*
 
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.
 
16
*
 
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.
 
21
*/
 
22
 
 
23
package org.jboss.remoting.transport.servlet;
 
24
 
 
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;
 
41
 
 
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;
 
57
import java.util.Map;
 
58
import java.util.Set;
 
59
import java.util.Iterator;
 
60
 
 
61
/**
 
62
 * The servlet based server invoker that receives the original http request
 
63
 * from the ServerInvokerServlet.
 
64
 *
 
65
 * @author <a href="mailto:tom.elrod@jboss.com">Tom Elrod</a>
 
66
 */
 
67
public class ServletServerInvoker extends WebServerInvoker implements ServletServerInvokerMBean
 
68
{
 
69
   public static final String UNWRAP_SINGLETON_ARRAYS = "unwrapSingletonArrays";
 
70
   
 
71
   private static final Logger log = Logger.getLogger(ServletServerInvoker.class);
 
72
   
 
73
   private boolean unwrapSingletonArrays;
 
74
   
 
75
   private boolean useRemotingContentType;
 
76
 
 
77
   public ServletServerInvoker(InvokerLocator locator)
 
78
   {
 
79
      super(locator);
 
80
      init();
 
81
   }
 
82
 
 
83
   public ServletServerInvoker(InvokerLocator locator, Map configuration)
 
84
   {
 
85
      super(locator, configuration);
 
86
      init();
 
87
   }
 
88
 
 
89
   protected String getDefaultDataType()
 
90
   {
 
91
      return HTTPMarshaller.DATATYPE;
 
92
   }
 
93
   
 
94
   protected void init()
 
95
   {
 
96
      Object val = configuration.get(UNWRAP_SINGLETON_ARRAYS);
 
97
      if (val != null)
 
98
      {
 
99
         try
 
100
         {
 
101
            unwrapSingletonArrays = Boolean.valueOf((String)val).booleanValue();
 
102
            log.debug(this + " setting unwrapSingletonArrays to " + unwrapSingletonArrays);
 
103
         }
 
104
         catch (Exception e)
 
105
         {
 
106
            log.warn(this + " could not convert " + 
 
107
                     UNWRAP_SINGLETON_ARRAYS + " value of " +
 
108
                     val + " to a boolean value.");
 
109
         }
 
110
      }
 
111
      
 
112
      val = configuration.get(HTTPMetadataConstants.USE_REMOTING_CONTENT_TYPE);
 
113
      if (val instanceof String)
 
114
      {
 
115
         useRemotingContentType = Boolean.valueOf((String) val).booleanValue();
 
116
      }
 
117
      else if (val != null)
 
118
      {
 
119
         log.warn(HTTPMetadataConstants.USE_REMOTING_CONTENT_TYPE + " value should be a String: " + val);
 
120
      }
 
121
      log.debug(this + " useRemotingContentType: " + useRemotingContentType);
 
122
   }
 
123
 
 
124
   public void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
 
125
   {
 
126
      Map metadata = new HashMap();
 
127
 
 
128
      Enumeration enumer = request.getHeaderNames();
 
129
      while(enumer.hasMoreElements())
 
130
      {
 
131
         Object obj = enumer.nextElement();
 
132
         String headerKey = (String) obj;
 
133
         String headerValue = request.getHeader(headerKey);
 
134
         metadata.put(headerKey, headerValue);
 
135
      }
 
136
 
 
137
      Map urlParams = request.getParameterMap();
 
138
      if (unwrapSingletonArrays)
 
139
      {
 
140
         Iterator it = urlParams.keySet().iterator();
 
141
         while (it.hasNext())
 
142
         {
 
143
            Object key = it.next();
 
144
            Object value = urlParams.get(key);
 
145
            String[] valueArray = (String[]) value;
 
146
            if (valueArray.length == 1)
 
147
            {
 
148
               value = valueArray[0];
 
149
            }
 
150
            metadata.put(key, value);
 
151
         }
 
152
      }
 
153
      else
 
154
      {
 
155
         metadata.putAll(urlParams);
 
156
      }
 
157
      
 
158
      if(log.isTraceEnabled())
 
159
      {
 
160
         log.trace("metadata:");
 
161
         Iterator it = metadata.keySet().iterator();
 
162
         while (it.hasNext())
 
163
         {
 
164
            Object key = it.next();
 
165
            log.trace("  " + key + ": " + metadata.get(key));
 
166
         }
 
167
      }
 
168
      
 
169
      // UnMarshaller may not be an HTTPUnMarshaller, in which case it
 
170
      // can ignore this parameter.
 
171
      Object o = configuration.get(HTTPUnMarshaller.PRESERVE_LINES);
 
172
      if (o != null)
 
173
      {
 
174
         if (o instanceof String[])
 
175
         {
 
176
            metadata.put(HTTPUnMarshaller.PRESERVE_LINES, ((String[]) o)[0]);
 
177
         }
 
178
         else
 
179
         {
 
180
            metadata.put(HTTPUnMarshaller.PRESERVE_LINES, o);
 
181
         }
 
182
      }
 
183
 
 
184
      String requestContentType = request.getContentType();
 
185
 
 
186
 
 
187
      try
 
188
      {
 
189
         Object invocationResponse = null;
 
190
 
 
191
         ServletInputStream inputStream = request.getInputStream();
 
192
         UnMarshaller unmarshaller = MarshalFactory.getUnMarshaller(HTTPUnMarshaller.DATATYPE, getSerializationType());
 
193
         Object obj = null;
 
194
         if (unmarshaller instanceof VersionedUnMarshaller)
 
195
            obj = ((VersionedUnMarshaller)unmarshaller).read(inputStream, metadata, getVersion());
 
196
         else
 
197
            obj = unmarshaller.read(inputStream, metadata);
 
198
         inputStream.close();
 
199
 
 
200
         InvocationRequest invocationRequest = null;
 
201
 
 
202
         if(obj instanceof InvocationRequest)
 
203
         {
 
204
            invocationRequest = (InvocationRequest) obj;
 
205
         }
 
206
         else
 
207
         {
 
208
            if(WebUtil.isBinary(requestContentType))
 
209
            {
 
210
               invocationRequest = getInvocationRequest(metadata, obj);
 
211
            }
 
212
            else
 
213
            {
 
214
               invocationRequest = createNewInvocationRequest(metadata, obj);
 
215
            }
 
216
         }
 
217
         
 
218
         String remoteAddressString = request.getRemoteAddr();
 
219
         InetAddress remoteAddress = getAddressByName(remoteAddressString);
 
220
         Map requestPayload = invocationRequest.getRequestPayload();
 
221
         
 
222
         if (requestPayload == null)
 
223
         {
 
224
            requestPayload = new HashMap();
 
225
            invocationRequest.setRequestPayload(requestPayload);
 
226
         }
 
227
         
 
228
         requestPayload.put(Remoting.CLIENT_ADDRESS, remoteAddress);
 
229
 
 
230
         try
 
231
         {
 
232
            // call transport on the subclass, get the result to handback
 
233
            invocationResponse = invoke(invocationRequest);
 
234
         }
 
235
         catch(Throwable ex)
 
236
         {
 
237
            log.debug("Error thrown calling invoke on server invoker.", ex);
 
238
            invocationResponse = null;
 
239
            response.sendError(500, "Error processing invocation request.  " + ex.getMessage());
 
240
         }
 
241
 
 
242
         if(invocationResponse != null)
 
243
         {
 
244
            if (isInvalidContentType(requestContentType))
 
245
            {
 
246
               log.warn("Ignoring invalid content-type from client: " + requestContentType);
 
247
            }
 
248
            else
 
249
            {
 
250
               response.setContentType(requestContentType);
 
251
            }
 
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());
 
258
            else
 
259
               marshaller.write(invocationResponse, outputStream);
 
260
            outputStream.close();
 
261
         }
 
262
 
 
263
      }
 
264
      catch(ClassNotFoundException e)
 
265
      {
 
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());
 
268
 
 
269
      }
 
270
 
 
271
   }
 
272
 
 
273
   public byte[] processRequest(HttpServletRequest request, byte[] requestByte,
 
274
                                HttpServletResponse response)
 
275
         throws ServletException, IOException
 
276
   {
 
277
      byte[] retval = new byte[0];
 
278
      
 
279
      // Check if client is HTTPClientInvoker
 
280
      boolean isRemotingUserAgent = false;
 
281
      String userAgent = request.getHeader(HTTPMetadataConstants.REMOTING_USER_AGENT);
 
282
      if (userAgent != null)
 
283
      {
 
284
         isRemotingUserAgent = userAgent.startsWith("JBossRemoting");
 
285
      }
 
286
 
 
287
      Map metadata = new HashMap();
 
288
 
 
289
      Enumeration enumer = request.getHeaderNames();
 
290
      while(enumer.hasMoreElements())
 
291
      {
 
292
         Object obj = enumer.nextElement();
 
293
         String headerKey = (String) obj;
 
294
         String headerValue = request.getHeader(headerKey);
 
295
         metadata.put(headerKey, headerValue);
 
296
      }
 
297
 
 
298
      Map urlParams = request.getParameterMap();
 
299
      if (unwrapSingletonArrays)
 
300
      {
 
301
         Iterator it = urlParams.keySet().iterator();
 
302
         while (it.hasNext())
 
303
         {
 
304
            Object key = it.next();
 
305
            Object value = urlParams.get(key);
 
306
            String[] valueArray = (String[]) value;
 
307
            if (valueArray.length == 1)
 
308
            {
 
309
               value = valueArray[0];
 
310
            }
 
311
            metadata.put(key, value);
 
312
         }
 
313
      }
 
314
      else
 
315
      {
 
316
         metadata.putAll(urlParams);
 
317
      }
 
318
 
 
319
      metadata.put(HTTPMetadataConstants.METHODTYPE, request.getMethod());
 
320
      
 
321
      // UnMarshaller may not be an HTTPUnMarshaller, in which case it
 
322
      // can ignore this parameter.
 
323
      Object o = configuration.get(HTTPUnMarshaller.PRESERVE_LINES);
 
324
      if (o != null)
 
325
      {
 
326
         if (o instanceof String[])
 
327
         {
 
328
            metadata.put(HTTPUnMarshaller.PRESERVE_LINES, ((String[]) o)[0]);
 
329
         }
 
330
         else
 
331
         {
 
332
            metadata.put(HTTPUnMarshaller.PRESERVE_LINES, o);
 
333
         }
 
334
      }
 
335
      
 
336
      String path = request.getPathTranslated();
 
337
      if (path != null)
 
338
         metadata.put(HTTPMetadataConstants.PATH, path);
 
339
 
 
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)
 
343
      {
 
344
         remotingContentType = (String) metadata.get(HTTPMetadataConstants.REMOTING_CONTENT_TYPE_LC);
 
345
      }
 
346
      
 
347
      String requestContentType = request.getContentType();
 
348
 
 
349
 
 
350
      try
 
351
      {
 
352
         InvocationRequest invocationRequest = null;
 
353
         Object responseObject = null;
 
354
         boolean isError = false;
 
355
 
 
356
         String method = request.getMethod();
 
357
         if (method.equals("GET") || method.equals("HEAD") || (method.equals("OPTIONS") && request.getContentLength() <= 0))
 
358
         {
 
359
            invocationRequest = createNewInvocationRequest(metadata, null);
 
360
         }
 
361
         else
 
362
         {
 
363
            ServletInputStream inputStream = request.getInputStream();
 
364
            UnMarshaller unmarshaller = getUnMarshaller();
 
365
            Object obj = null;
 
366
            if (unmarshaller instanceof VersionedUnMarshaller)
 
367
               obj = ((VersionedUnMarshaller)unmarshaller).read(new ByteArrayInputStream(requestByte), metadata, getVersion());
 
368
            else
 
369
               obj = unmarshaller.read(new ByteArrayInputStream(requestByte), metadata);
 
370
            inputStream.close();
 
371
 
 
372
            if(obj instanceof InvocationRequest)
 
373
            {
 
374
               invocationRequest = (InvocationRequest) obj;
 
375
 
 
376
               Map requestMap = invocationRequest.getRequestPayload();
 
377
               if (requestMap == null)
 
378
               {
 
379
                  invocationRequest.setRequestPayload(metadata);
 
380
               }
 
381
               else
 
382
               {
 
383
                  requestMap.putAll(metadata);
 
384
               }
 
385
            }
 
386
            else
 
387
            {
 
388
               if((useRemotingContentType && HTTPMetadataConstants.REMOTING_CONTENT_TYPE_NON_STRING.equalsIgnoreCase(remotingContentType))
 
389
                  || (!useRemotingContentType && WebUtil.isBinary(requestContentType)))
 
390
               {
 
391
                  invocationRequest = getInvocationRequest(metadata, obj);
 
392
               }
 
393
               else
 
394
               {
 
395
                  invocationRequest = createNewInvocationRequest(metadata, obj);
 
396
               }
 
397
            }
 
398
         }
 
399
 
 
400
         String remoteAddressString = request.getRemoteAddr();
 
401
         InetAddress remoteAddress = getAddressByName(remoteAddressString);
 
402
         Map requestPayload = invocationRequest.getRequestPayload();
 
403
         
 
404
         if (requestPayload == null)
 
405
         {
 
406
            requestPayload = new HashMap();
 
407
            invocationRequest.setRequestPayload(requestPayload);
 
408
         }
 
409
         
 
410
         requestPayload.put(Remoting.CLIENT_ADDRESS, remoteAddress);
 
411
         
 
412
         
 
413
         try
 
414
         {
 
415
            // call transport on the subclass, get the result to handback
 
416
            responseObject = invoke(invocationRequest);
 
417
         }
 
418
         catch(Throwable ex)
 
419
         {
 
420
            log.debug("Error thrown calling invoke on server invoker.", ex);
 
421
            
 
422
            if (checkForNoExceptionReturn(metadata))
 
423
            {
 
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. ");
 
427
               return retval;
 
428
            }
 
429
            else
 
430
            {
 
431
               responseObject = ex;
 
432
               isError = true;
 
433
            }
 
434
         }
 
435
 
 
436
         int status = 200;
 
437
         if(responseObject != null)
 
438
         {
 
439
            if(isError)
 
440
            {
 
441
               status = 500;
 
442
            }
 
443
         }
 
444
         else
 
445
         {
 
446
            if (!isRemotingUserAgent || "HEAD".equals(request.getMethod()))
 
447
            {
 
448
               status = 204;
 
449
            }
 
450
         }
 
451
 
 
452
         // extract response code/message if exists
 
453
         Map responseMap = invocationRequest.getReturnPayload();
 
454
         if(responseMap != null)
 
455
         {
 
456
            Integer handlerStatus = (Integer) responseMap.remove(HTTPMetadataConstants.RESPONSE_CODE);
 
457
            if(handlerStatus != null)
 
458
            {
 
459
               status = handlerStatus.intValue();
 
460
            }
 
461
 
 
462
            // add any response map headers
 
463
            Set entries = responseMap.entrySet();
 
464
            Iterator itr = entries.iterator();
 
465
            while(itr.hasNext())
 
466
            {
 
467
               Map.Entry entry = (Map.Entry)itr.next();
 
468
               response.addHeader(entry.getKey().toString(), entry.getValue().toString());
 
469
            }
 
470
         }
 
471
 
 
472
 
 
473
 
 
474
         // can't set message anymore as is deprecated
 
475
         response.setStatus(status);
 
476
         
 
477
         if (isRemotingUserAgent && !(invocationRequest instanceof CreatedInvocationRequest))
 
478
         {
 
479
            responseObject = new InvocationResponse(invocationRequest.getSessionId(),
 
480
                                                    responseObject, isError, responseMap);
 
481
         }
 
482
 
 
483
         if(responseObject != null)
 
484
         {
 
485
            String responseContentType = null;
 
486
            if (responseMap != null)
 
487
            {
 
488
               responseContentType = (String) responseMap.get("Content-Type");
 
489
            }
 
490
            
 
491
            if (responseContentType != null)
 
492
            {
 
493
               if (isInvalidContentType(responseContentType))
 
494
               {
 
495
                  log.warn("Ignoring invalid content-type from ServerInvocationHandler: " + responseContentType);
 
496
                  responseContentType = WebUtil.getContentType(responseObject); 
 
497
               }
 
498
            }
 
499
            else
 
500
            {
 
501
               responseContentType = WebUtil.getContentType(responseObject); 
 
502
            }
 
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());
 
508
            else
 
509
               marshaller.write(responseObject, outputStream);
 
510
            retval = outputStream.toByteArray();
 
511
            response.setContentLength(retval.length);
 
512
         }
 
513
         
 
514
         if (responseObject instanceof String)
 
515
         {
 
516
            response.addHeader(HTTPMetadataConstants.REMOTING_CONTENT_TYPE, HTTPMetadataConstants.REMOTING_CONTENT_TYPE_STRING);
 
517
         }
 
518
         else
 
519
         {
 
520
            response.addHeader(HTTPMetadataConstants.REMOTING_CONTENT_TYPE, HTTPMetadataConstants.REMOTING_CONTENT_TYPE_NON_STRING);        
 
521
         }
 
522
      }
 
523
      catch(ClassNotFoundException e)
 
524
      {
 
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());
 
527
      }
 
528
 
 
529
      return retval;
 
530
   }
 
531
   
 
532
   static private boolean isInvalidContentType(String contentType)
 
533
   {
 
534
      return contentType.indexOf('\n') + contentType.indexOf('\r') > -2;
 
535
   }
 
536
   
 
537
   private boolean checkForNoExceptionReturn(Map headers)
 
538
   {
 
539
      boolean flag = false;
 
540
 
 
541
      if(headers != null)
 
542
      {
 
543
         Object val = headers.get(HTTPMetadataConstants.DONT_RETURN_EXCEPTION);
 
544
         if (val != null)
 
545
         {
 
546
            if (val instanceof String)
 
547
            {
 
548
               flag = Boolean.valueOf((String) val).booleanValue();
 
549
            }
 
550
            else if (val instanceof String[])
 
551
            {
 
552
               String param = ((String[]) val)[0];
 
553
               flag = Boolean.valueOf(param).booleanValue();
 
554
            }
 
555
         }
 
556
      }
 
557
      
 
558
      return flag;
 
559
   }
 
560
   
 
561
   static private InetAddress getAddressByName(final String host) throws UnknownHostException
 
562
   {
 
563
      if (SecurityUtility.skipAccessControl())
 
564
      {
 
565
         return InetAddress.getByName(host);
 
566
      }
 
567
      
 
568
      try
 
569
      {
 
570
         return (InetAddress)AccessController.doPrivileged( new PrivilegedExceptionAction()
 
571
         {
 
572
            public Object run() throws IOException
 
573
            {
 
574
               return InetAddress.getByName(host);
 
575
            }
 
576
         });
 
577
      }
 
578
      catch (PrivilegedActionException e)
 
579
      {
 
580
         throw (UnknownHostException) e.getCause();
 
581
      }
 
582
   }
 
583
}
 
 
b'\\ No newline at end of file'