KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xalan > extensions > ExtensionHandlerJavaPackage


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 /*
17  * $Id: ExtensionHandlerJavaPackage.java,v 1.19 2004/02/11 05:26:23 minchau Exp $
18  */

19 package org.apache.xalan.extensions;
20
21 import java.io.IOException JavaDoc;
22 import java.lang.reflect.Constructor JavaDoc;
23 import java.lang.reflect.InvocationTargetException JavaDoc;
24 import java.lang.reflect.Method JavaDoc;
25 import java.lang.reflect.Modifier JavaDoc;
26 import java.util.Vector JavaDoc;
27
28 import javax.xml.transform.TransformerException JavaDoc;
29
30 import org.apache.xalan.res.XSLMessages;
31 import org.apache.xalan.res.XSLTErrorResources;
32 import org.apache.xalan.templates.ElemTemplateElement;
33 import org.apache.xalan.templates.Stylesheet;
34 import org.apache.xalan.trace.ExtensionEvent;
35 import org.apache.xalan.transformer.TransformerImpl;
36 import org.apache.xpath.functions.FuncExtFunction;
37 import org.apache.xpath.objects.XObject;
38
39 /**
40  * Represents an extension namespace for XPath that handles java packages
41  * that may be fully or partially specified.
42  * It is recommended that the class URI be of one of the following forms:
43  * <pre>
44  * xalan://partial.class.name
45  * xalan://
46  * http://xml.apache.org/xalan/java (which is the same as xalan://)
47  * </pre>
48  * However, we do not enforce this. If the class name contains a
49  * a /, we only use the part to the right of the rightmost slash.
50  * In addition, we ignore any "class:" prefix.
51  * Provides functions to test a function's existence and call a function.
52  * Also provides functions to test an element's existence and call an
53  * element.
54  *
55  * @author <a HREF="mailto:garyp@firstech.com">Gary L Peskin</a>
56  *
57  * @xsl.usage internal
58  */

