package scs.container.servant;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Properties;
import org.omg.PortableServer.Servant;
import org.omg.PortableServer.POAPackage.ObjectNotActive;
import org.omg.PortableServer.POAPackage.ServantNotActive;
import org.omg.PortableServer.POAPackage.WrongAdapter;
import org.omg.PortableServer.POAPackage.WrongPolicy;
import scs.container.ComponentAlreadyLoaded;
import scs.container.ComponentHandle;
import scs.core.ComponentId;
import scs.container.ComponentLoaderPOA;
import scs.container.ComponentNotFound;
import scs.container.LoadFailure;
import scs.core.IComponentHelper;
import scs.core.ShutdownFailed;
import scs.core.servant.IComponentServant;
/**
* Servant da interface scs::container::ComponentLoader
* @author Eduardo Fonseca / Luiz Marques
*/
public class ComponentLoaderServant extends ComponentLoaderPOA {
public class JarFileLoader extends URLClassLoader
{
public JarFileLoader (URL[] urls)
{
super (urls);
}
public boolean addFile (String path)
{
String urlPath = "file://" + path;
try {
addURL (new URL (urlPath));
} catch (MalformedURLException e) {
return(false);
}
return(true);
}
}
private ComponentCollectionServant collectionServant = null;
private Properties config = null;
private int instanceIdCounter = 0;
JarFileLoader loader = null;
/**
* @param configuration Properties contendo os parametros de configuracao
* @param compColl Referencia para o ComponentCollection do container
*/
public ComponentLoaderServant(Properties configuration, ComponentCollectionServant compColl) {
this.config = configuration;
this.collectionServant = compColl;
String jarfiles = config.getProperty("jar-files");
URL urls [] = {};
loader = new JarFileLoader(urls);
if( jarfiles.length() > 0 ) {
String files[] = jarfiles.split(";");
for (int i = 0; i < files.length; i++) {
loader.addFile(files[i]);
}
}
}
/**
* Retorna os componentes que podem ser instanciados pelo container
* @return ComponentId[] representando componentes conhecidos pelo container e, portanto,
* passiveis de instanciacao
*/
public ComponentId[] getInstalledComponents() {
HashSet<ComponentId> componentIds = new HashSet<ComponentId>();
Enumeration keys = config.keys();
while (keys.hasMoreElements()) {
String element = (String) keys.nextElement();
String [] line = element.split("-");
if(line.length == 3 && line[0].equals("component"))
{
ComponentId c = new ComponentId();
c.name = line[1];
c.version = Integer.parseInt(line[2]);
componentIds.add(c);
}
}
if(componentIds.size() == 0)
return null;
ComponentId[] cmps = new ComponentId[componentIds.size()];
int i = 0;
for (Iterator iter = componentIds.iterator(); iter.hasNext();) {
ComponentId element = (ComponentId) iter.next();
cmps[i] = element;
i++;
}
return cmps;
}
/** Cria uma instancia da classe cujo nome e passado como parametro
* @param classname String que representa o nome da classe a ser intanciada
*/
public Servant loadServant(String classname) throws LoadFailure, ComponentNotFound {
boolean found = false;
Servant toRun = null;
try {
toRun = (Servant)Class.forName(classname).newInstance();
found = true;
} catch (ClassNotFoundException e) {
found = false;
} catch (InstantiationException e) {
throw new LoadFailure();
} catch (IllegalAccessException e) {
throw new LoadFailure();
} catch (IllegalArgumentException e) {
throw new LoadFailure();
} catch (SecurityException e) {
throw new LoadFailure();
}
if( found )
return toRun;
try {
System.err.println("chamando this.loader.loadClass(" + classname + ")");
toRun = (Servant) this.loader.loadClass(classname).newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
throw new ComponentNotFound();
} catch (InstantiationException e) {
throw new LoadFailure();
} catch (IllegalAccessException e) {
throw new LoadFailure();
} catch (IllegalArgumentException e) {
throw new LoadFailure();
} catch (SecurityException e) {
throw new LoadFailure();
}
return toRun;
}
/**
* Carrega no container componente representado por ComponentId
* @param id ComponentId que representa o componente a ser carregado
* @param args Conjuntos de argumentos passados para o construtor do componente
*/
public ComponentHandle load(ComponentId id, String[] args)
throws ComponentNotFound, ComponentAlreadyLoaded, LoadFailure {
Servant toRun = null;
String className = config.getProperty("component-"+id.name+"-"+id.version);
if(className == null)
{
throw new ComponentNotFound();
}
//System.err.println("carregando classe: " + className );
toRun = this.loadServant(className);
IComponentServant icomp= (IComponentServant) toRun;
icomp.createComponentId(id);
ComponentHandle handle = new ComponentHandle();
/**
* Nao limita a quantidade de instancias por componente por default,
* pois esse parametro nao esta definido nas propriedades do componente
*/
/*
ComponentHandle compHandles[] = this.collectionServant.getComponent(id);
if( compHandles != null && compHandles.length > 0 ) {
throw new ComponentAlreadyLoaded();
}
*/
try {
//System.err.println("Tentativa de narrow da classe carregada para IComponent ... " );
//System.err.println();
handle.cmp = IComponentHelper.narrow(this._poa().servant_to_reference(toRun));
handle.id = id;
handle.instance_id = instanceIdCounter++;
} catch (ServantNotActive e) {
throw new LoadFailure();
} catch (WrongPolicy e) {
throw new LoadFailure();
}
this.collectionServant.addComponent(handle);
return handle;
}
/**
* descarrega a instancia ComponentHandle do container
* @param handle ComponentHandle representando a instancia a ser descarregada
*/
public void unload(ComponentHandle handle) throws ComponentNotFound {
if( ! this.collectionServant.removeComponent(handle) )
throw new ComponentNotFound();
try {
handle.cmp.shutdown();
} catch (ShutdownFailed e) {
e.printStackTrace();
}
try {
this._poa().deactivate_object(this._poa().reference_to_id(handle.cmp));
} catch (ObjectNotActive e) {
e.printStackTrace();
} catch (WrongPolicy e) {
e.printStackTrace();
} catch (WrongAdapter e) {
e.printStackTrace();
}
}
}