You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by da...@apache.org on 2003/10/22 04:04:31 UTC
cvs commit: incubator-geronimo/modules/kernel/src/java/org/apache/geronimo/kernel/deployment/task CreateClassSpace.java
dain 2003/10/21 19:04:31
Modified: modules/kernel/src/java/org/apache/geronimo/kernel/deployment/loader
ClassSpace.java
modules/kernel/src/java/org/apache/geronimo/kernel/deployment/service
ClassSpaceMetadata.java
ClassSpaceMetadataXMLLoader.java
ServiceDeploymentPlanner.java
modules/kernel/src/java/org/apache/geronimo/kernel/deployment/task
CreateClassSpace.java
Log:
Added declarative parent class space.
Added declarative class space class implementation class.
Added a ton of instrumentation to class space implementation.
Revision Changes Path
1.3 +89 -15 incubator-geronimo/modules/kernel/src/java/org/apache/geronimo/kernel/deployment/loader/ClassSpace.java
Index: ClassSpace.java
===================================================================
RCS file: /home/cvs/incubator-geronimo/modules/kernel/src/java/org/apache/geronimo/kernel/deployment/loader/ClassSpace.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- ClassSpace.java 14 Sep 2003 11:57:37 -0000 1.2
+++ ClassSpace.java 22 Oct 2003 02:04:31 -0000 1.3
@@ -57,8 +57,16 @@
import java.net.URL;
import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.Comparator;
+import javax.management.ObjectName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -72,37 +80,103 @@
public class ClassSpace extends URLClassLoader implements ClassSpaceMBean {
private final static Log log = LogFactory.getLog(ClassSpace.class);
- private final String name;
+ /**
+ * Unique name of this class space.
+ */
+ private final ObjectName name;
+
+ /**
+ * Cache of loaded classesByName... used for debugging purposes
+ */
+ private final Map classesByName = new HashMap();
+
+ /**
+ * Deployments handled by this space
+ */
+ private final Map urlsByDeployment = new HashMap();
/**
* @jmx:managed-constructor
*/
- public ClassSpace(String name, URL[] urls) {
- super(urls,
- Thread.currentThread().getContextClassLoader() == null?
- ClassSpace.class.getClassLoader():
- Thread.currentThread().getContextClassLoader());
+ public ClassSpace(ClassLoader parent, ObjectName name) {
+ super(new URL[0], parent);
this.name = name;
- for (int i = 0; i < urls.length; i++) {
- URL url = urls[i];
- log.debug("Added url to class-space: name=" + name + " url=" + url);
- }
+ }
+
+ /**
+ * @jmx:managed-attribute
+ */
+ public ObjectName getName() {
+ return name;
}
/**
* @jmx:managed-operation
*/
- public void addURLs(List urls) {
+ public synchronized void addDeployment(ObjectName deployment, List urls) {
for (Iterator i = urls.iterator(); i.hasNext();) {
URL url = (URL) i.next();
addURL(url);
+ log.debug("Added url to class-space: name=" + name + " url=" + url);
}
+ urlsByDeployment.put(deployment, Collections.unmodifiableList(new ArrayList(urls)));
}
/**
- * @jmx:managed-attribute
+ * Returns a sorted list loaded classes.
+ * @jmx:managed-operation
*/
- public String getName() {
- return name;
+ public synchronized SortedSet listLoadedClassNames() {
+ return Collections.unmodifiableSortedSet(new TreeSet(classesByName.keySet()));
+ }
+
+ /**
+ * @jmx:managed-operation
+ */
+ public synchronized Map listUrlsByDeployment() {
+ return Collections.unmodifiableMap(urlsByDeployment);
+ }
+
+ /**
+ * @jmx:managed-operation
+ */
+ public synchronized SortedSet listURLs() {
+ TreeSet urls = new TreeSet(new ToStringComparator());
+ URL[] urlArray = getURLs();
+ for (int i = 0; i < urlArray.length; i++) {
+ urls.add(urlArray[i]);
+
+ }
+ return Collections.unmodifiableSortedSet(urls);
+ }
+
+ /**
+ * @jmx:managed-operation
+ */
+ public synchronized Class loadClass(String name) throws ClassNotFoundException {
+ return super.loadClass(name, false);
+ }
+
+ /**
+ * @jmx:managed-operation
+ */
+ public synchronized Class loadClass(String className, boolean resolve) throws ClassNotFoundException {
+ return super.loadClass(className, resolve);
+ }
+
+ protected Class findClass(final String className) throws ClassNotFoundException {
+ // define the class
+ Class clazz = super.findClass(className);
+
+ // add it to our cache
+ classesByName.put(clazz.getName(), clazz);
+
+ return clazz;
+ }
+
+ private class ToStringComparator implements Comparator {
+ public int compare(Object o1, Object o2) {
+ return o1.toString().compareTo(o2.toString());
+ }
}
}
1.2 +41 -1 incubator-geronimo/modules/kernel/src/java/org/apache/geronimo/kernel/deployment/service/ClassSpaceMetadata.java
Index: ClassSpaceMetadata.java
===================================================================
RCS file: /home/cvs/incubator-geronimo/modules/kernel/src/java/org/apache/geronimo/kernel/deployment/service/ClassSpaceMetadata.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ClassSpaceMetadata.java 8 Sep 2003 04:38:33 -0000 1.1
+++ ClassSpaceMetadata.java 22 Oct 2003 02:04:31 -0000 1.2
@@ -65,8 +65,16 @@
* @version $Revision$ $Date$
*/
public class ClassSpaceMetadata {
+ public static final int CREATE_IF_NECESSARY = 0;
+ public static final int CREATE_ALWYAS = 1;
+ public static final int CREATE_NEVER = 2;
+
private ObjectName name;
+ private ObjectName deploymentName;
+ private String className;
+ private int create;
private final List urls = new ArrayList();
+ private ObjectName parent;
public ObjectName getName() {
return name;
@@ -76,7 +84,39 @@
this.name = name;
}
+ public ObjectName getDeploymentName() {
+ return deploymentName;
+ }
+
+ public void setDeploymentName(ObjectName deploymentName) {
+ this.deploymentName = deploymentName;
+ }
+
+ public String getClassName() {
+ return className;
+ }
+
+ public void setClassName(String className) {
+ this.className = className;
+ }
+
+ public int getCreate() {
+ return create;
+ }
+
+ public void setCreate(int create) {
+ this.create = create;
+ }
+
public List getUrls() {
return urls;
+ }
+
+ public ObjectName getParent() {
+ return parent;
+ }
+
+ public void setParent(ObjectName parent) {
+ this.parent = parent;
}
}
1.2 +33 -1 incubator-geronimo/modules/kernel/src/java/org/apache/geronimo/kernel/deployment/service/ClassSpaceMetadataXMLLoader.java
Index: ClassSpaceMetadataXMLLoader.java
===================================================================
RCS file: /home/cvs/incubator-geronimo/modules/kernel/src/java/org/apache/geronimo/kernel/deployment/service/ClassSpaceMetadataXMLLoader.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ClassSpaceMetadataXMLLoader.java 8 Sep 2003 04:38:33 -0000 1.1
+++ ClassSpaceMetadataXMLLoader.java 22 Oct 2003 02:04:31 -0000 1.2
@@ -93,6 +93,38 @@
} catch (MalformedObjectNameException e) {
throw new DeploymentException(e);
}
+
+ // implementation class
+ String code = element.getAttribute("code").trim();
+ if (code.length() > 0) {
+ md.setClassName(code);
+ } else {
+ md.setClassName("org.apache.geronimo.kernel.deployment.loader.ClassSpace");
+ }
+
+ // should we be creating the classloader
+ String create = element.getAttribute("create").trim();
+ if (create.length() > 0) {
+ if ((new Boolean(create)).booleanValue()) {
+ md.setCreate(ClassSpaceMetadata.CREATE_ALWYAS);
+ } else {
+ md.setCreate(ClassSpaceMetadata.CREATE_NEVER);
+ }
+ } else {
+ md.setCreate(ClassSpaceMetadata.CREATE_IF_NECESSARY);
+ }
+
+ // what should be the parent of this class space if we end up creating it
+ String parentName = element.getAttribute("parent");
+ if (parentName != null && parentName.length() > 0) {
+ try {
+ md.setParent(new ObjectName(parentName));
+ } catch (MalformedObjectNameException e) {
+ throw new DeploymentException(e);
+ }
+ }
+
+ // get the urls
List urls = md.getUrls();
NodeList nl = element.getElementsByTagName("codebase");
try {
1.3 +28 -21 incubator-geronimo/modules/kernel/src/java/org/apache/geronimo/kernel/deployment/service/ServiceDeploymentPlanner.java
Index: ServiceDeploymentPlanner.java
===================================================================
RCS file: /home/cvs/incubator-geronimo/modules/kernel/src/java/org/apache/geronimo/kernel/deployment/service/ServiceDeploymentPlanner.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- ServiceDeploymentPlanner.java 5 Oct 2003 01:37:00 -0000 1.2
+++ ServiceDeploymentPlanner.java 22 Oct 2003 02:04:31 -0000 1.3
@@ -168,7 +168,6 @@
InputStream is;
URL url = goal.getUrl();
URI baseURI = URI.create(url.toString()).normalize();
- ;
URLType type = goal.getType();
if (type == URLType.RESOURCE) {
@@ -207,14 +206,16 @@
} catch (MalformedObjectNameException e) {
throw new DeploymentException(e);
}
-
ServiceDeployment serviceInfo = new ServiceDeployment(deploymentName, null, url);
createDeploymentUnitPlan.addTask(new RegisterMBeanInstance(server, deploymentName, serviceInfo));
MBeanMetadata metadata = new MBeanMetadata(deploymentName);
createDeploymentUnitPlan.addTask(new StartMBeanInstance(server, metadata));
- ObjectName loaderName = addClassSpaces(doc.getElementsByTagName("class-space"), createDeploymentUnitPlan, url);
+ // add a plan to create a class space
+ ClassSpaceMetadata md = createClassSpaceMetadata((Element) doc.getElementsByTagName("class-space").item(0), deploymentName, url);
+ createDeploymentUnitPlan.addTask(new CreateClassSpace(server, md));
plans.add(createDeploymentUnitPlan);
+ ObjectName loaderName = md.getName();
// register a plan to create each mbean
NodeList nl = doc.getElementsByTagName("mbean");
@@ -243,35 +244,41 @@
return true;
}
- private ObjectName addClassSpaces(NodeList nl, DeploymentPlan plan, URL baseURL) throws DeploymentException {
- Element classSpaceElement = (Element) nl.item(0);
+ private ClassSpaceMetadata createClassSpaceMetadata(Element classSpaceElement, ObjectName deploymentName, URL baseURL) throws DeploymentException {
+ ClassSpaceMetadata classSpaceMetadata;
if (classSpaceElement == null) {
- return null;
+ classSpaceMetadata = new ClassSpaceMetadata();
+ try {
+ classSpaceMetadata.setName(new ObjectName("geronimo.system:role=ClassSpace,name=Application"));
+ } catch (MalformedObjectNameException e) {
+ // this will never happen as above is a valid object name
+ throw new AssertionError(e);
+ }
+ classSpaceMetadata.setClassName("org.apache.geronimo.kernel.deployment.loader.ClassSpace");
+ classSpaceMetadata.setCreate(ClassSpaceMetadata.CREATE_IF_NECESSARY);
+ } else {
+ ClassSpaceMetadataXMLLoader classSpaceLoader = new ClassSpaceMetadataXMLLoader(baseURL);
+ classSpaceMetadata = classSpaceLoader.loadXML(classSpaceElement);
}
-
- ClassSpaceMetadataXMLLoader classSpaceLoader = new ClassSpaceMetadataXMLLoader(baseURL);
- ClassSpaceMetadata md = classSpaceLoader.loadXML(classSpaceElement);
- CreateClassSpace createTask = new CreateClassSpace(server, md);
- plan.addTask(createTask);
- return md.getName();
+ classSpaceMetadata.setDeploymentName(deploymentName);
+ return classSpaceMetadata;
}
private boolean removeURL(UndeployURL goal, Set goals, Set plans) throws DeploymentException {
-
+
URL url = goal.getUrl();
-
+
//TODO: better method of determining whether this deployer should
//handle this undeploy call. This deployer should only handle the undeploy
//if it is something that it would have deployed (ie a service). More context
//information needs to be available to make this decision. For now, just handle
//the case of the unpacked service, just to prevent this deployer from undeploying everything.
-
- if (!url.getPath().endsWith("-service.xml")) {
+
+ if (!url.getPath().endsWith("-service.xml")) {
return false;
}
-
-
+
ObjectName deploymentName = null;
try {
deploymentName = new ObjectName("geronimo.deployment:role=DeploymentUnit,type=Service,url=" + ObjectName.quote(url.toString()));
@@ -302,14 +309,14 @@
for (Iterator i = mbeans.iterator(); i.hasNext();) {
ObjectName name = (ObjectName) i.next();
destroyPlan.addTask(new DestroyMBeanInstance(server, name));
-
+
}
destroyPlan.addTask(new DestroyMBeanInstance(server, deploymentName));
plans.add(destroyPlan);
goals.remove(goal);
-
+
return true;
}
1.2 +60 -16 incubator-geronimo/modules/kernel/src/java/org/apache/geronimo/kernel/deployment/task/CreateClassSpace.java
Index: CreateClassSpace.java
===================================================================
RCS file: /home/cvs/incubator-geronimo/modules/kernel/src/java/org/apache/geronimo/kernel/deployment/task/CreateClassSpace.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- CreateClassSpace.java 8 Sep 2003 04:38:34 -0000 1.1
+++ CreateClassSpace.java 22 Oct 2003 02:04:31 -0000 1.2
@@ -55,14 +55,12 @@
*/
package org.apache.geronimo.kernel.deployment.task;
-import java.net.URL;
+import java.lang.reflect.Constructor;
import java.util.List;
-import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
-import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
@@ -96,23 +94,68 @@
ObjectName name = metadata.getName();
List urls = metadata.getUrls();
if (!server.isRegistered(name)) {
+ // Get the class object for the class space
+ // Class must be available from the JMX classloader repoistory
+ Class clazz = null;
try {
- // @todo add trace logging
- // @todo use metadata to determine implementation
- ClassSpace space = new ClassSpace(metadata.getName().toString(), (URL[]) urls.toArray(new URL[urls.size()]));
- actualName = server.registerMBean(space, name).getObjectName();
- } catch (RuntimeException e) {
- throw new DeploymentException(e);
- } catch (InstanceAlreadyExistsException e) {
- throw new DeploymentException(e);
- } catch (MBeanRegistrationException e) {
- throw new DeploymentException(e);
- } catch (NotCompliantMBeanException e) {
+ clazz = server.getClassLoaderRepository().loadClass(metadata.getClassName());
+ } catch (ClassNotFoundException e) {
throw new DeploymentException(e);
}
+ if (!ClassSpace.class.isAssignableFrom(clazz)) {
+ throw new DeploymentException("Class does not implement ClassSpace: " + clazz.getName());
+ }
+ if (!ClassLoader.class.isAssignableFrom(clazz)) {
+ throw new DeploymentException("Class is not a ClassLoader: " + clazz.getName());
+ }
+
+ // Get the constructor
+ Constructor constructor = null;
+ try {
+ constructor = clazz.getConstructor(new Class[]{ClassLoader.class, ObjectName.class});
+ } catch (Exception e) {
+ throw new DeploymentException("Class does not have the constructor " +
+ clazz.getName() + "(Classloader parent, String name)");
+ }
+
+ // Determine the parent classloader
+ ObjectName parentName = metadata.getParent();
+ ClassLoader parent = null;
+ if (parentName != null) {
+ try {
+ parent = server.getClassLoader(parentName);
+ } catch (InstanceNotFoundException e) {
+ throw new DeploymentException("Parent class loader not found", e);
+ }
+ } else {
+ Thread.currentThread().getContextClassLoader();
+ if (parent == null) {
+ parent = ClassLoader.getSystemClassLoader();
+ }
+ }
+
+ // Construct a class space instance
+ ClassSpace space = null;
+ try {
+ space = (ClassSpace) constructor.newInstance(new Object[]{parent, metadata.getName()});
+ } catch (Exception e) {
+ // @todo use a typed exception which carries the object name and class type
+ throw new DeploymentException("Could not create class space instance", e);
+ }
+
+ // Add the URLs from the deployment to the class space
+ space.addDeployment(metadata.getDeploymentName(), metadata.getUrls());
+
+ // Register the class loader witht the MBeanServer
+ try {
+ actualName = server.registerMBean(space, name).getObjectName();
+ } catch (Exception e) {
+ // @todo use a typed exception which carries the object name and class type
+ throw new DeploymentException("Could not register class space with MBeanServer", e);
+ }
} else {
try {
- server.invoke(name, "addURLs", new Object[]{urls}, new String[]{"java.util.List"});
+ server.invoke(name, "addDeployment", new Object[]{metadata.getDeploymentName(), urls}, new String[]{"javax.management.ObjectName", "java.util.List"});
} catch (InstanceNotFoundException e) {
throw new DeploymentException(e);
} catch (MBeanException e) {
@@ -124,6 +167,7 @@
}
public void undo() {
+ // @todo we have a problem here... class space may have been used so it may now contain bad classes (not a problem when constructing a new space)
if (actualName != null) {
try {
server.unregisterMBean(actualName);