All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.cristalise.kernel.process.module.ModuleManager Maven / Gradle / Ivy

/**
 * This file is part of the CRISTAL-iSE kernel.
 * Copyright (c) 2001-2015 The CRISTAL Consortium. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation; either version 3 of the License, or (at
 * your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 *
 * http://www.fsf.org/licensing/licenses/lgpl.html
 */
package org.cristalise.kernel.process.module;

import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Properties;

import org.cristalise.kernel.common.InvalidDataException;
import org.cristalise.kernel.common.ObjectNotFoundException;
import org.cristalise.kernel.entity.proxy.AgentProxy;
import org.cristalise.kernel.entity.proxy.ItemProxy;
import org.cristalise.kernel.lookup.DomainPath;
import org.cristalise.kernel.persistency.outcome.OutcomeValidator;
import org.cristalise.kernel.persistency.outcome.Schema;
import org.cristalise.kernel.process.Bootstrap;
import org.cristalise.kernel.process.Gateway;
import org.cristalise.kernel.scripting.ScriptingEngineException;
import org.cristalise.kernel.utils.FileStringUtility;
import org.cristalise.kernel.utils.LocalObjectLoader;
import org.cristalise.kernel.utils.Logger;


public class ModuleManager {
	ArrayList modules = new ArrayList();
	HashMap modulesXML = new HashMap();
	Properties props = new Properties();
	AgentProxy user;
	boolean isServer;
	OutcomeValidator moduleValidator;

