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]

Reply via email to