59
60
61 public class ExtensionHandlerJavaPackage extends ExtensionHandlerJava
62 {
63
64   /**
65    * Construct a new extension namespace handler given all the information
66    * needed.
67    *
68    * @param namespaceUri the extension namespace URI that I'm implementing
69    * @param scriptLang language of code implementing the extension
70    * @param className the beginning of the class name of the class. This
71    * should be followed by a dot (.)
72    */

73   public ExtensionHandlerJavaPackage(String JavaDoc namespaceUri,
74                                      String JavaDoc scriptLang,
75                                      String JavaDoc className)
76   {
77     super(namespaceUri, scriptLang, className);
78   }
79
80
81   /**
82    * Tests whether a certain function name is known within this namespace.
83    * Since this is for a package, we concatenate the package name used when
84    * this handler was created and the function name specified in the argument.
85    * There is
86    * no information regarding the arguments to the function call or
87    * whether the method implementing the function is a static method or
88    * an instance method.
89    * @param function name of the function being tested
90    * @return true if its known, false if not.
91    */

92
93   public boolean isFunctionAvailable(String JavaDoc function)
94   {
95     try
96     {
97       String JavaDoc fullName = m_className + function;
98       int lastDot = fullName.lastIndexOf(".");
99       if (lastDot >= 0)
100       {
101         Class JavaDoc myClass = getClassForName(fullName.substring(0, lastDot));
102         Method JavaDoc[] methods = myClass.getMethods();
103         int nMethods = methods.length;
104         function = fullName.substring(lastDot + 1);
105         for (int i = 0; i < nMethods; i++)
106         {
107           if (methods[i].getName().equals(function))
108             return true;
109         }
110       }
111     }
112     catch (ClassNotFoundException JavaDoc cnfe) {}
113
114     return false;
115   }
116
117
118   /**
119    * Tests whether a certain element name is known within this namespace.
120    * Looks for a method with the appropriate name and signature.
121    * This method examines both static and instance methods.
122    * @param function name of the function being tested
123    * @return true if its known, false if not.
124    */

125
126   public boolean isElementAvailable(String JavaDoc element)
127   {
128     try
129     {
130       String JavaDoc fullName = m_className + element;
131       int lastDot = fullName.lastIndexOf(".");
132       if (lastDot >= 0)
133       {
134         Class JavaDoc myClass = getClassForName(fullName.substring(0, lastDot));
135         Method JavaDoc[] methods = myClass.getMethods();
136         int nMethods = methods.length;
137         element = fullName.substring(lastDot + 1);
138         for (int i = 0; i < nMethods; i++)
139         {
140           if (methods[i].getName().equals(element))
141           {
142             Class JavaDoc[] paramTypes = methods[i].getParameterTypes();
143             if ( (paramTypes.length == 2)
144               && paramTypes[0].isAssignableFrom(
145                                      org.apache.xalan.extensions.XSLProcessorContext.class)
146               && paramTypes[1].isAssignableFrom(
147                                        org.apache.xalan.templates.ElemExtensionCall.class) )
148             {
149               return true;
150             }
151           }
152         }
153       }
154     }
155     catch (ClassNotFoundException JavaDoc cnfe) {}
156
157     return false;
158   }
159
160
161   /**
162    * Process a call to a function in the package java namespace.
163    * There are three possible types of calls:
164    * <pre>
165    * Constructor:
166    * packagens:class.name.new(arg1, arg2, ...)
167    *
168    * Static method:
169    * packagens:class.name.method(arg1, arg2, ...)
170    *
171    * Instance method:
172    * packagens:method(obj, arg1, arg2, ...)
173    * </pre>
174    * We use the following rules to determine the type of call made:
175    * <ol type="1">
176    * <li>If the function name ends with a ".new", call the best constructor for
177    * class whose name is formed by concatenating the value specified on
178    * the namespace with the value specified in the function invocation
179    * before ".new".</li>
180    * <li>If the function name contains a period, call the best static method "method"
181    * in the class whose name is formed by concatenating the value specified on
182    * the namespace with the value specified in the function invocation.</li>
183    * <li>Otherwise, call the best instance method "method"
184    * in the class whose name is formed by concatenating the value specified on
185    * the namespace with the value specified in the function invocation.
186    * Note that a static method of the same
187    * name will <i>not</i> be called in the current implementation. This
188    * module does not verify that the obj argument is a member of the
189    * package namespace.</li>
190    * </ol>
191    *
192    * @param funcName Function name.
193    * @param args The arguments of the function call.
194    *
195    * @return the return value of the function evaluation.
196    *
197    * @throws TransformerException if parsing trouble
198    */

199
200   public Object JavaDoc callFunction (String JavaDoc funcName,
201                               Vector JavaDoc args,
202                               Object JavaDoc methodKey,
203                               ExpressionContext exprContext)
204     throws TransformerException JavaDoc
205   {
206
207     String JavaDoc className;
208     String JavaDoc methodName;
209     Class JavaDoc classObj;
210     Object JavaDoc targetObject;
211     int lastDot = funcName.lastIndexOf(".");
212     Object JavaDoc[] methodArgs;
213     Object JavaDoc[][] convertedArgs;
214     Class JavaDoc[] paramTypes;
215
216     try
217     {
218
219       if (funcName.endsWith(".new")) { // Handle constructor call
220

221         methodArgs = new Object JavaDoc[args.size()];
222         convertedArgs = new Object JavaDoc[1][];
223         for (int i = 0; i < methodArgs.length; i++)
224         {
225           methodArgs[i] = args.elementAt(i);
226         }
227         Constructor JavaDoc c = (Constructor JavaDoc) getFromCache(methodKey, null, methodArgs);
228         if (c != null)
229         {
230           try
231           {
232             paramTypes = c.getParameterTypes();
233             MethodResolver.convertParams(methodArgs, convertedArgs, paramTypes, exprContext);
234             return c.newInstance(convertedArgs[0]);
235           }
236           catch (InvocationTargetException JavaDoc ite)
237           {
238             throw ite;
239           }
240           catch(Exception JavaDoc e)
241           {
242             // Must not have been the right one
243
}
244         }
245         className = m_className + funcName.substring(0, lastDot);
246         try
247         {
248           classObj = getClassForName(className);
249         }
250         catch (ClassNotFoundException JavaDoc e)
251         {
252           throw new TransformerException JavaDoc(e);
253         }
254         c = MethodResolver.getConstructor(classObj,
255                                           methodArgs,
256                                           convertedArgs,
257                                           exprContext);
258         putToCache(methodKey, null, methodArgs, c);
259         if (TransformerImpl.S_DEBUG) {
260             TransformerImpl trans = (TransformerImpl)exprContext.getXPathContext().getOwnerObject();
261             trans.getTraceManager().fireExtensionEvent(new ExtensionEvent(trans, c, convertedArgs[0]));
262             Object JavaDoc result;
263             try {
264                 result = c.newInstance(convertedArgs[0]);
265             } catch (Exception JavaDoc e) {
266                 throw e;
267             } finally {
268                 trans.getTraceManager().fireExtensionEndEvent(new ExtensionEvent(trans, c, convertedArgs[0]));
269             }
270             return result;
271         } else
272             return c.newInstance(convertedArgs[0]);
273       }
274
275       else if (-1 != lastDot) { // Handle static method call
276

277         methodArgs = new Object JavaDoc[args.size()];
278         convertedArgs = new Object JavaDoc[1][];
279         for (int i = 0; i < methodArgs.length; i++)
280         {
281           methodArgs[i] = args.elementAt(i);
282         }
283         Method JavaDoc m = (Method JavaDoc) getFromCache(methodKey, null, methodArgs);
284         if (m != null && !TransformerImpl.S_DEBUG)
285         {
286           try
287           {
288             paramTypes = m.getParameterTypes();
289             MethodResolver.convertParams(methodArgs, convertedArgs, paramTypes, exprContext);
290             return m.invoke(null, convertedArgs[0]);
291           }
292           catch (InvocationTargetException JavaDoc ite)
293           {
294             throw ite;
295           }
296           catch(Exception JavaDoc e)
297           {
298             // Must not have been the right one
299
}
300         }
301         className = m_className + funcName.substring(0, lastDot);
302         methodName = funcName.substring(lastDot + 1);
303         try
304         {
305           classObj = getClassForName(className);
306         }
307         catch (ClassNotFoundException JavaDoc e)
308         {
309           throw new TransformerException JavaDoc(e);
310         }
311         m = MethodResolver.getMethod(classObj,
312                                      methodName,
313                                      methodArgs,
314                                      convertedArgs,
315                                      exprContext,
316                                      MethodResolver.STATIC_ONLY);
317         putToCache(methodKey, null, methodArgs, m);
318         if (TransformerImpl.S_DEBUG) {
319             TransformerImpl trans = (TransformerImpl)exprContext.getXPathContext().getOwnerObject();
320             trans.getTraceManager().fireExtensionEvent(m, null, convertedArgs[0]);
321             Object JavaDoc result;
322             try {
323                 result = m.invoke(null, convertedArgs[0]);
324             } catch (Exception JavaDoc e) {
325                 throw e;
326             } finally {
327                 trans.getTraceManager().fireExtensionEndEvent(m, null, convertedArgs[0]);
328             }
329             return result;
330         }
331         else
332             return m.invoke(null, convertedArgs[0]);
333       }
334
335       else { // Handle instance method call
336

337         if (args.size() < 1)
338         {
339           throw new TransformerException JavaDoc(XSLMessages.createMessage(XSLTErrorResources.ER_INSTANCE_MTHD_CALL_REQUIRES, new Object JavaDoc[]{funcName })); //"Instance method call to method " + funcName
340
//+ " requires an Object instance as first argument");
341
}
342         targetObject = args.elementAt(0);
343         if (targetObject instanceof XObject) // Next level down for XObjects
344
targetObject = ((XObject) targetObject).object();
345         methodArgs = new Object JavaDoc[args.size() - 1];
346         convertedArgs = new Object JavaDoc[1][];
347         for (int i = 0; i < methodArgs.length; i++)
348         {
349           methodArgs[i] = args.elementAt(i+1);
350         }
351         Method JavaDoc m = (Method JavaDoc) getFromCache(methodKey, targetObject, methodArgs);
352         if (m != null)
353         {
354           try
355           {
356             paramTypes = m.getParameterTypes();
357             MethodResolver.convertParams(methodArgs, convertedArgs, paramTypes, exprContext);
358             return m.invoke(targetObject, convertedArgs[0]);
359           }
360           catch (InvocationTargetException JavaDoc ite)
361           {
362             throw ite;
363           }
364           catch(Exception JavaDoc e)
365           {
366             // Must not have been the right one
367
}
368         }
369         classObj = targetObject.getClass();
370         m = MethodResolver.getMethod(classObj,
371                                      funcName,
372                                      methodArgs,
373                                      convertedArgs,
374                                      exprContext,
375                                      MethodResolver.INSTANCE_ONLY);
376         putToCache(methodKey, targetObject, methodArgs, m);
377         if (TransformerImpl.S_DEBUG) {
378             TransformerImpl trans = (TransformerImpl)exprContext.getXPathContext().getOwnerObject();
379             trans.getTraceManager().fireExtensionEvent(m, targetObject, convertedArgs[0]);
380             Object JavaDoc result;
381             try {
382                 result = m.invoke(targetObject, convertedArgs[0]);
383             } catch (Exception JavaDoc e) {
384                 throw e;
385             } finally {
386                 trans.getTraceManager().fireExtensionEndEvent(m, targetObject, convertedArgs[0]);
387             }
388             return result;
389         } else
390             return m.invoke(targetObject, convertedArgs[0]);
391       }
392     }
393     catch (InvocationTargetException JavaDoc ite)
394     {
395       Throwable JavaDoc resultException = ite;
396       Throwable JavaDoc targetException = ite.getTargetException();
397  
398       if (targetException instanceof TransformerException JavaDoc)
399         throw ((TransformerException JavaDoc)targetException);
400       else if (targetException != null)
401         resultException = targetException;
402             
403       throw new TransformerException JavaDoc(resultException);
404     }
405     catch (Exception JavaDoc e)
406     {
407       // e.printStackTrace();
408
throw new TransformerException JavaDoc(e);
409     }
410   }
411
412   /**
413    * Process a call to an XPath extension function
414    *
415    * @param extFunction The XPath extension function
416    * @param args The arguments of the function call.
417    * @param exprContext The context in which this expression is being executed.
418    * @return the return value of the function evaluation.
419    * @throws TransformerException
420    */

421   public Object JavaDoc callFunction(FuncExtFunction extFunction,
422                              Vector JavaDoc args,
423                              ExpressionContext exprContext)
424       throws TransformerException JavaDoc
425   {
426     return callFunction(extFunction.getFunctionName(), args,
427                         extFunction.getMethodKey(), exprContext);
428   }
429
430   /**
431    * Process a call to this extension namespace via an element. As a side
432    * effect, the results are sent to the TransformerImpl's result tree.
433    * For this namespace, only static element methods are currently supported.
434    * If instance methods are needed, please let us know your requirements.
435    * @param localPart Element name's local part.
436    * @param element The extension element being processed.
437    * @param transformer Handle to TransformerImpl.
438    * @param stylesheetTree The compiled stylesheet tree.
439    * @param mode The current mode.
440    * @param sourceTree The root of the source tree (but don't assume
441    * it's a Document).
442    * @param sourceNode The current context node.
443    * @param mode The current mode.
444    * @param methodKey A key that uniquely identifies this element call.
445    * @throws IOException if loading trouble
446    * @throws TransformerException if parsing trouble
447    */

448
449   public void processElement (String JavaDoc localPart,
450                               ElemTemplateElement element,
451                               TransformerImpl transformer,
452                               Stylesheet stylesheetTree,
453                               Object JavaDoc methodKey)
454     throws TransformerException JavaDoc, IOException JavaDoc
455   {
456     Object JavaDoc result = null;
457     Class JavaDoc classObj;
458
459     Method JavaDoc m = (Method JavaDoc) getFromCache(methodKey, null, null);
460     if (null == m)
461     {
462       try
463       {
464         String JavaDoc fullName = m_className + localPart;
465         int lastDot = fullName.lastIndexOf(".");
466         if (lastDot < 0)
467           throw new TransformerException JavaDoc(XSLMessages.createMessage(XSLTErrorResources.ER_INVALID_ELEMENT_NAME, new Object JavaDoc[]{fullName })); //"Invalid element name specified " + fullName);
468
try
469         {
470           classObj = getClassForName(fullName.substring(0, lastDot));
471         }
472         catch (ClassNotFoundException JavaDoc e)
473         {
474           throw new TransformerException JavaDoc(e);
475         }
476         localPart = fullName.substring(lastDot + 1);
477         m = MethodResolver.getElementMethod(classObj, localPart);
478         if (!Modifier.isStatic(m.getModifiers()))
479           throw new TransformerException JavaDoc(XSLMessages.createMessage(XSLTErrorResources.ER_ELEMENT_NAME_METHOD_STATIC, new Object JavaDoc[]{fullName })); //"Element name method must be static " + fullName);
480
}
481       catch (Exception JavaDoc e)
482       {
483         // e.printStackTrace ();
484
throw new TransformerException JavaDoc (e);
485       }
486       putToCache(methodKey, null, null, m);
487     }
488
489     XSLProcessorContext xpc = new XSLProcessorContext(transformer,
490                                                       stylesheetTree);
491
492     try
493     {
494       if (TransformerImpl.S_DEBUG) {
495           transformer.getTraceManager().fireExtensionEvent(m, null, new Object JavaDoc[] {xpc, element});
496         try {
497             result = m.invoke(null, new Object JavaDoc[] {xpc, element});
498         } catch (Exception JavaDoc e) {
499             throw e;
500         } finally {
501             transformer.getTraceManager().fireExtensionEndEvent(m, null, new Object JavaDoc[] {xpc, element});
502         }
503       } else
504         result = m.invoke(null, new Object JavaDoc[] {xpc, element});
505     }
506     catch (InvocationTargetException JavaDoc ite)
507     {
508       Throwable JavaDoc resultException = ite;
509       Throwable JavaDoc targetException = ite.getTargetException();
510  
511       if (targetException instanceof TransformerException JavaDoc)
512         throw ((TransformerException JavaDoc)targetException);
513       else if (targetException != null)
514         resultException = targetException;
515             
516       throw new TransformerException JavaDoc(resultException);
517     }
518     catch (Exception JavaDoc e)
519     {
520       // e.printStackTrace ();
521
throw new TransformerException JavaDoc (e);
522     }
523
524     if (result != null)
525     {
526       xpc.outputToResultTree (stylesheetTree, result);
527     }
528  
529   }
530
531 }
532
Popular Tags