tmiller 02/04/09 11:52:26
Modified: java/src/org/apache/xalan/xsltc/compiler Tag:
jaxp-ri-1_2_0-fcs-branch FunctionAvailableCall.java
FunctionCall.java
Log:
bug 7375 fixed, handles ext java functions now
Revision Changes Path
No revision
No revision
1.5.4.1 +163 -13
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/FunctionAvailableCall.java
Index: FunctionAvailableCall.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/FunctionAvailableCall.java,v
retrieving revision 1.5
retrieving revision 1.5.4.1
diff -u -r1.5 -r1.5.4.1
--- FunctionAvailableCall.java 1 Feb 2002 20:07:08 -0000 1.5
+++ FunctionAvailableCall.java 9 Apr 2002 18:52:26 -0000 1.5.4.1
@@ -1,5 +1,5 @@
/*
- * @(#)$Id: FunctionAvailableCall.java,v 1.5 2002/02/01 20:07:08 tmiller Exp
$
+ * @(#)$Id: FunctionAvailableCall.java,v 1.5.4.1 2002/04/09 18:52:26 tmiller
Exp $
*
* The Apache Software License, Version 1.1
*
@@ -56,7 +56,7 @@
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
- * @author Jacek Ambroziak
+ * @author G. Todd Miller
* @author Santiago Pericas-Geertsen
*
*/
@@ -64,38 +64,188 @@
package org.apache.xalan.xsltc.compiler;
import java.util.Vector;
-import java.util.HashSet;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Method;
import org.apache.xalan.xsltc.compiler.util.Type;
import org.apache.bcel.generic.*;
import org.apache.xalan.xsltc.compiler.util.*;
+import org.apache.xalan.xsltc.runtime.TransletLoader;
final class FunctionAvailableCall extends FunctionCall {
+ private boolean _isFunctionAvailable = false;
+ private Expression _arg;
+ private String _namespaceOfFunct =null;
+ private String _nameOfFunct =null;
+
+
+ /**
+ * Constructs a FunctionAvailableCall FunctionCall. Takes the
+ * function name qname, for example, 'function-available', and a list
+ * of arguments where the arguments must be instances of
+ * LiteralExpression. The test for availability considers
+ * internal xsl functions such as 'floor' as well as external
+ * Java functions, such as 'java.lang.Math.sin'. The case of
+ * external functions is handled here, the case of internal
+ * functions is handled in getResult.
+ */
public FunctionAvailableCall(QName fname, Vector arguments) {
super(fname, arguments);
+ _arg = (Expression)arguments.elementAt(0);
+ _type = null;
+ if (_arg instanceof LiteralExpr) {
+ LiteralExpr arg = (LiteralExpr)_arg;
+ _namespaceOfFunct = arg.getNamespace();
+ _nameOfFunct = arg.getValue();
+ if ((_namespaceOfFunct != null) &&
+ (!_namespaceOfFunct.equals(Constants.EMPTYSTRING)))
+ {
+ // the function is external, such as a java function
+ _isFunctionAvailable = hasMethods();
+ }
+ // the case of internal function is handled in getResult.
+ }
+ // case where _arg is not instanceof LiteralExpr can not be handled.
}
/**
- * Force the argument to this function to be a literal string.
+ * Argument of function-available call must be literal, typecheck
+ * returns the type of function-available to be boolean.
*/
public Type typeCheck(SymbolTable stable) throws TypeCheckError {
- if (argument() instanceof LiteralExpr) {
- return _type = Type.Boolean;
+ // may be already set
+ if ( _type != null ) {
+ return _type;
+ }
+ if (_arg instanceof LiteralExpr) {
+ _type = Type.Boolean;
+ return Type.Boolean;
}
ErrorMsg err = new ErrorMsg(ErrorMsg.NEED_LITERAL_ERR,
- "function-available", this);
+ "function-available", this);
throw new TypeCheckError(err);
}
/**
- * Returns the result that this function will return
+ * (For ext. java functions only)
+ * Parses the argument to function-available to extract the package
+ * qualified class name, for example, given the argument
+ * 'java:java.lang.Math.sin', getClassName would return
+ * 'java.lang.Math'. See also 'getMethodName'.
+ */
+ private String getClassName(String argValue){
+ int colonSep = argValue.indexOf(":");
+ if (colonSep != -1) {
+ argValue = argValue.substring(colonSep+1);
+ }
+ int lastDot = argValue.lastIndexOf(".");
+ if (lastDot != -1) {
+ argValue = argValue.substring(0, lastDot);
+ }
+ return argValue;
+ }
+
+ /**
+ * (For ext. java functions only)
+ * Parses the argument to function-available
+ * to extract the method name, for example, given the argument
+ * 'java.lang.Math.sin', getMethodName would return 'sin'.
+ */
+ private String getMethodName(String argValue){
+ int lastDot = argValue.lastIndexOf(".");
+ if (lastDot != -1) {
+ argValue = argValue.substring(lastDot+1);
+ }
+ return argValue;
+ }
+
+ /**
+ * (For java external functions only)
+ * Creates a full package qualified
+ * function name taking into account the namespace and the
+ * function name derived from the argument passed to function-available.
+ * For example, given a name of 'java:java.lang.Math.sin' and a
+ * namespace of 'http://xml.apache.org/xalan/xsltc/java' this routine
+ * constructs a uri and then derives the class name
+ * 'java.lang.Math.sin' from the uri. The uri in this example would
+ * be 'http://xml.apache.org/xalan/xsltc/java.java.lang.Math.sin'
+ */
+ private String getExternalFunctionName() {
+ int colonIndex = _nameOfFunct.indexOf(":");
+ String uri = _namespaceOfFunct +
+ "." + _nameOfFunct.substring(colonIndex+1);
+ try{
+ return getClassNameFromUri(uri);
+ } catch (TypeCheckError e) {
+ return null;
+ }
+ }
+
+ /**
+ * for external java functions only: reports on whether or not
+ * the specified method is found in the specifed class.
+ */
+ private boolean hasMethods() {
+
+ LiteralExpr arg = (LiteralExpr)_arg;
+ final String externalFunctName = getExternalFunctionName();
+ if (externalFunctName == null) {
+ return false;
+ }
+ final String className = getClassName(externalFunctName);
+
+ if (_namespaceOfFunct.startsWith(JAVA_EXT_PREFIX) ||
+ _namespaceOfFunct.startsWith(JAVA_EXT_XALAN)) {
+ try {
+ TransletLoader loader = new TransletLoader();
+ final Class clazz = loader.loadClass(className);
+
+ if (clazz == null) {
+ final ErrorMsg msg =
+ new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR,
className);
+ getParser().reportError(Constants.ERROR, msg);
+ }
+ else {
+ final String methodName =
getMethodName(externalFunctName);
+ final Method[] methods = clazz.getDeclaredMethods();
+
+ for (int i = 0; i < methods.length; i++) {
+ final int mods = methods[i].getModifiers();
+
+ if (Modifier.isPublic(mods)
+ && Modifier.isStatic(mods)
+ && methods[i].getName().equals(methodName))
+ {
+ return true;
+ }
+ }
+ }
+ }
+ catch (ClassNotFoundException e) {
+ final ErrorMsg msg =
+ new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, className);
+ getParser().reportError(Constants.ERROR, msg);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * reports on whether the function specified in the argument to
+ * xslt function 'function-available' was found.
*/
public boolean getResult() {
- final Parser parser = getParser();
- final LiteralExpr arg = (LiteralExpr)argument();
- return(parser.functionSupported(arg.getValue()));
+ if ((_namespaceOfFunct == null) ||
+ (_namespaceOfFunct.equals(Constants.EMPTYSTRING)))
+ {
+ // no namespace, so the function is an internal xslt function.
+ final Parser parser = getParser();
+ _isFunctionAvailable = parser.functionSupported(_nameOfFunct);
+ }
+ return _isFunctionAvailable;
}
+
/**
* Calls to 'function-available' are resolved at compile time since
* the namespaces declared in the stylsheet are not available at run
@@ -103,7 +253,7 @@
*/
public void translate(ClassGenerator classGen, MethodGenerator
methodGen) {
final ConstantPoolGen cpg = classGen.getConstantPool();
- final boolean result = getResult();
- methodGen.getInstructionList().append(new PUSH(cpg, result));
+ methodGen.getInstructionList().append(new PUSH(cpg, getResult()));
}
+
}
1.12.4.2 +3 -3
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/FunctionCall.java
Index: FunctionCall.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/FunctionCall.java,v
retrieving revision 1.12.4.1
retrieving revision 1.12.4.2
diff -u -r1.12.4.1 -r1.12.4.2
--- FunctionCall.java 5 Apr 2002 22:45:25 -0000 1.12.4.1
+++ FunctionCall.java 9 Apr 2002 18:52:26 -0000 1.12.4.2
@@ -1,5 +1,5 @@
/*
- * @(#)$Id: FunctionCall.java,v 1.12.4.1 2002/04/05 22:45:25 santiagopg Exp $
+ * @(#)$Id: FunctionCall.java,v 1.12.4.2 2002/04/09 18:52:26 tmiller Exp $
*
* The Apache Software License, Version 1.1
*
@@ -86,8 +86,8 @@
private final static Vector EMPTY_ARG_LIST = new Vector(0);
// Valid namespaces for Java function-call extension
- private final static String JAVA_EXT_PREFIX = TRANSLET_URI + "/java";
- private final static String JAVA_EXT_XALAN =
+ protected final static String JAVA_EXT_PREFIX = TRANSLET_URI + "/java";
+ protected final static String JAVA_EXT_XALAN =
"http://xml.apache.org/xslt/java";
// External Java function's class/method/signature
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]