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);