/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.config;
import gw.lang.reflect.ITypeLoader;
import gw.lang.reflect.TypeSystem;
import gw.lang.reflect.IType;
import gw.lang.reflect.IConstructorInfo;
import gw.lang.reflect.java.JavaTypes;
import gw.lang.reflect.module.IExecutionEnvironment;
import gw.util.ILogger;
import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.lang.reflect.Constructor;
import org.w3c.dom.Node;
import org.w3c.dom.NamedNodeMap;
public class TypeLoaderSpec
{
String _typeloaderClassName = null;
HashMap _additionalArgs = new HashMap();
public TypeLoaderSpec(Node xmlNode, URL registryUrl)
{
NamedNodeMap map = xmlNode.getAttributes();
int length = map.getLength() - 1;
while( length >= 0 )
{
Node node = map.item( length );
if( node.getNodeName().equals( Registry.TAG_CLASS ) )
{
_typeloaderClassName = node.getNodeValue();
} else if (node.getNodeName().equals(Registry.TAG_SRC))
{
try {
File file = new File(registryUrl.toURI()).getParentFile();
file = new File(file, node.getNodeValue()).getCanonicalFile();
_additionalArgs.put( node.getNodeName(), file.getAbsolutePath() );
} catch (Exception e) {
throw new RuntimeException(e);
}
} else
{
_additionalArgs.put( node.getNodeName(), node.getNodeValue() );
}
length--;
}
}
public String getTypeloaderClassName()
{
return _typeloaderClassName;
}
public HashMap getAdditionalArgs()
{
return _additionalArgs;
}
public ITypeLoader createTypeLoader( IExecutionEnvironment execEnv )
{
return createTypeLoader( execEnv, _typeloaderClassName, _additionalArgs );
}
public static ITypeLoader createTypeLoader( IExecutionEnvironment execEnv, String typeloaderClassName, HashMap additionalArgs )
{
ILogger logger = CommonServices.getEntityAccess().getLogger();
ITypeLoader additionalTypeLoader = null;
boolean gosu = false;
try
{
Class clazz = execEnv.getClass().getClassLoader().loadClass( typeloaderClassName );
Constructor constructor = getConstructor( clazz, IExecutionEnvironment.class, Map.class );
if( constructor != null )
{
additionalTypeLoader = (ITypeLoader)constructor.newInstance( execEnv, additionalArgs );
}
else
{
constructor = getConstructor( clazz, IExecutionEnvironment.class );
if( constructor != null )
{
additionalTypeLoader = (ITypeLoader)constructor.newInstance( execEnv );
}
else
{
constructor = getConstructor( clazz );
if( constructor != null )
{
additionalTypeLoader = (ITypeLoader)constructor.newInstance();
}
else
{
logger.error( "The type loader " + typeloaderClassName + " does not have a callable constructor. It must provide\n" +
"a constructor that takes either (IExecutionEnvironment, Map), (IExecutionEnvironment) or no paramters" );
}
}
}
}
catch( Exception e )
{
try {
IType type = TypeSystem.getByFullName(typeloaderClassName);
gosu = true;
IConstructorInfo constructor = getConstructor( type, JavaTypes.IEXECUTION_ENVIRONMENT(), JavaTypes.MAP());
if( constructor != null )
{
additionalTypeLoader = (ITypeLoader)constructor.getConstructor().newInstance( execEnv, additionalArgs );
}
else
{
constructor = getConstructor( type, JavaTypes.IEXECUTION_ENVIRONMENT() );
if( constructor != null )
{
additionalTypeLoader = (ITypeLoader)constructor.getConstructor().newInstance( execEnv );
}
else
{
constructor = getConstructor( type );
if( constructor != null )
{
additionalTypeLoader = (ITypeLoader)constructor.getConstructor().newInstance();
}
else
{
logger.error( "The type loader " + typeloaderClassName + " does not have a callable constructor. It must provide\n" +
"a constructor that takes either (IExecutionEnvironment, Map), (IExecutionEnvironment) or no paramters" );
}
}
}
} catch (Exception e2) {
logger.error( "Unable to load type loader " + typeloaderClassName, gosu ? e2 : e );
return null;
}
}
return additionalTypeLoader;
}
private static Constructor getConstructor( Class clazz, Class... argTypes )
{
try
{
return clazz.getConstructor( argTypes );
}
catch( NoSuchMethodException e )
{
return null;
}
}
private static IConstructorInfo getConstructor(IType type, IType... argTypes) {
return type.getTypeInfo().getConstructor(argTypes);
}
}