garyp 00/10/08 16:50:24
Modified: java/src/org/apache/xalan/extensions
ExtensionHandlerJavaPackage.java
Log:
Implement function-available, element-available, processElement; clean up
javadoc
Revision Changes Path
1.2 +138 -35
xml-xalan/java/src/org/apache/xalan/extensions/ExtensionHandlerJavaPackage.java
Index: ExtensionHandlerJavaPackage.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/extensions/ExtensionHandlerJavaPackage.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ExtensionHandlerJavaPackage.java 2000/10/08 03:34:30 1.1
+++ ExtensionHandlerJavaPackage.java 2000/10/08 23:50:23 1.2
@@ -59,6 +59,7 @@
import java.util.Hashtable;
import java.util.Vector;
import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.lang.reflect.Constructor;
import java.io.IOException;
@@ -75,28 +76,37 @@
/**
* <meta name="usage" content="internal"/>
- * Class handling the java extension namespaces for XPath that
- * represent packages. The package namespace should begin with
- * xalan:// but this is not currently enforced.
- * Provides functions to test a function's existence and call a function
+ * Represents an extension namespace for XPath that handles java packages
+ * that may be fully or partially specified.
+ * It is recommended that the class URI be of one of the following forms:
+ * <pre>
+ * xalan://partial.class.name
+ * xalan://
+ * http://xml.apache.org/xslt/java (which is the same as xalan://)
+ * </pre>
+ * However, we do not enforce this. If the class name contains a
+ * a /, we only use the part to the right of the rightmost slash.
+ * In addition, we ignore any "class:" prefix.
+ * Provides functions to test a function's existence and call a function.
+ * Also provides functions to test an element's existence and call an
+ * element.
*
+ * @author <a href="mailto:[EMAIL PROTECTED]">Gary L Peskin</a>
+ *
*/
+
public class ExtensionHandlerJavaPackage extends ExtensionHandlerJava
{
-
/**
* Construct a new extension namespace handler given all the information
* needed.
*
* @param namespaceUri the extension namespace URI that I'm implementing
- * @param funcNames string containing list of functions of extension NS
- * @param lang language of code implementing the extension
- * @param srcURL value of src attribute (if any) - treated as a URL
- * or a classname depending on the value of lang. If
- * srcURL is not null, then scriptSrc is ignored.
- * @param scriptSrc the actual script code (if any)
+ * @param scriptLang language of code implementing the extension
+ * @param className the beginning of the class name of the class. This
+ * should be followed by a dot (.)
*/
public ExtensionHandlerJavaPackage(String namespaceUri,
String scriptLang,
@@ -108,37 +118,80 @@
/**
* Tests whether a certain function name is known within this namespace.
- * Since this is for a package , we simply try to find a
- * method or constructor for the fully qualified class name passed in the
- * argument. There is no guarantee, of course, that this will actually
- * work at runtime since we may have problems converting the arguments.
- *
+ * Since this is for a package, we concatenate the package name used when
+ * this handler was created and the function name specified in the
argument.
+ * There is
+ * no information regarding the arguments to the function call or
+ * whether the method implementing the function is a static method or
+ * an instance method.
* @param function name of the function being tested
- *
* @return true if its known, false if not.
*/
+
public boolean isFunctionAvailable(String function)
{
- // TODO: This function needs to be implemented.
- return true;
+ try
+ {
+ String fullName = m_className + function;
+ int lastDot = fullName.lastIndexOf(".");
+ if (lastDot >= 0)
+ {
+ Class myClass = Class.forName(fullName.substring(0, lastDot));
+ Method[] methods = myClass.getMethods();
+ int nMethods = methods.length;
+ function = fullName.substring(lastDot + 1);
+ for (int i = 0; i < nMethods; i++)
+ {
+ if (methods[i].getName().equals(function))
+ return true;
+ }
+ }
+ }
+ catch (ClassNotFoundException cnfe) {}
+
+ return false;
}
/**
* Tests whether a certain element name is known within this namespace.
- * Since this is for a package , we simply try to find a
- * method or constructor for the fully qualified class name passed in the
- * argument. There is no guarantee, of course, that this will actually
- * work at runtime since we may have problems converting the arguments.
- *
+ * Looks for a method with the appropriate name and signature.
+ * This method examines both static and instance methods.
* @param function name of the function being tested
- *
* @return true if its known, false if not.
*/
+
public boolean isElementAvailable(String element)
{
- // TODO: This function needs to be implemented.
- return true;
+ try
+ {
+ String fullName = m_className + element;
+ int lastDot = fullName.lastIndexOf(".");
+ if (lastDot >= 0)
+ {
+ Class myClass = Class.forName(fullName.substring(0, lastDot));
+ Method[] methods = myClass.getMethods();
+ int nMethods = methods.length;
+ element = fullName.substring(lastDot + 1);
+ for (int i = 0; i < nMethods; i++)
+ {
+ if (methods[i].getName().equals(element))
+ {
+ Class[] paramTypes = methods[i].getParameterTypes();
+ if ( (paramTypes.length == 2)
+ && paramTypes[0].isAssignableFrom(
+
org.apache.xalan.extensions.XSLProcessorContext.class)
+ && paramTypes[1].isAssignableFrom(org.w3c.dom.Element.class) )
+ {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ catch (ClassNotFoundException cnfe) {}
+
+ return false;
}
@@ -338,7 +391,8 @@
/**
* Process a call to this extension namespace via an element. As a side
* effect, the results are sent to the TransformerImpl's result tree.
- *
+ * For this namespace, only static element methods are currently supported.
+ * If instance methods are needed, please let us know your requirements.
* @param localPart Element name's local part.
* @param element The extension element being processed.
* @param transformer Handle to TransformerImpl.
@@ -347,11 +401,8 @@
* @param sourceTree The root of the source tree (but don't assume
* it's a Document).
* @param sourceNode The current context node.
- *
- * @exception XSLProcessorException thrown if something goes wrong
- * while running the extension handler.
- * @exception MalformedURLException if loading trouble
- * @exception FileNotFoundException if loading trouble
+ * @param mode The current mode.
+ * @param methodKey A key that uniquely identifies this element call.
* @exception IOException if loading trouble
* @exception SAXException if parsing trouble
*/
@@ -366,8 +417,60 @@
Object methodKey)
throws SAXException, IOException
{
- throw new SAXException("Extension elements are not yet implemented for "
- + "non-class namespaces: "
+ localPart);
+ Object result = null;
+ Class classObj;
+
+ Method m = (Method) getFromCache(methodKey, null, null);
+ if (null == m)
+ {
+ try
+ {
+ String fullName = m_className + localPart;
+ int lastDot = fullName.lastIndexOf(".");
+ if (lastDot < 0)
+ throw new SAXException("Invalid element name specified " +
fullName);
+ try
+ {
+ classObj = Class.forName(fullName.substring(0, lastDot));
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new SAXException(e);
+ }
+ localPart = fullName.substring(lastDot + 1);
+ m = MethodResolver.getElementMethod(classObj, localPart);
+ if (!Modifier.isStatic(m.getModifiers()))
+ throw new SAXException("Element name method must be static " +
fullName);
+ }
+ catch (Exception e)
+ {
+ // e.printStackTrace ();
+ throw new SAXException (e.getMessage (), e);
+ }
+ putToCache(methodKey, null, null, m);
+ }
+
+ XSLProcessorContext xpc = new XSLProcessorContext(transformer,
+ stylesheetTree,
+ sourceTree,
+ sourceNode,
+ mode);
+
+ try
+ {
+ result = m.invoke(null, new Object[] {xpc, element});
+ }
+ catch (Exception e)
+ {
+ // e.printStackTrace ();
+ throw new SAXException (e.getMessage (), e);
+ }
+
+ if (result != null)
+ {
+ xpc.outputToResultTree (stylesheetTree, result);
+ }
+
}
}