aruny 2004/02/23 09:29:36
Modified: java/src/org/apache/xalan/xsltc/compiler Constants.java
FunctionCall.java Param.java
java/src/org/apache/xalan/xsltc/compiler/util
ReferenceType.java
Added: java/src/org/apache/xalan/xsltc/runtime CallFunction.java
ObjectFactory.java SecuritySupport.java
SecuritySupport12.java
Log:
Description : Adding the basic functionality for resolving external function
dynamically. If static resolution fails then Dynamic resolution is used as last
resort
Revision Changes Path
1.40 +5 -1
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Constants.java
Index: Constants.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Constants.java,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -r1.39 -r1.40
--- Constants.java 16 Feb 2004 22:24:28 -0000 1.39
+++ Constants.java 23 Feb 2004 17:29:35 -0000 1.40
@@ -258,6 +258,8 @@
public static final String TRANSLET_OUTPUT_BASE
= "org.apache.xalan.xsltc.TransletOutputBase";
// output interface
+ public static final String CALL_FUNCTION_CLASS
+ = "org.apache.xalan.xsltc.runtime.CallFunction";
public static final String TRANSLET_OUTPUT_INTERFACE
= "org.apache.xml.serializer.SerializationHandler";
public static final String BASIS_LIBRARY_CLASS
@@ -299,6 +301,8 @@
public static final String TRANSLET_PNAME
= "translet";
+ public static final String INVOKE_METHOD
+ = "invokeMethod";
public static final String GET_NODE_NAME
= "getNodeNameX";
public static final String CHARACTERSW
1.38 +72 -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.37
retrieving revision 1.38
diff -u -r1.37 -r1.38
--- FunctionCall.java 23 Feb 2004 10:29:35 -0000 1.37
+++ FunctionCall.java 23 Feb 2004 17:29:35 -0000 1.38
@@ -37,6 +37,13 @@
import org.apache.bcel.generic.InvokeInstruction;
import org.apache.bcel.generic.NEW;
import org.apache.bcel.generic.PUSH;
+import org.apache.bcel.generic.LocalVariableGen;
+import org.apache.bcel.generic.ASTORE;
+import org.apache.bcel.generic.ANEWARRAY;
+import org.apache.bcel.generic.ALOAD;
+import org.apache.bcel.generic.ACONST_NULL;
+
+
import org.apache.xalan.xsltc.compiler.util.BooleanType;
import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
@@ -126,6 +133,9 @@
// If the java method is static
private boolean _isStatic = false;
+ // If unable to resolve statically then resolve dynamically
+ private boolean resolveDynamic = false;
+
// Legal conversions between internal and Java types.
private static final MultiHashtable _internal2Java = new
MultiHashtable();
@@ -484,10 +494,14 @@
}
if (_type != null) {
- return _type;
+ return _type;
}
+ else{
+ resolveDynamic = true;
+ }
- throw new TypeCheckError(ErrorMsg.ARGUMENT_CONVERSION_ERR,
getMethodSignature(argsType));
+ return _type = (_clazz != null) ? Type.newObjectType(_clazz)
+ : Type.newObjectType(_className);
}
@@ -526,6 +540,11 @@
&& _clazz != null
&&
_clazz.isAssignableFrom(((ObjectType)firstArgType).getJavaClass()))
hasThisArgument = true;
+ else if(firstArgType instanceof ReferenceType){
+ resolveDynamic = true;
+ typeCheckArgs(stable);
+ return Type.String;
+ }
if (hasThisArgument) {
_thisArgument = (Expression) _arguments.elementAt(0);
@@ -775,6 +794,56 @@
_chosenConstructor.getDeclaringClass());
}
+ else if(resolveDynamic) {
+
+ final LocalVariableGen _local =
methodGen.addLocalVariable2("objects",
+ org.apache.bcel.generic.Type.OBJECT, il.getEnd());
+
+ //Create the Object[].
+ il.append(new PUSH(cpg, n + 1));
+ il.append(new ANEWARRAY(cpg.addClass(OBJECT_CLASS)));
+
+ // Push "this" if it is an instance method
+ il.append(DUP);
+ if (_thisArgument != null) {
+ il.append(new PUSH(cpg, 0));
+ _thisArgument.translate(classGen, methodGen);
+ }
+ //else add null to the Object array
+ else {
+ il.append(new PUSH(cpg, 0));
+ il.append(ACONST_NULL);
+ }
+ il.append(AASTORE);
+
+ //Add the parameters to Object[]
+ for (int i = 0; i < n; i++) {
+ il.append(DUP);
+ il.append(new PUSH(cpg, i + 1));
+ Expression exp = argument(i);
+ exp.translate(classGen, methodGen);
+ exp.startIterator(classGen, methodGen);
+ exp.getType().translateTo(classGen, methodGen, Type.Reference);
+ il.append(AASTORE);
+ }
+ il.append(new ASTORE(_local.getIndex()));
+
+ //call invoke parameter
+ String methodName = null;
+ if (_chosenMethod != null)
+ methodName = _chosenMethod.getName();
+ else
+ methodName = _fname.getLocalPart();
+
+ il.append(new PUSH(cpg, _className));
+ il.append(new PUSH(cpg, methodName));
+ il.append(new ALOAD(_local.getIndex()));
+
+ index = cpg.addMethodref(CALL_FUNCTION_CLASS, INVOKE_METHOD,
+
"(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;");
+ il.append(new INVOKESTATIC(index));
+
+ }
// Invoke function calls that are handled in separate classes
else {
final String clazz = _chosenMethod.getDeclaringClass().getName();
1.28 +3 -2
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Param.java
Index: Param.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Param.java,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -r1.27 -r1.28
--- Param.java 16 Feb 2004 22:24:28 -0000 1.27
+++ Param.java 23 Feb 2004 17:29:35 -0000 1.28
@@ -34,6 +34,7 @@
import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
import org.apache.xalan.xsltc.compiler.util.ReferenceType;
import org.apache.xalan.xsltc.compiler.util.Type;
+import org.apache.xalan.xsltc.compiler.util.ObjectType;
import org.apache.xalan.xsltc.compiler.util.TypeCheckError;
import org.apache.xalan.xsltc.runtime.BasisLibrary;
@@ -149,7 +150,7 @@
public Type typeCheck(SymbolTable stable) throws TypeCheckError {
if (_select != null) {
_type = _select.typeCheck(stable);
- if (_type instanceof ReferenceType == false) {
+ if (_type instanceof ReferenceType == false && !(_type instanceof
ObjectType)) {
_select = new CastExpr(_select, Type.Reference);
}
}
1.19 +3 -1
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/util/ReferenceType.java
Index: ReferenceType.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/util/ReferenceType.java,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -r1.18 -r1.19
--- ReferenceType.java 16 Feb 2004 22:26:44 -0000 1.18
+++ ReferenceType.java 23 Feb 2004 17:29:35 -0000 1.19
@@ -89,6 +89,8 @@
else if (type == Type.Object) {
translateTo(classGen, methodGen, (ObjectType) type);
}
+ else if (type == Type.Reference ) {
+ }
else {
ErrorMsg err = new ErrorMsg(ErrorMsg.INTERNAL_ERR, type.toString());
classGen.getParser().reportError(Constants.FATAL, err);
1.1
xml-xalan/java/src/org/apache/xalan/xsltc/runtime/CallFunction.java
Index: CallFunction.java
===================================================================
/*
* Copyright 2001-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id:
*/
package org.apache.xalan.xsltc.runtime;
import java.util.Vector;
import java.lang.reflect.Modifier;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.IllegalAccessException;
import java.lang.IllegalArgumentException;
import java.lang.InstantiationException;
/**
* Resolve the function dynamically
*/
public final class CallFunction {
public static String className;
public static String methodName;
public static int nArgs;
public static Class clazz;
public static String invokeMethod(String _className, String _methodName,
Object [] _arguments){
className = _className;
methodName = _methodName;
int size = _arguments.length-1;
Object [] arguments = new Object[size];
Object object= _arguments[0];
clazz =null;
try {
clazz = ObjectFactory.findProviderClass(className,
ObjectFactory.findClassLoader(), true);
if (clazz == null) {
throw new RuntimeException("Couldn't load the class");
}
}catch (ClassNotFoundException e) {
throw new RuntimeException("Couldn't load the class");
}
for(int i=0,j=1;i<size;i++,++j){
arguments[i] = _arguments[j];
}
nArgs = size;
if( methodName != null ){
Method method;
if((method = findMethods(arguments)) == null){
throw new RuntimeException("Method not found");
}
try{
Object obj = method.invoke(object,arguments);
return obj.toString() ;
}
catch(IllegalAccessException e){
throw new RuntimeException("Error: Method is inaccessible");
}
catch(IllegalArgumentException e){
throw new RuntimeException("Error: Number of actual and
formal argument differ ");
}
catch(InvocationTargetException e){
throw new RuntimeException("Error: underlying constructor
throws an exception ");
}
}
else {
Constructor constructor;
if((constructor = findConstructor(arguments)) == null){
throw new RuntimeException("Constructor not found");
}
try{
Object obs = constructor.newInstance(arguments);
return obs.toString() ;
}catch(InvocationTargetException e){
throw new RuntimeException("Error: constructor throws an
exception ");
}
catch(IllegalAccessException e){
throw new RuntimeException("Error: constructor is
inaccessible");
}
catch(IllegalArgumentException e){
throw new RuntimeException("Error: Number of actual and
formal argument differ ");
}
catch(InstantiationException e){
throw new RuntimeException("Error: Class that declares the
underlying constructor represents an abstract class");
}
}
}
/**
* Returns a Constructor
*/
private static Constructor findConstructor(Object[] arguments) {
Vector constructors =null;
final Constructor[] c_constructors = clazz.getConstructors();
for (int i = 0; i < c_constructors.length; i++) {
final int mods = c_constructors[i].getModifiers();
// Is it public, static and same number of args ?
if (Modifier.isPublic(mods) &&
c_constructors[i].getParameterTypes().length == nArgs){
if (constructors == null) {
constructors = new Vector();
}
constructors.addElement(c_constructors[i]);
}
}
if (constructors == null) {
// Method not found in this class
throw new RuntimeException("CONSTRUCTOR_NOT_FOUND_ERR" + className
+":"+ methodName);
}
int nConstructors = constructors.size();
boolean accept=false;
for (int j, i = 0; i < nConstructors; i++) {
// Check if all parameters to this constructor can be converted
final Constructor constructor =
(Constructor)constructors.elementAt(i);
final Class[] paramTypes = constructor.getParameterTypes();
for (j = 0; j < nArgs; j++) {
Class argumentClass = arguments[j].getClass();
if (argumentClass == paramTypes[j]){
accept= true;
}
else if(argumentClass.isAssignableFrom(paramTypes[j])){
accept=true;
}
else {
accept =false;
break;
}
}
if (accept)
return constructor;
}
return null;
}
/**
* Return the Method
*/
private static Method findMethods(Object[] arguments) {
Vector methods = null;
final Method[] m_methods = clazz.getMethods();
for (int i = 0; i < m_methods.length; i++){
final int mods = m_methods[i].getModifiers();
// Is it public and same number of args ?
if( Modifier.isPublic(mods)
&& m_methods[i].getName().equals(methodName)
&& m_methods[i].getParameterTypes().length == nArgs){
if (methods == null){
methods = new Vector();
}
methods.addElement(m_methods[i]);
}
}
if (methods == null) {
// Method not found in this class
throw new RuntimeException("METHOD_NOT_FOUND_ERR" + className +":"+
methodName);
}
int nMethods = methods.size();
boolean accept=false;
for (int j, i = 0; i < nMethods; i++) {
// Check if all parameters to this constructor can be converted
final Method method = (Method)methods.elementAt(i);
final Class[] paramTypes = method.getParameterTypes();
for (j = 0; j < nArgs; j++) {
Class argumentClass = arguments[j].getClass();
if (argumentClass == paramTypes[j]){
accept= true;
}
else if(argumentClass.isAssignableFrom(paramTypes[j])){
accept=true;
}
else if(paramTypes[j].isPrimitive() ){
arguments[j] = isPrimitive(paramTypes[j],arguments[j]);
accept = true;
}
else {
accept =false;
break;
}
}
if (accept)
return method;
}
return null;
}
public static Object isPrimitive(Class paramType, Object argument){
if( argument.getClass() == Integer.class )
return typeCast(paramType,(Integer)argument);
else if( argument.getClass() == Float.class )
return typeCast(paramType,(Float)argument);
else if( argument.getClass() == Double.class )
return typeCast(paramType,(Double)argument);
else if( argument.getClass() == Long.class )
return typeCast(paramType,(Long)argument);
else if( argument.getClass() == Boolean.class )
return (Boolean)argument;
else if( argument.getClass() == Byte.class )
return (Byte)argument;
else
return null;
}
static Object typeCast(Class paramType, Double object){
if (paramType == Long.TYPE)
return new Long(object.longValue());
else if (paramType == Integer.TYPE)
return new Integer(object.intValue());
else if (paramType == Float.TYPE)
return new Float(object.floatValue());
else if (paramType == Short.TYPE)
return new Short(object.shortValue());
else if (paramType == Byte.TYPE)
return new Byte(object.byteValue());
else
return object;
}
static Object typeCast(Class paramType, Long object){
if (paramType == Integer.TYPE)
return new Integer(object.intValue());
else if (paramType == Float.TYPE)
return new Float(object.floatValue());
else if (paramType == Short.TYPE)
return new Short(object.shortValue());
else if (paramType == Byte.TYPE)
return new Byte(object.byteValue());
else
return object;
}
static Object typeCast(Class paramType, Integer object){
if(paramType == Double.TYPE)
return new Double(object.doubleValue());
else if (paramType == Float.TYPE)
return new Float(object.floatValue());
else if (paramType == Short.TYPE)
return new Short(object.shortValue());
else if (paramType == Byte.TYPE)
return new Byte(object.byteValue());
else
return object;
}
static Object typeCast(Class paramType, Float object){
if(paramType == Double.TYPE)
return new Double(object.doubleValue());
else if (paramType == Integer.TYPE)
return new Float(object.intValue());
else if (paramType == Short.TYPE)
return new Short(object.shortValue());
else if (paramType == Byte.TYPE)
return new Byte(object.byteValue());
else
return object;
}
}
1.1
xml-xalan/java/src/org/apache/xalan/xsltc/runtime/ObjectFactory.java
Index: ObjectFactory.java
===================================================================
/*
* Copyright 2001-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: ObjectFactory.java,v 1.1 2004/02/23 17:29:35 aruny Exp $
*/
package org.apache.xalan.xsltc.runtime;
import java.io.InputStream;
import java.io.IOException;
import java.io.File;
import java.io.FileInputStream;
import java.util.Properties;
import java.io.BufferedReader;
import java.io.InputStreamReader;
/**
* This class is duplicated for each JAXP subpackage so keep it in sync.
* It is package private and therefore is not exposed as part of the JAXP
* API.
* <p>
* This code is designed to implement the JAXP 1.1 spec pluggability
* feature and is designed to run on JDK version 1.1 and
* later, and to compile on JDK 1.2 and onward.
* The code also runs both as part of an unbundled jar file and
* when bundled as part of the JDK.
* <p>
* This class was moved from the <code>javax.xml.parsers.ObjectFactory</code>
* class and modified to be used as a general utility for creating objects
* dynamically.
*
* @version $Id: ObjectFactory.java,v 1.1 2004/02/23 17:29:35 aruny Exp $
*/
class ObjectFactory {
//
// Constants
//
// name of default properties file to look for in JDK's jre/lib directory
private static final String DEFAULT_PROPERTIES_FILENAME =
"xalan.properties";
private static final String SERVICES_PATH = "META-INF/services/";
/** Set to true for debugging */
private static final boolean DEBUG = false;
/** cache the contents of the xalan.properties file.
* Until an attempt has been made to read this file, this will
* be null; if the file does not exist or we encounter some other error
* during the read, this will be empty.
*/
private static Properties fXalanProperties = null;
/***
* Cache the time stamp of the xalan.properties file so
* that we know if it's been modified and can invalidate
* the cache when necessary.
*/
private static long fLastModified = -1;
//
// Public static methods
//
/**
* Finds the implementation Class object in the specified order. The
* specified order is the following:
* <ol>
* <li>query the system property using <code>System.getProperty</code>
* <li>read <code>META-INF/services/<i>factoryId</i></code> file
* <li>use fallback classname
* </ol>
*
* @return instance of factory, never null
*
* @param factoryId Name of the factory to find, same as
* a property name
* @param fallbackClassName Implementation class name, if nothing else
* is found. Use null to mean no fallback.
*
* @exception ObjectFactory.ConfigurationError
*/
static Object createObject(String factoryId, String fallbackClassName)
throws ConfigurationError {
return createObject(factoryId, null, fallbackClassName);
} // createObject(String,String):Object
/**
* Finds the implementation Class object in the specified order. The
* specified order is the following:
* <ol>
* <li>query the system property using <code>System.getProperty</code>
* <li>read <code>$java.home/lib/<i>propertiesFilename</i></code> file
* <li>read <code>META-INF/services/<i>factoryId</i></code> file
* <li>use fallback classname
* </ol>
*
* @return instance of factory, never null
*
* @param factoryId Name of the factory to find, same as
* a property name
* @param propertiesFilename The filename in the $java.home/lib directory
* of the properties file. If none specified,
* ${java.home}/lib/xalan.properties will be
used.
* @param fallbackClassName Implementation class name, if nothing else
* is found. Use null to mean no fallback.
*
* @exception ObjectFactory.ConfigurationError
*/
static Object createObject(String factoryId,
String propertiesFilename,
String fallbackClassName)
throws ConfigurationError
{
Class factoryClass = lookUpFactoryClass(factoryId,
propertiesFilename,
fallbackClassName);
if (factoryClass == null) {
throw new ConfigurationError(
"Provider for " + factoryId + " cannot be found", null);
}
try{
Object instance = factoryClass.newInstance();
debugPrintln("created new instance of factory " + factoryId);
return instance;
} catch (Exception x) {
throw new ConfigurationError(
"Provider for factory " + factoryId
+ " could not be instantiated: " + x, x);
}
} // createObject(String,String,String):Object
/**
* Finds the implementation Class object in the specified order. The
* specified order is the following:
* <ol>
* <li>query the system property using <code>System.getProperty</code>
* <li>read <code>$java.home/lib/<i>propertiesFilename</i></code> file
* <li>read <code>META-INF/services/<i>factoryId</i></code> file
* <li>use fallback classname
* </ol>
*
* @return Class object of factory, never null
*
* @param factoryId Name of the factory to find, same as
* a property name
* @param propertiesFilename The filename in the $java.home/lib directory
* of the properties file. If none specified,
* ${java.home}/lib/xalan.properties will be
used.
* @param fallbackClassName Implementation class name, if nothing else
* is found. Use null to mean no fallback.
*
* @exception ObjectFactory.ConfigurationError
*/
static Class lookUpFactoryClass(String factoryId)
throws ConfigurationError
{
return lookUpFactoryClass(factoryId, null, null);
} // lookUpFactoryClass(String):Class
/**
* Finds the implementation Class object in the specified order. The
* specified order is the following:
* <ol>
* <li>query the system property using <code>System.getProperty</code>
* <li>read <code>$java.home/lib/<i>propertiesFilename</i></code> file
* <li>read <code>META-INF/services/<i>factoryId</i></code> file
* <li>use fallback classname
* </ol>
*
* @return Class object that provides factory service, never null
*
* @param factoryId Name of the factory to find, same as
* a property name
* @param propertiesFilename The filename in the $java.home/lib directory
* of the properties file. If none specified,
* ${java.home}/lib/xalan.properties will be
used.
* @param fallbackClassName Implementation class name, if nothing else
* is found. Use null to mean no fallback.
*
* @exception ObjectFactory.ConfigurationError
*/
static Class lookUpFactoryClass(String factoryId,
String propertiesFilename,
String fallbackClassName)
throws ConfigurationError
{
String factoryClassName = lookUpFactoryClassName(factoryId,
propertiesFilename,
fallbackClassName);
ClassLoader cl = findClassLoader();
if (factoryClassName == null) {
factoryClassName = fallbackClassName;
}
// assert(className != null);
try{
Class providerClass = findProviderClass(factoryClassName,
cl,
true);
debugPrintln("created new instance of " + providerClass +
" using ClassLoader: " + cl);
return providerClass;
} catch (ClassNotFoundException x) {
throw new ConfigurationError(
"Provider " + factoryClassName + " not found", x);
} catch (Exception x) {
throw new ConfigurationError(
"Provider "+factoryClassName+" could not be instantiated: "+x,
x);
}
} // lookUpFactoryClass(String,String,String):Class
/**
* Finds the name of the required implementation class in the specified
* order. The specified order is the following:
* <ol>
* <li>query the system property using <code>System.getProperty</code>
* <li>read <code>$java.home/lib/<i>propertiesFilename</i></code> file
* <li>read <code>META-INF/services/<i>factoryId</i></code> file
* <li>use fallback classname
* </ol>
*
* @return name of class that provides factory service, never null
*
* @param factoryId Name of the factory to find, same as
* a property name
* @param propertiesFilename The filename in the $java.home/lib directory
* of the properties file. If none specified,
* ${java.home}/lib/xalan.properties will be
used.
* @param fallbackClassName Implementation class name, if nothing else
* is found. Use null to mean no fallback.
*
* @exception ObjectFactory.ConfigurationError
*/
static String lookUpFactoryClassName(String factoryId,
String propertiesFilename,
String fallbackClassName)
{
SecuritySupport ss = SecuritySupport.getInstance();
// Use the system property first
try {
String systemProp = ss.getSystemProperty(factoryId);
if (systemProp != null) {
debugPrintln("found system property, value=" + systemProp);
return systemProp;
}
} catch (SecurityException se) {
// Ignore and continue w/ next location
}
// Try to read from propertiesFilename, or
// $java.home/lib/xalan.properties
String factoryClassName = null;
// no properties file name specified; use
// $JAVA_HOME/lib/xalan.properties:
if (propertiesFilename == null) {
File propertiesFile = null;
boolean propertiesFileExists = false;
try {
String javah = ss.getSystemProperty("java.home");
propertiesFilename = javah + File.separator +
"lib" + File.separator + DEFAULT_PROPERTIES_FILENAME;
propertiesFile = new File(propertiesFilename);
propertiesFileExists = ss.getFileExists(propertiesFile);
} catch (SecurityException e) {
// try again...
fLastModified = -1;
fXalanProperties = null;
}
synchronized (ObjectFactory.class) {
boolean loadProperties = false;
try {
// file existed last time
if(fLastModified >= 0) {
if(propertiesFileExists &&
(fLastModified < (fLastModified =
ss.getLastModified(propertiesFile)))) {
loadProperties = true;
} else {
// file has stopped existing...
if(!propertiesFileExists) {
fLastModified = -1;
fXalanProperties = null;
} // else, file wasn't modified!
}
} else {
// file has started to exist:
if(propertiesFileExists) {
loadProperties = true;
fLastModified =
ss.getLastModified(propertiesFile);
} // else, nothing's changed
}
if(loadProperties) {
// must never have attempted to read xalan.properties
// before (or it's outdeated)
fXalanProperties = new Properties();
FileInputStream fis =
ss.getFileInputStream(propertiesFile);
fXalanProperties.load(fis);
fis.close();
}
} catch (Exception x) {
fXalanProperties = null;
fLastModified = -1;
// assert(x instanceof FileNotFoundException
// || x instanceof SecurityException)
// In both cases, ignore and continue w/ next location
}
}
if(fXalanProperties != null) {
factoryClassName = fXalanProperties.getProperty(factoryId);
}
} else {
try {
FileInputStream fis =
ss.getFileInputStream(new
File(propertiesFilename));
Properties props = new Properties();
props.load(fis);
fis.close();
factoryClassName = props.getProperty(factoryId);
} catch (Exception x) {
// assert(x instanceof FileNotFoundException
// || x instanceof SecurityException)
// In both cases, ignore and continue w/ next location
}
}
if (factoryClassName != null) {
debugPrintln("found in " + propertiesFilename + ", value="
+ factoryClassName);
return factoryClassName;
}
// Try Jar Service Provider Mechanism
return findJarServiceProviderName(factoryId);
} // lookUpFactoryClass(String,String):String
//
// Private static methods
//
/** Prints a message to standard error if debugging is enabled. */
private static void debugPrintln(String msg) {
if (DEBUG) {
System.err.println("JAXP: " + msg);
}
} // debugPrintln(String)
/**
* Figure out which ClassLoader to use. For JDK 1.2 and later use
* the context ClassLoader.
*/
static ClassLoader findClassLoader()
throws ConfigurationError
{
SecuritySupport ss = SecuritySupport.getInstance();
// Figure out which ClassLoader to use for loading the provider
// class. If there is a Context ClassLoader then use it.
ClassLoader context = ss.getContextClassLoader();
ClassLoader system = ss.getSystemClassLoader();
ClassLoader chain = system;
while (true) {
if (context == chain) {
// Assert: we are on JDK 1.1 or we have no Context ClassLoader
// or any Context ClassLoader in chain of system classloader
// (including extension ClassLoader) so extend to widest
// ClassLoader (always look in system ClassLoader if Xalan
// is in boot/extension/system classpath and in current
// ClassLoader otherwise); normal classloaders delegate
// back to system ClassLoader first so this widening doesn't
// change the fact that context ClassLoader will be consulted
ClassLoader current = ObjectFactory.class.getClassLoader();
chain = system;
while (true) {
if (current == chain) {
// Assert: Current ClassLoader in chain of
// boot/extension/system ClassLoaders
return system;
}
if (chain == null) {
break;
}
chain = ss.getParentClassLoader(chain);
}
// Assert: Current ClassLoader not in chain of
// boot/extension/system ClassLoaders
return current;
}
if (chain == null) {
// boot ClassLoader reached
break;
}
// Check for any extension ClassLoaders in chain up to
// boot ClassLoader
chain = ss.getParentClassLoader(chain);
};
// Assert: Context ClassLoader not in chain of
// boot/extension/system ClassLoaders
return context;
} // findClassLoader():ClassLoader
/**
* Create an instance of a class using the specified ClassLoader
*/
static Object newInstance(String className, ClassLoader cl,
boolean doFallback)
throws ConfigurationError
{
// assert(className != null);
try{
Class providerClass = findProviderClass(className, cl,
doFallback);
Object instance = providerClass.newInstance();
debugPrintln("created new instance of " + providerClass +
" using ClassLoader: " + cl);
return instance;
} catch (ClassNotFoundException x) {
throw new ConfigurationError(
"Provider " + className + " not found", x);
} catch (Exception x) {
throw new ConfigurationError(
"Provider " + className + " could not be instantiated: " + x,
x);
}
}
/**
* Find a Class using the specified ClassLoader
*/
static Class findProviderClass(String className, ClassLoader cl,
boolean doFallback)
throws ClassNotFoundException, ConfigurationError
{
//throw security exception if the calling thread is not allowed to
access the
//class. Restrict the access to the package classes as specified in
java.security policy.
SecurityManager security = System.getSecurityManager();
try{
if (security != null){
security.checkPackageAccess(className);
}
}catch(SecurityException e){
throw e;
}
Class providerClass;
if (cl == null) {
// XXX Use the bootstrap ClassLoader. There is no way to
// load a class using the bootstrap ClassLoader that works
// in both JDK 1.1 and Java 2. However, this should still
// work b/c the following should be true:
//
// (cl == null) iff current ClassLoader == null
//
// Thus Class.forName(String) will use the current
// ClassLoader which will be the bootstrap ClassLoader.
providerClass = Class.forName(className);
} else {
try {
providerClass = cl.loadClass(className);
} catch (ClassNotFoundException x) {
if (doFallback) {
// Fall back to current classloader
ClassLoader current =
ObjectFactory.class.getClassLoader();
if (current == null) {
providerClass = Class.forName(className);
} else if (cl != current) {
cl = current;
providerClass = cl.loadClass(className);
} else {
throw x;
}
} else {
throw x;
}
}
}
return providerClass;
}
/**
* Find the name of service provider using Jar Service Provider Mechanism
*
* @return instance of provider class if found or null
*/
private static String findJarServiceProviderName(String factoryId)
{
SecuritySupport ss = SecuritySupport.getInstance();
String serviceId = SERVICES_PATH + factoryId;
InputStream is = null;
// First try the Context ClassLoader
ClassLoader cl = findClassLoader();
is = ss.getResourceAsStream(cl, serviceId);
// If no provider found then try the current ClassLoader
if (is == null) {
ClassLoader current = ObjectFactory.class.getClassLoader();
if (cl != current) {
cl = current;
is = ss.getResourceAsStream(cl, serviceId);
}
}
if (is == null) {
// No provider found
return null;
}
debugPrintln("found jar resource=" + serviceId +
" using ClassLoader: " + cl);
// Read the service provider name in UTF-8 as specified in
// the jar spec. Unfortunately this fails in Microsoft
// VJ++, which does not implement the UTF-8
// encoding. Theoretically, we should simply let it fail in
// that case, since the JVM is obviously broken if it
// doesn't support such a basic standard. But since there
// are still some users attempting to use VJ++ for
// development, we have dropped in a fallback which makes a
// second attempt using the platform's default encoding. In
// VJ++ this is apparently ASCII, which is a subset of
// UTF-8... and since the strings we'll be reading here are
// also primarily limited to the 7-bit ASCII range (at
// least, in English versions), this should work well
// enough to keep us on the air until we're ready to
// officially decommit from VJ++. [Edited comment from
// jkesselm]
BufferedReader rd;
try {
rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
} catch (java.io.UnsupportedEncodingException e) {
rd = new BufferedReader(new InputStreamReader(is));
}
String factoryClassName = null;
try {
// XXX Does not handle all possible input as specified by the
// Jar Service Provider specification
factoryClassName = rd.readLine();
rd.close();
} catch (IOException x) {
// No provider found
return null;
}
if (factoryClassName != null &&
! "".equals(factoryClassName)) {
debugPrintln("found in resource, value="
+ factoryClassName);
// Note: here we do not want to fall back to the current
// ClassLoader because we want to avoid the case where the
// resource file was found using one ClassLoader and the
// provider class was instantiated using a different one.
return factoryClassName;
}
// No provider found
return null;
}
//
// Classes
//
/**
* A configuration error.
*/
static class ConfigurationError
extends Error {
//
// Data
//
/** Exception. */
private Exception exception;
//
// Constructors
//
/**
* Construct a new instance with the specified detail string and
* exception.
*/
ConfigurationError(String msg, Exception x) {
super(msg);
this.exception = x;
} // <init>(String,Exception)
//
// Public methods
//
/** Returns the exception associated to this error. */
Exception getException() {
return exception;
} // getException():Exception
} // class ConfigurationError
} // class ObjectFactory
1.1
xml-xalan/java/src/org/apache/xalan/xsltc/runtime/SecuritySupport.java
Index: SecuritySupport.java
===================================================================
/*
* Copyright 2002-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: SecuritySupport.java,v 1.1 2004/02/23 17:29:35 aruny Exp $
*/
package org.apache.xalan.xsltc.runtime;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Properties;
/**
* This class is duplicated for each Xalan-Java subpackage so keep it in sync.
* It is package private and therefore is not exposed as part of the
Xalan-Java
* API.
*
* Base class with security related methods that work on JDK 1.1.
*/
class SecuritySupport {
/*
* Make this of type Object so that the verifier won't try to
* prove its type, thus possibly trying to load the SecuritySupport12
* class.
*/
private static final Object securitySupport;
static {
SecuritySupport ss = null;
try {
Class c = Class.forName("java.security.AccessController");
// if that worked, we're on 1.2.
/*
// don't reference the class explicitly so it doesn't
// get dragged in accidentally.
c = Class.forName("javax.mail.SecuritySupport12");
Constructor cons = c.getConstructor(new Class[] { });
ss = (SecuritySupport)cons.newInstance(new Object[] { });
*/
/*
* Unfortunately, we can't load the class using reflection
* because the class is package private. And the class has
* to be package private so the APIs aren't exposed to other
* code that could use them to circumvent security. Thus,
* we accept the risk that the direct reference might fail
* on some JDK 1.1 JVMs, even though we would never execute
* this code in such a case. Sigh...
*/
ss = new SecuritySupport12();
} catch (Exception ex) {
// ignore it
} finally {
if (ss == null)
ss = new SecuritySupport();
securitySupport = ss;
}
}
/**
* Return an appropriate instance of this class, depending on whether
* we're on a JDK 1.1 or J2SE 1.2 (or later) system.
*/
static SecuritySupport getInstance() {
return (SecuritySupport)securitySupport;
}
ClassLoader getContextClassLoader() {
return null;
}
ClassLoader getSystemClassLoader() {
return null;
}
ClassLoader getParentClassLoader(ClassLoader cl) {
return null;
}
String getSystemProperty(String propName) {
return System.getProperty(propName);
}
FileInputStream getFileInputStream(File file)
throws FileNotFoundException
{
return new FileInputStream(file);
}
InputStream getResourceAsStream(ClassLoader cl, String name) {
InputStream ris;
if (cl == null) {
ris = ClassLoader.getSystemResourceAsStream(name);
} else {
ris = cl.getResourceAsStream(name);
}
return ris;
}
boolean getFileExists(File f) {
return f.exists();
}
long getLastModified(File f) {
return f.lastModified();
}
}
1.1
xml-xalan/java/src/org/apache/xalan/xsltc/runtime/SecuritySupport12.java
Index: SecuritySupport12.java
===================================================================
/*
* Copyright 2002-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: SecuritySupport12.java,v 1.1 2004/02/23 17:29:35 aruny Exp $
*/
package org.apache.xalan.xsltc.runtime;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Properties;
/**
* This class is duplicated for each Xalan-Java subpackage so keep it in sync.
* It is package private and therefore is not exposed as part of the
Xalan-Java
* API.
*
* Security related methods that only work on J2SE 1.2 and newer.
*/
class SecuritySupport12 extends SecuritySupport {
ClassLoader getContextClassLoader() {
return (ClassLoader)
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
ClassLoader cl = null;
try {
cl = Thread.currentThread().getContextClassLoader();
} catch (SecurityException ex) { }
return cl;
}
});
}
ClassLoader getSystemClassLoader() {
return (ClassLoader)
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
ClassLoader cl = null;
try {
cl = ClassLoader.getSystemClassLoader();
} catch (SecurityException ex) {}
return cl;
}
});
}
ClassLoader getParentClassLoader(final ClassLoader cl) {
return (ClassLoader)
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
ClassLoader parent = null;
try {
parent = cl.getParent();
} catch (SecurityException ex) {}
// eliminate loops in case of the boot
// ClassLoader returning itself as a parent
return (parent == cl) ? null : parent;
}
});
}
String getSystemProperty(final String propName) {
return (String)
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return System.getProperty(propName);
}
});
}
FileInputStream getFileInputStream(final File file)
throws FileNotFoundException
{
try {
return (FileInputStream)
AccessController.doPrivileged(new PrivilegedExceptionAction()
{
public Object run() throws FileNotFoundException {
return new FileInputStream(file);
}
});
} catch (PrivilegedActionException e) {
throw (FileNotFoundException)e.getException();
}
}
InputStream getResourceAsStream(final ClassLoader cl,
final String name)
{
return (InputStream)
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
InputStream ris;
if (cl == null) {
ris = ClassLoader.getSystemResourceAsStream(name);
} else {
ris = cl.getResourceAsStream(name);
}
return ris;
}
});
}
boolean getFileExists(final File f) {
return ((Boolean)
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return new Boolean(f.exists());
}
})).booleanValue();
}
long getLastModified(final File f) {
return ((Long)
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return new Long(f.lastModified());
}
})).longValue();
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]