	public ModuleManager(Enumeration moduleEnum, boolean isServer) throws ModuleException {
		this.isServer = isServer;
		try {
			Schema moduleSchema = LocalObjectLoader.getSchema("Module", 0);//new Schema("Module", 0, null,
					//FileStringUtility.url2String(Gateway.getResource().getKernelResourceURL("boot/OD/Module.xsd")));
			moduleValidator = new OutcomeValidator(moduleSchema);
		} catch (InvalidDataException ex) {
			Logger.error(ex);
			throw new ModuleException("Module Schema is not valid");
		} catch (ObjectNotFoundException ex) {
			throw new ModuleException("Could not load Module Schema from kernel resources");
		}
		ArrayList loadedModules = new ArrayList();
		ArrayList moduleNs = new ArrayList();
		while(moduleEnum.hasMoreElements()) {
			URL newModuleURL = moduleEnum.nextElement();
			try {
				String moduleXML = FileStringUtility.url2String(newModuleURL);
				String errors = moduleValidator.validate(moduleXML);
				if (errors.length() > 0)
					throw new ModuleException("Module XML found at "+newModuleURL+" was not valid: "+errors);
				Module newModule = (Module)Gateway.getMarshaller().unmarshall(moduleXML);
				if (newModule.getResURL() != null && newModule.getResURL().length()>0) Gateway.getResource().addModuleBaseURL(newModule.getNamespace(), newModule.getResURL());
				modules.add(newModule);
				modulesXML.put(newModule.getNamespace(), moduleXML);
				// check for clash
				if (loadedModules.contains(newModule.getName())) throw new ModuleException("Module name clash: "+newModule.getName());
				if (moduleNs.contains(newModule.getNamespace())) throw new ModuleException("Module namespace clash: "+newModule.getNamespace());
				// check kernel version
				String reqKernelVer = newModule.getInfo().kernelVersion;
				if (reqKernelVer != null && Gateway.getKernelVersion().compareTo(reqKernelVer) < 0)
					throw new ModuleException("Module "+newModule.getName()+" requires kernel version "+reqKernelVer +" or higher.");
				Logger.debug(4, "Module found: "+newModule.getNamespace()+" - "+newModule.getName());
				loadedModules.add(newModule.getName()); moduleNs.add(newModule.getNamespace());
			} catch (ModuleException e) {
				Logger.error("Could not load module description from "+newModuleURL);
				throw e;
			} catch (Exception e) {
				Logger.error(e);
				throw new ModuleException("Could not load module.xml from "+newModuleURL);
			}
		}
		
		Logger.debug(5, "Checking dependencies");
		boolean allDepsPresent = true;
		
		ArrayList prevModules = new ArrayList();
		for (int i=0; i deps = thisMod.getDependencies();
				depClean = true;
				for (String dep : deps) {
					Logger.msg(6, thisMod.getName()+" depends on "+dep);
					if (!loadedModules.contains(dep)) {
						Logger.error("UNMET MODULE DEPENDENCY: "+thisMod.getName()+" requires "+dep);
						allDepsPresent = false;
					}
					else if (!prevModules.contains(dep)) {
						Logger.msg(1, "ModuleManager: Shuffling "+thisMod.getName()+" to the end to fulfil dependency on "+dep);
						modules.remove(i);
						modules.add(thisMod);
						thisMod = modules.get(i);
						skipped++;
						depClean = false;
						break;
					}
				}
				if (skipped > modules.size()-i) {
					StringBuffer badMod = new StringBuffer();
					for (Module mod : modules.subList(i, modules.size())) {
						badMod.append(mod.getName()).append(" ");
					}
					Logger.die("Circular module dependencies involving: "+badMod);
				}
			}
			// Current module is 'next', this is the correct order to load the properties
			Properties modProp = thisMod.getProperties(isServer);
	        for (Enumeration e = modProp.propertyNames(); e.hasMoreElements();) {
	            String propName = (String)e.nextElement();
	            props.put(propName, modProp.get(propName));
	        }
			prevModules.add(thisMod.getName());
		}
		if (!allDepsPresent) Logger.die("Unmet module dependencies. Cannot continue");
	}

	public void setUser(AgentProxy user) {
		this.user = user;
	}

	public String getModuleVersions() {
		StringBuffer ver = new StringBuffer();
		for (Module thisMod : modules) {
			if (ver.length()>0) ver.append("; ");
			ver.append(thisMod.getName()+" ("+thisMod.getVersion()+")");
		}
		return ver.toString();
	}
	
	
	public Properties getAllModuleProperties() {
		return props;
	}
	
	public void runScripts(String event) {
		for (Module thisMod : modules) {
			if (Bootstrap.shutdown) return;
			try {
				thisMod.runScript(event, user, isServer);
			} catch (ScriptingEngineException e) {
				Logger.error(e);
				Logger.die(e.getMessage());
			}
		}
	}
	
	public void registerModules() throws ModuleException {
		ItemProxy serverItem;
		try {
			serverItem = Gateway.getProxyManager().getProxy(new DomainPath("/servers/"+Gateway.getProperties().getString("ItemServer.name")));
		} catch (ObjectNotFoundException e) {
			throw new ModuleException("Cannot find local server name.");
		}
		Logger.debug(3, "Registering modules");

		boolean reset = Gateway.getProperties().getBoolean("Module.reset", false);

		for (Module thisMod : modules) {
			if (Bootstrap.shutdown) return; 
			Logger.msg("Registering module "+thisMod.getName());
			try {
				String thisResetKey = "Module."+thisMod.getNamespace()+".reset";
				boolean thisReset = reset;
				if (Gateway.getProperties().containsKey(thisResetKey))
					thisReset = Gateway.getProperties().getBoolean(thisResetKey);
				thisMod.importAll(serverItem, user, modulesXML.get(thisMod.getNamespace()), thisReset);
			} catch (Exception e) {
				Logger.error(e);
				throw new ModuleException("Error importing items for module "+thisMod.getName());
			}
			Logger.msg("Module "+thisMod.getName()+" registered");
			
			try {
				thisMod.runScript("startup", user, true);
			} catch (ScriptingEngineException e) {
				Logger.error(e);
				throw new ModuleException("Error in startup script for module "+thisMod.getName());
			}
			
		}
	}

	public void dumpModules() {
		for (Module thisMod : modules) {
			try {
				FileStringUtility.string2File(thisMod.getName()+".xml", Gateway.getMarshaller().marshall(thisMod));
			} catch (Exception e) {
				Logger.error(e);
			}
		}
		
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy