/*
* Copyright(c) 2005 Center for E-Commerce Infrastructure Development, The
* University of Hong Kong (HKU). All Rights Reserved.
*
* This software is licensed under the GNU GENERAL PUBLIC LICENSE Version 2.0 [1]
*
* [1] http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
*/
package hk.hku.cecid.piazza.commons.module;
import hk.hku.cecid.piazza.commons.util.Instance;
import hk.hku.cecid.piazza.commons.util.PropertyTree;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
/**
* ModuleGroup represents a group of modules and is capable of starting
* and stopping its active modules. A module group can have multiple system
* modules and the first one defined in the module group descriptor will be
* treated as the default system module.
*
* @author Hugo Y. K. Lam
*
*/
public class ModuleGroup {
private Map allModules;
private List normalModules;
private List systemModules;
private List activeModules;
private String name;
private ClassLoader loader;
private PropertyTree descriptor;
private ModuleGroup parent;
private Set children;
/**
* Creates a new instance of ModuleGroup.
*
* @param descriptorLocation the descriptor location.
*/
public ModuleGroup(String descriptorLocation) {
this(descriptorLocation, null);
}
/**
* Creates a new instance of ModuleGroup.
*
* @param descriptorLocation the descriptor location.
* @param loader the class loader for loading the modules.
*/
public ModuleGroup(String descriptorLocation, ClassLoader loader) {
if (descriptorLocation == null) {
throw new ModuleException("No module group descriptor specified");
}
if (loader == null) {
loader = getClass().getClassLoader();
}
URL resrc = Module.getResource(descriptorLocation, loader);
if (resrc == null) {
throw new ModuleException("Module group descriptor not found: "
+ descriptorLocation);
}
try {
this.loader = loader;
this.allModules = Collections.synchronizedMap(new LinkedHashMap());
this.normalModules = new Vector();
this.systemModules = new Vector();
this.activeModules = new Vector();
this.children = Collections.synchronizedSet(new HashSet());
this.descriptor = new PropertyTree(resrc);
this.name = descriptor.getProperty("/module-group/@name");
loadModules();
}
catch (Exception e) {
throw new ModuleException("Unable to initialize module group '"+getName()+"'", e);
}
}
/**
* Loads and initializes the defined modules.
*/
private void loadModules() {
try {
int ms = descriptor.countProperties("/module-group/module");
for (int i=1; i<=ms; i++) {
String mclass = descriptor.getProperty("/module-group/module["+i+"]/class");
String mdesc = descriptor.getProperty("/module-group/module["+i+"]/descriptor");
Instance instance = new Instance(mclass, loader,
new Class[]{String.class, ClassLoader.class, Boolean.TYPE},
new Object[]{mdesc, loader, Boolean.FALSE});
Module module = (Module)instance.getObject();
module.setGroup(this);
module.init();
if (module instanceof ActiveModule) {
activeModules.add(module);
}
else if (module instanceof SystemModule) {
systemModules.add(module);
}
else {
normalModules.add(module);
}
if (module.getId() != null) {
allModules.put(module.getId(), module);
}
}
}
catch (Exception e) {
throw new ModuleException("Unable to load modules", e);
}
}
/**
* Starts all active modules.
*/
public void startActiveModules() {
Iterator ms = activeModules.iterator();
while (ms.hasNext()) {
ActiveModule am = (ActiveModule)ms.next();
if (am.isGroupStart()) {
am.start();
}
}
}
/**
* Stops all active modules.
*/
public void stopActiveModules() {
Iterator ms = activeModules.iterator();
while (ms.hasNext()) {
ActiveModule am = (ActiveModule)ms.next();
if (am.isGroupStop()) {
am.stop();
}
}
}
/**
* Gets the default system module.
*
* @return the default system module or null if there is none.
*/
public SystemModule getSystemModule() {
if (systemModules.size() > 0) {
return (SystemModule)systemModules.get(0);
}
else {
return null;
}
}
/**
* Gets all modules in this module group.
*
* @return all modules in this module group.
*/
public Collection getModules() {
return allModules.values();
}
/**
* Gets the specified module in this module group.
*
* @param id the module ID.
* @return the specified module.
*/
public Module getModule(String id) {
if (id != null) {
return (Module)allModules.get(id);
}
else {
return null;
}
}
/**
* Gets the name of this module group.
*
* @return the name of this module group.
*/
public String getName() {
return name == null? "unknown":name;
}
/**
* Gets the parent module group.
*
* @return the parent module group.
*/
public ModuleGroup getParent() {
return parent;
}
/**
* Sets the parent module group.
*
* @param parent the parent module group.
*/
public void setParent(ModuleGroup parent) {
this.parent = parent;
}
/**
* Adds a child module group.
*
* @param group the child module group.
*/
public void addChild(ModuleGroup group) {
if (group != null) {
if (children.add(group)) {
group.setParent(this);
}
}
}
public void removeChild(ModuleGroup group) {
if (group != null) {
if (children.remove(group)) {
group.setParent(null);
}
}
}
/**
* Gets the child module groups.
*
* @return the child module groups.
*/
public Collection getChildren() {
return children;
}
/**
* Returns a string representation of this module group.
*
* @return a string representation of this module group.
* @see java.lang.Object#toString()
*/
public String toString() {
return "Module Group ["+getName()+"]";
}
}