KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openlaszlo > data > JavaDataSource


1 /* ****************************************************************************
2  * JavaDataSource.java
3  * ****************************************************************************/

4
5 /* J_LZ_COPYRIGHT_BEGIN *******************************************************
6 * Copyright 2001-2004 Laszlo Systems, Inc. All Rights Reserved. *
7 * Use is subject to license terms. *
8 * J_LZ_COPYRIGHT_END *********************************************************/

9
10 /*
11  * The Apache Software License, Version 1.1
12  *
13  *
14  * Copyright(c) 2002 The Apache Software Foundation. All rights
15  * reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions
19  * are met:
20  *
21  * 1. Redistributions of source code must retain the above copyright
22  * notice, this list of conditions and the following disclaimer.
23  *
24  * 2. Redistributions in binary form must reproduce the above copyright
25  * notice, this list of conditions and the following disclaimer in
26  * the documentation and/or other materials provided with the
27  * distribution.
28  *
29  * 3. The end-user documentation included with the redistribution,
30  * if any, must include the following acknowledgment:
31  * "This product includes software developed by the
32  * Apache Software Foundation(http://www.apache.org/)."
33  * Alternately, this acknowledgment may appear in the software itself,
34  * if and wherever such third-party acknowledgments normally appear.
35  *
36  * 4. The names "XML-RPC" and "Apache Software Foundation" must
37  * not be used to endorse or promote products derived from this
38  * software without prior written permission. For written
39  * permission, please contact apache@apache.org.
40  *
41  * 5. Products derived from this software may not be called "Apache",
42  * nor may "Apache" appear in their name, without prior written
43  * permission of the Apache Software Foundation.
44  *
45  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
46  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
47  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
48  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
49  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT
51  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
52  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
53  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
54  * OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
55  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56  * SUCH DAMAGE.
57  * ====================================================================
58  *
59  * This software consists of voluntary contributions made by many
60  * individuals on behalf of the Apache Software Foundation. For more
61  * information on the Apache Software Foundation, please see
62  * <http://www.apache.org/>.
63  */

64 package org.openlaszlo.data;
65
66 import java.io.*;
67 import java.lang.reflect.*;
68 import java.util.*;
69 import java.net.MalformedURLException JavaDoc;
70 import javax.servlet.http.*;
71 import org.apache.xmlrpc.*;
72 import org.openlaszlo.server.LPS;
73 import org.openlaszlo.server.Option;
74 import org.openlaszlo.xml.*;
75 import org.openlaszlo.xml.internal.*;
76 import org.openlaszlo.utils.*;
77 import org.openlaszlo.remote.*;
78 // LoadCount belongs in utils
79
import org.openlaszlo.servlets.LoadCount;
80 import org.openlaszlo.media.MimeType;
81 import org.apache.log4j.*;
82
83 /**
84  * Data source for java direct calls.
85  */

