/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.gosu.module; import gw.config.CommonServices; import gw.config.Registry; import gw.config.TypeLoaderSpec; import gw.fs.IDirectory; import gw.internal.gosu.parser.FileSystemGosuClassRepository; import gw.internal.gosu.parser.ModuleTypeLoader; import gw.lang.reflect.ITypeLoader; import gw.lang.reflect.TypeSystem; import gw.lang.reflect.gs.GosuClassTypeLoader; import gw.lang.reflect.gs.IFileSystemGosuClassRepository; import gw.lang.reflect.gs.IGosuClassRepository; import gw.lang.reflect.module.Dependency; import gw.lang.reflect.module.IExecutionEnvironment; import gw.lang.reflect.module.IGlobalModule; import gw.lang.reflect.module.IModule; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class GlobalModule extends Module implements IGlobalModule { public GlobalModule(IExecutionEnvironment execEnv, String moduleName) { super( execEnv, moduleName); } @Override protected void createExtensionTypeLoaders() { // do nothing } @Override protected void createStandardTypeLoaders() { FileSystemGosuClassRepository repository = new FileSystemGosuClassRepository(this); CommonServices.getTypeSystem().pushTypeLoader(this, new GosuClassTypeLoader(this, repository)); createGlobalTypeloaders(); } public void createGlobalTypeloaders() { ModuleTypeLoader _moduleTypeLoader = getModuleTypeLoader(); List<Class<? extends ITypeLoader>> globalLoaderTypes = CommonServices.getGlobalLoaderProvider().getGlobalLoaderTypes(); if( globalLoaderTypes != null ) { Collections.reverse(globalLoaderTypes); } IFileSystemGosuClassRepository classRepository = new FileSystemGosuClassRepository(this); classRepository.setSourcePath(getAllSourcePaths()); TypeSystem.pushModule(this); try { if( globalLoaderTypes != null ) { for (Class<? extends ITypeLoader> globalLoader : globalLoaderTypes) { try { ITypeLoader typeLoader = createTypeLoader(classRepository, this, globalLoader); if (typeLoader != null) { _moduleTypeLoader.pushTypeLoader(typeLoader); } else { throw new NullPointerException(); } } catch (Throwable t) { throw new RuntimeException("Cannot create type loader: " + globalLoader, t); } } } //TODO - remove this if/when we no longer support typeloaders in the registry.xml file List<TypeLoaderSpec> typeLoaderList = Registry.instance().getAdditionalTypeLoaders(); for (TypeLoaderSpec typeLoaderSpec : typeLoaderList) { ITypeLoader typeLoader = typeLoaderSpec.createTypeLoader(this.getExecutionEnvironment()); if (typeLoader != null) { _moduleTypeLoader.pushTypeLoader(typeLoader); } } // initialize loaders List<ITypeLoader> loaders = _moduleTypeLoader.getTypeLoaders(); for (int i = loaders.size() - 1; i >= 0; i--) { loaders.get(i).init(); } CommonServices.getGosuInitializationHooks().afterTypeLoaderCreation(); } finally { TypeSystem.popModule(this); } } private IDirectory[] getAllSourcePaths() { List<IDirectory> srcs = new ArrayList<IDirectory>(); for (IModule m : getModuleTraversalList()) { srcs.addAll(m.getSourcePath()); } return srcs.toArray(new IDirectory[srcs.size()]); } /** * In global module, all dependencies should be traversed, even non-exported. */ @Override protected void traverse(final IModule theModule, List<IModule> traversalList) { traversalList.add(theModule); for (Dependency dependency : theModule.getDependencies()) { IModule dependencyModule = dependency.getModule(); if (!traversalList.contains(dependencyModule)) { traverse(dependencyModule, traversalList); } } } protected static ITypeLoader createTypeLoader( IFileSystemGosuClassRepository classRepository, IModule module, Class loaderClass) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException { try { ITypeLoader typeLoader; CommonServices.getGosuInitializationHooks().beforeTypeLoaderCreation(loaderClass); Constructor[] constructors = loaderClass.getConstructors(); typeLoader = null; for (Constructor cons : constructors) { Class[] parameterTypes = cons.getParameterTypes(); if (parameterTypes.length == 0) { typeLoader = (ITypeLoader) cons.newInstance(); } else if (parameterTypes.length == 1 && parameterTypes[0] == gw.lang.reflect.module.IModule.class) { typeLoader = (ITypeLoader) cons.newInstance(module); } else if (cons.getParameterTypes().length == 1 && cons.getParameterTypes()[0] == IGosuClassRepository.class) { typeLoader = (ITypeLoader) cons.newInstance(classRepository); } else { // Ignore it } } return typeLoader; } catch (LinkageError le) { throw le; } } }