86 public class JavaDataSource extends DataSource
87 {
88     private static Logger mLogger = Logger.getLogger(JavaDataSource.class);
89
90     private static String JavaDoc OBJECTS = "__lzobj";
91
92     //------------------------------------------------------------
93
// Begin javarpc info variables
94
//------------------------------------------------------------
95

96     final public static int LOAD_INVOKE = 0x01;
97     final public static int LOAD_STATIC_GET_PROTO = 0x02;
98     final public static int LOAD_INSTANCE_CREATE_PROTO = 0x04;
99     final public static int LOAD_INSTANCE_GET_PROTO = 0x08;
100     final public static int LOAD_INSTANCE_DESTROY_PROTO = 0x10;
101     final public static int LOAD_INSTANCE_GET_INVOKE_TARGET = 0x20;
102     final public static int LOAD_RETURN_OBJECT_ENCODE = 0x40;
103
104     static long mLastCleared = -1;
105
106     // Map of SWF prototypes for session objects.
107
public static VersionMap mSessionPrototypes = new VersionMap();
108     // Map of SWF prototypes for webapp objects.
109
public static VersionMap mWebAppPrototypes = new VersionMap();
110     // Map of SWF prototypes for static objects.
111
public static VersionMap mStaticPrototypes = new VersionMap();
112
113     // Count of sessions. Also used by SessionBindingMap.
114
public static ThreadSafeCounter mSessionCounter
115         = new ThreadSafeCounter();
116     // Count of system-wide objects. Also used by SessionBindingMap.
117
public static ThreadSafeCounter mSessionObjectsCounter
118         = new ThreadSafeCounter();
119     // Count of webapp objects.
120
public static ThreadSafeCounter mWebAppObjectsCounter =
121         new ThreadSafeCounter();
122
123     public static LoadCount mJavaRPCLoad = new LoadCount(10);
124     public static LoadCount mInvokeLoad = new LoadCount(10);
125     public static LoadCount mReturnObjectEncodeLoad = new LoadCount(10);
126     public static LoadCount mStaticProtoGetLoad = new LoadCount(10);
127     public static LoadCount mInstanceProtoCreateLoad = new LoadCount(10);
128     public static LoadCount mInstanceProtoGetLoad = new LoadCount(10);
129     public static LoadCount mInstanceProtoDestroyLoad = new LoadCount(10);
130     public static LoadCount mInstanceGetInvokeTargetLoad = new LoadCount(10);
131
132     //------------------------------------------------------------
133
// End javarpc info variables
134
//------------------------------------------------------------
135

136     static final String JavaDoc UNKNOWN = "unknown";
137     static final String JavaDoc SESSION = "session";
138     static final String JavaDoc WEBAPP = "webapp";
139     static final String JavaDoc NONE = "none";
140
141     static final int SCOPE_UNKNOWN = -1;
142     static final int SCOPE_SESSION = 0;
143     static final int SCOPE_WEBAPP = 1;
144     static final int SCOPE_NONE = 2;
145
146     HashMap mVoidMap = null;
147     ObjectData DEFAULT_VOID;
148
149     public JavaDataSource() {
150         clearLoadInfo();
151         try {
152             DEFAULT_VOID = new ObjectData
153                 (XMLRPCCompiler.compileResponse(0, "void",
154                                                 LPS.mSWFVersionNumDefault));
155         } catch (IOException e) {
156             mLogger.error("exception: " + e.getMessage(), e);
157             throw new RuntimeException JavaDoc(e.getMessage());
158         }
159     }
160
161     /**
162      * @return unique name of this data source
163      */

164     public String JavaDoc name()
165     {
166         return "java";
167     }
168
169     /**
170      * Sends system information to client.
171      *
172      * @throws DataSourceException if there was a problem retrieving or sending
173      * the data.
174      */

175     public Data getData(String JavaDoc app, HttpServletRequest req,
176                         HttpServletResponse res, long lastModifiedTime)
177         throws DataSourceException {
178         mLogger.debug("getData");
179
180         int swfversion = LPS.getSWFVersionNum(req);
181
182         if (! req.getMethod().equals("POST"))
183             return compileFault("request must be POST", swfversion);
184
185         String JavaDoc url;
186         try {
187             url = getURL(req);
188         } catch (MalformedURLException JavaDoc e) {
189             return compileFault("malformed url", e, swfversion);
190         }
191
192         String JavaDoc cname = getClassName(url);
193         if (cname == null)
194             return compileFault("invalid class or bad url: " + url, swfversion);
195
196         if (! isClassOk(cname, req.getServletPath()))
197             return compileFault("forbidden class: " + cname, swfversion);
198
199         Class JavaDoc targetClass = getClass(cname);
200         if (targetClass == null)
201             return compileFault("no such class " + cname, swfversion);
202
203         int scope = getScope(req);
204         if (scope == SCOPE_UNKNOWN)
205             return compileFault("no scope request parameter", swfversion);
206
207         String JavaDoc postbody = req.getParameter("lzpostbody");
208         if (postbody == null || postbody.equals(""))
209             return compileFault("no post body", swfversion);
210
211         // one of 'pojo' or 'javabean'
212
String JavaDoc objectReturnType = req.getParameter("objectreturntype");
213         if (objectReturnType == null || "".equals(objectReturnType)) {
214             objectReturnType = "pojo";
215         }
216
217         if (mLogger.isDebugEnabled()) {
218             mLogger.debug("class name: " + cname);
219             mLogger.debug("object return type: " + objectReturnType);
220             mLogger.debug("POST body:\n" + postbody);
221         }
222
223         XmlRpcRequest xr = new LZXmlRpcRequestProcessor()
224             .processRequest(new ByteArrayInputStream(postbody.getBytes()));
225
226         long t0, t1;
227         t0 = System.currentTimeMillis();
228         mJavaRPCLoad.increment();
229         try {
230             return execute(req, res, targetClass, scope, objectReturnType,
231                            swfversion, xr.getMethodName(), xr.getParameters());
232         } catch (IOException e) {
233             return compileFault("exception executing " + xr.getMethodName(), e,
234                                 swfversion);
235         } finally {
236             t1 = System.currentTimeMillis();
237             mJavaRPCLoad.decrement((int)(t1-t0));
238         }
239     }
240
241     /**
242      * Check to see if class is allowed.
243      */

244     public boolean isClassOk(String JavaDoc cname, String JavaDoc path) {
245         return LPS.configuration.optionAllows(path, "security", cname, false);
246     }
247
248     /**
249      * This code borrows from Apache's XMLRPC
250      * org.apache.xmlrpc.Invoker.execute() method.
251      */

252     public Data execute(HttpServletRequest req, HttpServletResponse res,
253                         Class JavaDoc targetClass, int scope, String JavaDoc objectReturnType,
254                         int swfversion, String JavaDoc methodName,
255                         Vector params) throws IOException {
256
257         if (mLogger.isDebugEnabled()) {
258             StringBuffer JavaDoc p = new StringBuffer JavaDoc(" ");
259             for (int i=0; i < params.size(); i++) {
260                 p.append(params.get(i)).append(" ");
261             }
262             mLogger.debug("execute(" + methodName
263                           + ", [" + p.toString() + "],context)");
264         }
265
266         Class JavaDoc[] argClasses = null;
267         Object JavaDoc[] argValues = null;
268         
269         String JavaDoc _doreq = req.getParameter("doreq");
270         String JavaDoc _dores = req.getParameter("dores");
271         boolean doreq = (_doreq != null && _doreq.equals("1"));
272         boolean dores = (_dores != null && _dores.equals("1"));
273
274         int reqPos = -1; // position of request in parameter list
275
int resPos = -1; // position of response in parameter list
276

277         int httpCount = 0; // count of request and response passed in
278

279         int paramCount = (params != null ? params.size() : 0);
280
281         // if request exists, place request following the last parameter
282
if (doreq) {
283             mLogger.debug("adding request to method");
284             reqPos = paramCount;
285             httpCount++;
286         }
287
288         // if response exists, place response after it, else
289
// place it following the last parameter
290
if (dores) {
291             mLogger.debug("adding response to method");
292             resPos = (reqPos != -1 ? reqPos + 1 : paramCount);
293             httpCount++;
294         }
295
296         // create arrays for argument classes and values.
297
int count = paramCount + httpCount;
298         argClasses = new Class JavaDoc[count];
299         argValues = new Object JavaDoc[count];
300
301         if (doreq) {
302             argClasses[reqPos] = HttpServletRequest.class;
303             argValues[reqPos] = req;
304         }
305
306         if (dores) {
307             argClasses[resPos] = HttpServletResponse.class;
308             argValues[resPos] = res;
309         }
310
311         if (params != null) {
312             for (int i = 0; i < params.size(); i++) {
313                 argValues[i] = params.elementAt(i);
314                 if (argValues[i] instanceof Integer JavaDoc) {
315                     argClasses[i] = Integer.TYPE;
316                 } else if (argValues[i] instanceof Double JavaDoc) {
317                     argClasses[i] = Double.TYPE;
318                 } else if (argValues[i] instanceof Boolean JavaDoc) {
319                     argClasses[i] = Boolean.TYPE;
320                 } else {
321                     argClasses[i] = argValues[i].getClass();
322                 }
323             }
324         }
325
326         Method method = null;
327         Object JavaDoc invokeTarget = targetClass;
328         long t0, t1;
329
330         String JavaDoc op = req.getParameter("op");
331         if (op != null) {
332
333             String JavaDoc cname = targetClass.getName();
334             String JavaDoc oname = req.getParameter("oname");
335             if (scope == SCOPE_NONE) oname= NONE;
336             if (oname == null || "".equals(oname))
337                 return compileFault("no oname parameter", swfversion);
338
339             if (scope == SCOPE_NONE) {
340                 if ("get".equals(op) || "create".equals(op)) {
341                     t0 = System.currentTimeMillis();
342                     mStaticProtoGetLoad.increment();
343                     try {
344                         return getStaticPrototype(cname, swfversion);
345                     } finally {
346                         t1 = System.currentTimeMillis();
347                         mStaticProtoGetLoad.decrement((int)(t1-t0));
348                     }
349                 }
350             }
351
352             if ( scope == SCOPE_SESSION || scope == SCOPE_WEBAPP ) {
353
354                 if ("get".equals(op)) {
355                     t0 = System.currentTimeMillis();
356                     mInstanceProtoGetLoad.increment();
357                     try {
358                         return getInstancePrototype(cname, oname, scope, req,
359                                                     swfversion);
360                     } finally {
361                         t1 = System.currentTimeMillis();
362                         mInstanceProtoGetLoad.decrement((int)(t1-t0));
363                     }
364                 }
365
366                 if ("create".equals(op)) {
367                     t0 = System.currentTimeMillis();
368                     mInstanceProtoCreateLoad.increment();
369                     try {
370                         return createInstancePrototype(cname, oname, scope,
371                                                        argClasses, argValues, req,
372                                                        swfversion);
373                     } finally {
374                         t1 = System.currentTimeMillis();
375                         mInstanceProtoCreateLoad.decrement((int)(t1-t0));
376                     }
377                 }
378
379                 if ("destroy".equals(op)) {
380                     t0 = System.currentTimeMillis();
381                     mInstanceProtoDestroyLoad.increment();
382                     try {
383                         return destroyInstance(oname, scope, req, swfversion);
384                     } finally {
385                         t1 = System.currentTimeMillis();
386                         mInstanceProtoDestroyLoad.decrement((int)(t1-t0));
387                     }
388                 }
389
390                 if ("invoke".equals(op)) {
391                     t0 = System.currentTimeMillis();
392                     mInstanceGetInvokeTargetLoad.increment();
393                     try {
394                         invokeTarget = getInvokeTarget(oname, scope, req);
395                     } finally {
396                         t1 = System.currentTimeMillis();
397                         mInstanceGetInvokeTargetLoad.decrement((int)(t1-t0));
398                     }
399                     if (invokeTarget == null) {
400                         String JavaDoc errmsg = "could not find " + getScopeName(scope)
401                             + " instance " + oname;
402                         mLogger.error(errmsg);
403                         return compileFault(errmsg, swfversion);
404                     }
405                 }
406             }
407         }
408
409         t0 = System.currentTimeMillis();
410         mInvokeLoad.increment();
411         Object JavaDoc returnValue = null;
412         try {
413             // The last element of the XML-RPC method name is the Java
414
// method name.
415
int dot = methodName.lastIndexOf('.');
416             if (dot > -1 && dot + 1 < methodName.length()) {
417                 methodName = methodName.substring(dot + 1);
418             }
419
420             if (mLogger.isDebugEnabled()) {
421                 mLogger.debug("Searching for method: " + methodName +
422                               " in class " + targetClass.getName());
423                 if (argClasses.length != 0) {
424                     for (int i = 0; i < argClasses.length; i++) {
425                         mLogger.debug("Parameter " + i + ": " + argValues[i]
426                                       + " (" + argClasses[i] + ')');
427                     }
428                 }
429             }
430
431             try {
432                 method = getMethod(targetClass, methodName, argClasses);
433             } catch(NoSuchMethodException JavaDoc e) {
434                 mLogger.error("NoSuchMethodException", e);
435                 return compileFault(e.getMessage(), e, swfversion);
436             } catch(SecurityException JavaDoc e) {
437                 mLogger.error("SecurityException", e);
438                 return compileFault(e.getMessage(), e, swfversion);
439             }
440
441             // Make all public methods callable except those defined in
442
// java.lang.Object.
443
if (method.getDeclaringClass() == Object JavaDoc.class) {
444                 return compileFault("Can't call methods in java.lang.Object", swfversion);
445             }
446
447             // invoke
448
try {
449                 returnValue = method.invoke(invokeTarget, argValues);
450             } catch (IllegalAccessException JavaDoc e) {
451                 mLogger.error("IllegalAccessException", e);
452                 return compileFault(e.getMessage(), e, swfversion);
453             } catch (IllegalArgumentException JavaDoc e) {
454                 mLogger.error("IllegalArgumentException", e);
455                 return compileFault(e.getMessage(), e, swfversion);
456             } catch (InvocationTargetException e) {
457                 mLogger.error("InvocationTargetException", e);
458                 Throwable JavaDoc cause = e.getCause();
459                 if (cause != null) return compileFault(cause, swfversion);
460                 return compileFault(e.getMessage(), e, swfversion);
461             } catch (Exception JavaDoc e) {
462                 mLogger.error("Exception", e);
463                 return compileFault(e.getMessage(), e, swfversion);
464             } catch (Error JavaDoc e) {
465                 mLogger.error("Error", e);
466                 return compileFault(e.getMessage(), e, swfversion);
467             }
468         } finally {
469             t1 = System.currentTimeMillis();
470             mInvokeLoad.decrement((int)(t1-t0));
471         }
472
473         t0 = System.currentTimeMillis();
474         mReturnObjectEncodeLoad.increment();
475         try {
476             Class JavaDoc returnType = method.getReturnType();
477             if (returnType == Void.TYPE) {
478                 return getVoid(swfversion);
479             } else if (returnType == DataEncoder.class && returnValue != null) {
480                 return new EncoderData((DataEncoder)returnValue);
481             }
482
483             return new ObjectData
484                 (LZReturnObject.createObject(returnValue, objectReturnType,
485                                              swfversion));
486         } catch (IOException e) {
487             mLogger.error("IOException", e);
488             return compileFault(e.getMessage(), e, swfversion);
489         } finally {
490             t1 = System.currentTimeMillis();
491             mReturnObjectEncodeLoad.decrement((int)(t1-t0));
492         }
493     }
494
495
496     synchronized ObjectData getVoid(int swfversion) {
497         if (mVoidMap == null) {
498             mVoidMap = new HashMap();
499         }
500         ObjectData voidobj;
501         try {
502             Integer JavaDoc _swfversion = new Integer JavaDoc(swfversion);
503             voidobj = (ObjectData)mVoidMap.get(_swfversion);
504             if (voidobj == null) {
505                 mLogger.debug("creating void for swf " + swfversion);
506                 voidobj = new ObjectData
507                     (XMLRPCCompiler.compileResponse(0, "void", swfversion));
508                 mVoidMap.put(_swfversion, voidobj);
509             }
510         } catch (Exception JavaDoc e) {
511             mLogger.warn("using default void", e);
512             voidobj = DEFAULT_VOID;
513         }
514         return voidobj;
515     }
516
517     /**
518      * for scope == SCOPE_NONE (static objects).
519      */

520     Data getStaticPrototype(String JavaDoc cname, int swfversion) {
521         if (mLogger.isDebugEnabled()) {
522             mLogger.debug("getStaticPrototype(" + cname + ")");
523         }
524         return getPrototype(cname, SCOPE_NONE, swfversion);
525     }
526
527
528     /**
529      * Return prototype for session and webapp if object was
530      * previously created.
531      */

532     Data getInstancePrototype(String JavaDoc cname, String JavaDoc oname, int scope,
533                               HttpServletRequest req, int swfversion) {
534
535         if (mLogger.isDebugEnabled()) {
536             mLogger.debug("getInstancePrototype(" + cname + "," + oname + ")");
537         }
538
539         Integer JavaDoc swfv = new Integer JavaDoc(swfversion);
540         if (getJavaObject(req.getSession(false), scope, oname) != null) {
541             if (scope == SCOPE_WEBAPP) {
542                 return (Data)mWebAppPrototypes.get(swfv, cname);
543             } else if (scope == SCOPE_SESSION) {
544                 return (Data)mSessionPrototypes.get(swfv, cname);
545             }
546         }
547
548         String JavaDoc errmsg = "couldn't find "+getScopeName(scope)+" instance "+oname;
549         mLogger.error(errmsg);
550         return compileFault(errmsg, swfversion);
551     }
552
553
554     /**
555      * creates a client swf object (remoteobject create)
556      */

557     Data createInstancePrototype(String JavaDoc cname, String JavaDoc oname, int scope,
558                                  Class JavaDoc[] argClasses, Object JavaDoc[] argValues,
559                                  HttpServletRequest req, int swfversion) {
560
561         if (mLogger.isDebugEnabled()) {
562             mLogger.debug("createInstancePrototype(" + cname + "," + oname + ")");
563         }
564
565         // create session here, if it doesn't exist
566
HttpSession session = req.getSession(true);
567
568         String JavaDoc _clobber = req.getParameter("clobber");
569         boolean clobber = (_clobber != null && "1".equals(_clobber));
570
571         Object JavaDoc o = null;
572         if (! clobber ) {
573             o = getJavaObject(session, scope, oname);
574             if (o != null) {
575                 if (mLogger.isDebugEnabled()) {
576                     mLogger.debug("not clobbering existing " +
577                                   getScopeName(scope) +
578                                   " object " + oname );
579                 }
580                 return getPrototype(cname, scope, swfversion);
581             }
582         }
583
584         // send back client object.
585
try {
586             o = getServerInstance(cname, argClasses, argValues);
587             setJavaObject(session, scope, oname, o);
588         } catch (Exception JavaDoc e) {
589             return compileFault("could not create instance of " + cname, e,
590                                 swfversion);
591         }
592
593         return getPrototype(cname, scope, swfversion);
594     }
595
596
597     /**
598      * Get client prototype.
599      */

600     synchronized Data getPrototype(String JavaDoc cname, int scope, int swfversion) {
601         Integer JavaDoc swfv = new Integer JavaDoc(swfversion);
602         try {
603             Data data;
604             if (scope == SCOPE_NONE) {
605                 data = (Data)mStaticPrototypes.get(swfv, cname);
606             } else if (scope == SCOPE_WEBAPP) {
607                 data = (Data)mWebAppPrototypes.get(swfv, cname);
608             } else {
609                 data = (Data)mSessionPrototypes.get(swfv, cname);
610             }
611
612             if (data == null) {
613                 mLogger.debug("creating client prototype for " + cname);
614                 byte[] b = LZClientObject.createObject(cname, getScopeName(scope),
615                                                        swfversion);
616                 data = new ObjectData(b);
617                 if (scope == SCOPE_NONE) {
618                     mStaticPrototypes.put(swfv, cname, data);
619                 } else if (scope == SCOPE_WEBAPP) {
620                     mWebAppPrototypes.put(swfv, cname, data);
621                 } else {
622                     mSessionPrototypes.put(swfv, cname, data);
623                 }
624             }
625
626             return data;
627         } catch (Exception JavaDoc e) {
628             return compileFault("could not get " + cname +
629                                 " in scope " + getScopeName(scope), e,
630                                 swfversion);
631         }
632     }
633
634
635
636     /**
637      * removes client swf object from session attribute or webapp attribute.
638      * Note: swfversion not used but may be if we have different versions of
639      * object cached.
640      */

641     //--------------------------------------------------------------------
642
// TODO [2005-02-16 pkang]: think about what happens if swf version
643
// requested is different from the instance prototype we have cached.
644
//--------------------------------------------------------------------
645
Data destroyInstance(String JavaDoc oname, int scope, HttpServletRequest req,
646                          int swfversion) {
647
648         if (mLogger.isDebugEnabled()) {
649             mLogger.debug("destroyInstance(" + oname + ", " + scope);
650         }
651         removeJavaObject(req.getSession(false), scope, oname);
652         return getVoid(swfversion);
653     }
654
655     /*
656      * Get the invocation target for the session or webapp scope.
657      */

658     Object JavaDoc getInvokeTarget(String JavaDoc oname, int scope, HttpServletRequest req) {
659         return getJavaObject(req.getSession(false), scope, oname);
660     }
661
662
663     String JavaDoc getClassName(String JavaDoc url) {
664         if (url.startsWith("java://")) return url.substring(7);
665         return null;
666     }
667
668     Class JavaDoc getClass(String JavaDoc cname) {
669         try {
670             return Class.forName(cname);
671         } catch (ClassNotFoundException JavaDoc e) {
672             mLogger.error("class not found: " + cname);
673         }
674         return null;
675     }
676
677
678
679     /**
680      * pt1 and pt2 are assumed not to be null. If param types are 0, array length
681      * is 0.
682      */

683     boolean paramTypesMatch(Class JavaDoc[] pt1, Class JavaDoc[] pt2) {
684         if (pt1.length != pt2.length)
685             return false;
686
687         for (int i=0; i < pt1.length; i++) {
688             if ( ! pt1[i].isAssignableFrom(pt2[i]) ) {
689                 return false;
690             }
691         }
692         return true;
693     }
694
695     /**
696      * Create instance by calling constructor.
697      */

698     Object JavaDoc getServerInstance(String JavaDoc classname, Class JavaDoc[] argClasses, Object JavaDoc[] argValues)
699         throws Exception JavaDoc {
700
701         if (mLogger.isDebugEnabled()) {
702             mLogger.debug("getServerInstance(" + classname + ")");
703         }
704
705         Class JavaDoc cl = Class.forName(classname);
706
707         Constructor constructor = null;
708         Constructor[] carr = cl.getConstructors();
709         for (int i=0; i < carr.length; i++) {
710             Class JavaDoc[] ptarr = carr[i].getParameterTypes();
711             if ( paramTypesMatch(ptarr, argClasses) ) {
712                 constructor = carr[i];
713                 break;
714             }
715         }
716
717         if (constructor == null) {
718             StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
719             for (int i=0; i < argClasses.length; i++) {
720                 if (i != 0) buf.append(",");
721                 buf.append(argClasses[i].toString());
722             }
723             String JavaDoc msg = "no such constructor found: " + classname +
724                 "(" + buf.toString() + ")";
725             mLogger.error(msg);
726             throw new Exception JavaDoc(msg);
727         }
728
729         return constructor.newInstance(argValues);
730     }
731
732
733
734     
735     /**
736      * Like Class.getMethod() except we allow params that are derived.
737      */

738     Method getMethod(Class JavaDoc cl, String JavaDoc methodName, Class JavaDoc[] params)
739         throws NoSuchMethodException JavaDoc {
740
741         // targetClass.getMethod(methodName, argClasses);
742

743         Method[] classMethods = cl.getMethods();
744         for (int m=0; m < classMethods.length; m++) {
745
746             // find matching method
747
if ( ! methodName.equals(classMethods[m].getName()) ) continue;
748
749             // make sure params match
750
Class JavaDoc[] classParams = classMethods[m].getParameterTypes();
751             if (classParams.length == 0 && params == null)
752                 return classMethods[m];
753
754             if (classParams.length == params.length) {
755                 boolean ok = true;
756                 for (int p=0; p < classParams.length; p++) {
757                     if ( ! classParams[p].isAssignableFrom(params[p]) ) {
758                         ok = false;
759                         break;
760                     }
761                 }
762                 if (ok) return classMethods[m];
763             }
764         }
765
766         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
767         for (int i=0; i < params.length; i++) {
768             if (i != 0) buf.append(", ");
769             buf.append(params[i].toString());
770         }
771         throw new NoSuchMethodException JavaDoc(methodName + "(" + buf.toString() + "): no such method");
772     }
773
774
775     String JavaDoc getScopeName(int scope) {
776         if (SCOPE_SESSION == scope) return SESSION;
777         if (SCOPE_WEBAPP == scope) return WEBAPP;
778         if (SCOPE_NONE == scope) return NONE;
779         return UNKNOWN;
780     }
781
782     int getScope(HttpServletRequest req) {
783         String JavaDoc scope = req.getParameter("scope");
784         if (scope == null) return SCOPE_UNKNOWN;
785         if (SESSION.equals(scope)) return SCOPE_SESSION;
786         if (WEBAPP.equals(scope)) return SCOPE_WEBAPP;
787         if (NONE.equals(scope)) return SCOPE_NONE;
788         return SCOPE_UNKNOWN;
789     }
790
791
792     Object JavaDoc getJavaObject(HttpSession session, int scope, String JavaDoc oname) {
793         if (session == null) return null;
794         Map map = null;
795         if (scope == SCOPE_SESSION) {
796             map = (Map)session.getAttribute(OBJECTS);
797         } else if (scope == SCOPE_WEBAPP) {
798             map = (Map)session.getServletContext().getAttribute(OBJECTS);
799         }
800         return ( map == null ? null : map.get(oname) );
801     }
802
803
804     /**
805      * Add a java object to a session or webapp context.
806      */

807     void setJavaObject(HttpSession session, int scope, String JavaDoc oname, Object JavaDoc val){
808         if (session == null) {
809             if (mLogger.isDebugEnabled()) {
810                 mLogger.debug("setting java object with no session in scope "
811                               + getScopeName(scope));
812             }
813             return;
814         }
815         Map map = null;
816         if (scope == SCOPE_SESSION) {
817             map = (Map)session.getAttribute(OBJECTS);
818             if ( map == null ) {
819                 map = new SessionBindingMap();
820                 session.setAttribute(OBJECTS, map);
821                 // session counter increments happen through SessionBindingMap.
822
}
823         } else if (scope == SCOPE_WEBAPP) {
824             map = (Map)session.getServletContext().getAttribute(OBJECTS);
825             if ( map == null ) {
826                 map = new HashMap();
827                 session.getServletContext().setAttribute(OBJECTS, map);
828             }
829         } else {
830             mLogger.warn("tried setting object with scope " + getScopeName(scope)
831                          + "(" + scope + ")");
832             return;
833         }
834
835         // if a previous object didn't exist, increment object counter.
836
if (map != null) {
837             Object JavaDoc oldVal = map.put(oname, val);
838             if (oldVal == null) {
839                 if (scope == SCOPE_SESSION) {
840                     mSessionObjectsCounter.increment();
841                 } else if (scope == SCOPE_WEBAPP) {
842                     mWebAppObjectsCounter.increment();
843                 }
844             }
845         }
846     }
847
848     /**
849      * Remove a java object from session or webapp context.
850      */

851     void removeJavaObject(HttpSession session, int scope, String JavaDoc oname){
852         if (session == null) {
853             if (mLogger.isDebugEnabled()) {
854                 mLogger.debug("tried removing java object with no session in scope "
855                               + getScopeName(scope) + "(" + scope + ")");
856             }
857             return;
858         }
859         Map map = null;
860         if (scope == SCOPE_SESSION) {
861             map = (Map)session.getAttribute(OBJECTS);
862             // session counter decrements happen through SessionBindingMap.
863
} else if (scope == SCOPE_WEBAPP) {
864             map = (Map)session.getServletContext().getAttribute(OBJECTS);
865         } else {
866             mLogger.warn("tried removing object with scope " + getScopeName(scope));
867             return;
868         }
869         if (map != null) {
870             Object JavaDoc oldVal = map.remove(oname);
871             // if there was an existing one, decrement object counter.
872
if (oldVal != null) {
873                 if (scope == SCOPE_SESSION) {
874                     mSessionObjectsCounter.decrement();
875                 } else if (scope == SCOPE_WEBAPP) {
876                     mWebAppObjectsCounter.decrement();
877                 }
878             }
879         }
880     }
881
882
883     /**
884      * Compile fault exception message.
885      */

886     Data compileFault(Throwable JavaDoc e, int swfversion) {
887         mLogger.error("compileFault", e);
888         return compileFault(e.getMessage(), swfversion);
889     }
890
891     Data compileFault(String JavaDoc mesg, int swfversion) {
892         return compileFault(mesg, null, swfversion);
893     }
894
895     /**
896      * Compile fault response.
897      */

898     Data compileFault(String JavaDoc mesg, Throwable JavaDoc e, int swfversion) {
899         if (e == null) {
900             mLogger.error("compileFault mesg: " + mesg);
901         } else {
902             mLogger.error("compileFault mesg: " + mesg, e);
903         }
904         try {
905             return new ObjectData
906                 ( XMLRPCCompiler.compileFault(XMLUtils.escapeXml(mesg),
907                                               swfversion) );
908         } catch (Exception JavaDoc ex) {
909             mLogger.error("Exception", ex);
910             // this is an error since we can't build a fault response
911
throw new Error JavaDoc(e.getMessage());
912         }
913     }
914
915
916     /**
917      * Helper function for toXML().
918      */

919     static void toXML(StringBuffer JavaDoc sb, String JavaDoc nodeName,
920                       VersionMap m, ThreadSafeCounter objects,
921                       ThreadSafeCounter sessions){
922         sb.append("<").append(nodeName);
923         if (objects != null) {
924             sb.append(" objects=\"").append(objects.getCount()).append("\"");
925         }
926         if (sessions != null) {
927             sb.append(" sessions=\"").append(sessions.getCount()).append("\"");
928         }
929         sb.append(">");
930
931         Iterator iter = m.keySet().iterator();
932         while (iter.hasNext()) {
933             String JavaDoc k = (String JavaDoc)iter.next();
934             Map versions = (Map)m.getVersions(k);
935             Iterator viter = versions.keySet().iterator();
936             sb.append("<prototype class=\"").append(k).append("\"")
937                 .append(" versions=\"");
938             while (viter.hasNext()) {
939                 Integer JavaDoc swfv = (Integer JavaDoc)viter.next();
940                 sb.append(swfv).append(",");
941             }
942             sb.deleteCharAt(sb.length()-1).append("\"/>");
943         }
944         sb.append("</").append(nodeName).append(">");
945     }
946
947
948     public static void clearLoadInfo() {
949         mJavaRPCLoad.reset();
950         mInvokeLoad.reset();
951         mReturnObjectEncodeLoad.reset();
952         mStaticProtoGetLoad.reset();
953         mInstanceProtoCreateLoad.reset();
954         mInstanceProtoGetLoad.reset();
955         mInstanceProtoDestroyLoad.reset();
956         mInstanceGetInvokeTargetLoad.reset();
957         mLastCleared = System.currentTimeMillis();
958     }
959
960     static boolean doXML( int options, int mask ) {
961         return ( options & mask ) == mask;
962     }
963
964     /**
965      * XML string with relevant statistics about JavaDataSource.
966      */

967     synchronized static public String JavaDoc toXML( int options ) {
968         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
969         Date lc = new Date(mLastCleared);
970         sb.append("<javarpcinfo ")
971             .append(" last-cleared=\"").append(lc).append("\"")
972             .append(">");
973         {
974             toXML(sb, "session", mSessionPrototypes, mSessionObjectsCounter,
975                   mSessionCounter);
976             toXML(sb, "webapp", mWebAppPrototypes, mWebAppObjectsCounter, null);
977             toXML(sb, "static", mStaticPrototypes, null, null);
978
979             sb.append(mJavaRPCLoad.toXML("javarpc_load"));
980
981             if ( doXML(options, LOAD_INVOKE) ) {
982                 sb.append(mInvokeLoad.toXML("invoke_load"));
983             }
984             if ( doXML(options, LOAD_STATIC_GET_PROTO) ) {
985                 sb.append(mStaticProtoGetLoad.toXML("static_get_proto_load"));
986             }
987             if ( doXML(options, LOAD_INSTANCE_CREATE_PROTO) ) {
988                 sb.append(mInstanceProtoCreateLoad.toXML("instance_create_proto_load"));
989             }
990             if ( doXML(options, LOAD_INSTANCE_GET_PROTO) ) {
991                 sb.append(mInstanceProtoGetLoad.toXML("instance_get_proto_load"));
992             }
993             if ( doXML(options, LOAD_INSTANCE_DESTROY_PROTO) ) {
994                 sb.append(mInstanceProtoDestroyLoad.toXML("instance_destroy_proto_load"));
995             }
996             if ( doXML(options, LOAD_INSTANCE_GET_INVOKE_TARGET) ) {
997                 sb.append(mInstanceGetInvokeTargetLoad.toXML("instance_get_invoke_target_load"));
998             }
999             if ( doXML(options, LOAD_RETURN_OBJECT_ENCODE) ) {
1000                sb.append(mReturnObjectEncodeLoad.toXML("return_object_encode_load"));
1001            }
1002        }
1003        sb.append("</javarpcinfo>");
1004        return sb.toString();
1005    }
1006
1007
1008
1009    public class EncoderData extends Data
1010    {
1011        DataEncoder mDataEncoder;
1012        long mSize;
1013        public EncoderData(DataEncoder dataEncoder)
1014            throws IOException {
1015            mDataEncoder = dataEncoder;
1016            mSize = dataEncoder.getSize();
1017        }
1018
1019        public String JavaDoc getMimeType() {
1020            return MimeType.SWF;
1021        }
1022
1023        /**
1024         * @return the encoded XML
1025         */

1026        public InputStream getInputStream()
1027            throws IOException {
1028            return mDataEncoder.getInputStream();
1029        }
1030
1031        public long size() {
1032            return mSize;
1033        }
1034    }
1035
1036
1037    /**
1038     * A data object to hold session object.
1039     */

1040    public class ObjectData extends Data
1041    {
1042        byte[] mObject;
1043        public ObjectData(byte[] object) {
1044            mObject = object;
1045        }
1046
1047        public String JavaDoc getMimeType() {
1048            return MimeType.SWF;
1049        }
1050
1051        public InputStream getInputStream()
1052            throws IOException {
1053            return new ByteArrayInputStream(mObject);
1054        }
1055
1056        public long size() {
1057            return mObject.length;
1058        }
1059    }
1060}
1061
Popular Tags