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/08/14 02:02:39 UTC

cvs commit: incubator-geronimo/modules/core/src/java/org/apache/geronimo/deployment/plan InitializeMBeanInstance.java CreateMBeanInstance.java DeploymentPlan.java DeploymentTask.java DestroyMBeanInstance.java InvokeMBeanOperation.java RegisterMBeanInstance.java UnregisterMBeanInstance.java CreateClassSpace.java StartMBeanInstance.java

dain        2003/08/13 17:02:39

  Modified:    modules/core/src/java/org/apache/geronimo/deployment/plan
                        CreateMBeanInstance.java DeploymentPlan.java
                        DeploymentTask.java DestroyMBeanInstance.java
                        InvokeMBeanOperation.java
                        RegisterMBeanInstance.java
                        UnregisterMBeanInstance.java CreateClassSpace.java
                        StartMBeanInstance.java
  Added:       modules/core/src/java/org/apache/geronimo/deployment/plan
                        InitializeMBeanInstance.java
  Log:
  Deployment system now will wait for relationship type to be registered and for related MBeans to be created before attempting to enroll a MBean in a relationship.  This also delays the create callback until all related MBeans have been registered with the MBeanServer and have been enrolled in the relationship.
  
  Revision  Changes    Path
  1.5       +10 -122   incubator-geronimo/modules/core/src/java/org/apache/geronimo/deployment/plan/CreateMBeanInstance.java
  
  Index: CreateMBeanInstance.java
  ===================================================================
  RCS file: /home/cvs/incubator-geronimo/modules/core/src/java/org/apache/geronimo/deployment/plan/CreateMBeanInstance.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- CreateMBeanInstance.java	13 Aug 2003 21:17:20 -0000	1.4
  +++ CreateMBeanInstance.java	14 Aug 2003 00:02:38 -0000	1.5
  @@ -62,7 +62,6 @@
   import java.util.List;
   import java.util.Map;
   import java.util.Set;
  -import java.util.Collections;
   import javax.management.Attribute;
   import javax.management.AttributeList;
   import javax.management.InstanceAlreadyExistsException;
  @@ -76,35 +75,26 @@
   import javax.management.NotCompliantMBeanException;
   import javax.management.ObjectName;
   import javax.management.ReflectionException;
  -import javax.management.relation.RelationServiceMBean;
  -import javax.management.relation.Role;
  -import javax.management.relation.RoleList;
  -import javax.management.relation.RoleInfo;
   
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogFactory;
   import org.apache.geronimo.core.util.ClassUtil;
   import org.apache.geronimo.deployment.DeploymentException;
   import org.apache.geronimo.deployment.service.MBeanMetadata;
  -import org.apache.geronimo.deployment.service.MBeanRelationship;
  -import org.apache.geronimo.deployment.service.MBeanOperation;
  -import org.apache.geronimo.jmx.JMXUtil;
   
   /**
    * Creates an new MBean instance and intializes it according to the specified MBeanMetadata metadata
    *
    * @version $Revision$ $Date$
    */
  -public class CreateMBeanInstance extends DeploymentTask {
  +public class CreateMBeanInstance implements DeploymentTask {
       private final Log log = LogFactory.getLog(this.getClass());
       private final Set plans;
       private final MBeanServer server;
  -    private final RelationServiceMBean relationService;
       private final ObjectName parent;
       private final ObjectName loaderName;
       private final MBeanMetadata metadata;
       private ObjectName actualName;
  -    private boolean createCalled;
   
       public CreateMBeanInstance(Set plans, MBeanServer server, ObjectName parent, MBeanMetadata metadata, ObjectName loaderName) {
           this.plans = plans;
  @@ -112,7 +102,10 @@
           this.parent = parent;
           this.metadata = metadata;
           this.loaderName = loaderName;
  -        relationService = JMXUtil.getRelationService(server);
  +    }
  +
  +    public boolean canRun() throws DeploymentException {
  +        return true;
       }
   
       public void perform() throws DeploymentException {
  @@ -165,60 +158,6 @@
                   throw new DeploymentException(e);
               }
   
  -            // Resolve and enroll in all relationships
  -            Set relationships = metadata.getRelationships();
  -            try {
  -                for (Iterator i = relationships.iterator(); i.hasNext();) {
  -                    MBeanRelationship relationship = (MBeanRelationship) i.next();
  -
  -                    // if we don't have a relationship instance create one
  -                    String relationshipName = relationship.getName();
  -                    String relationshipRole = relationship.getRole();
  -                    if (!relationService.hasRelation(relationshipName).booleanValue()) {
  -                        // if  we don't have a relationship of the
  -                        String relationshipType = relationship.getType();
  -                        if (!relationService.getAllRelationTypeNames().contains(relationshipType)) {
  -                            throw new DeploymentException("Relationship type is not registered: relationType=" + relationshipType);
  -                        }
  -
  -                        RoleList roleList = new RoleList();
  -                        roleList.add(new Role(relationshipRole, Collections.singletonList(actualName)));
  -
  -                        // if we have a target we need to add it to the role list
  -                        String target = relationship.getTarget();
  -                        if (target != null && target.length() > 0) {
  -                            String targetRoleName = relationship.getTargetRole();
  -                            if (targetRoleName == null || targetRoleName.length() == 0) {
  -                                List roles = relationService.getRoleInfos(relationshipType);
  -                                if(roles.size() < 2) {
  -                                    throw new DeploymentException("Relationship has less than two roles. You cannot specify a target");
  -                                }
  -                                if(roles.size() > 2) {
  -                                    throw new DeploymentException("Relationship has more than two roles. You must use targetRoleName");
  -                                }
  -                                if (((RoleInfo) roles.get(0)).getName().equals(relationshipRole)) {
  -                                    targetRoleName = ((RoleInfo) roles.get(1)).getName();
  -                                } else {
  -                                    targetRoleName = ((RoleInfo) roles.get(0)).getName();
  -                                }
  -                            }
  -
  -                            roleList.add(new Role(targetRoleName, Collections.singletonList(new ObjectName(target))));
  -                        }
  -                        relationService.createRelation(relationshipName, relationshipType, roleList);
  -                    } else {
  -                        // We have an exiting relationship -- just add to the existing role
  -                        List members = relationService.getRole(relationshipName, relationshipRole);
  -                        members.add(actualName);
  -                        relationService.setRole(relationshipName, new Role(relationshipRole, members));
  -                    }
  -                }
  -            } catch (DeploymentException e) {
  -                throw e;
  -            } catch (Exception e) {
  -                throw new DeploymentException(e);
  -            }
  -
               // Set the MBean attributes
               MBeanInfo mbInfo;
               try {
  @@ -264,44 +203,9 @@
                   throw new DeploymentException(e);
               }
   
  -            // Invoke the create callback method
  -            try {
  -                server.invoke(actualName, "create", null, null);
  -                createCalled = true;
  -            } catch (RuntimeException e) {
  -                throw new DeploymentException(e);
  -            } catch (InstanceNotFoundException e) {
  -                throw new DeploymentException(e);
  -            } catch (MBeanException e) {
  -                throw new DeploymentException(e);
  -            } catch (ReflectionException e) {
  -                if (e.getTargetException() instanceof NoSuchMethodException) {
  -                    // did not have a create method - ok
  -                } else {
  -                    throw new DeploymentException(e);
  -                }
  -            }
  -
  -            // Add a deployment plan to start the MBean
  -            DeploymentPlan startPlan = new DeploymentPlan();
  -            startPlan.addTask(new StartMBeanInstance(server, actualName));
  -            List operations = metadata.getOperations();
  -            for (Iterator i = operations.iterator(); i.hasNext();) {
  -                MBeanOperation operation = (MBeanOperation) i.next();
  -                int argCount = operation.getTypes().size();
  -                String[] argTypes = (String[]) operation.getTypes().toArray(new String[argCount]);
  -                List values = operation.getArgs();
  -                Object[] args = new Object[argCount];
  -                for (int j = 0; j < argCount; j++) {
  -                    Object value = values.get(j);
  -                    if (value instanceof String) {
  -                        value = getValue(newCL, argTypes[j], (String) value);
  -                    }
  -                    args[j] = value;
  -                }
  -                startPlan.addTask(new InvokeMBeanOperation(server, actualName, operation.getOperation(), argTypes, args));
  -            }
  -            plans.add(startPlan);
  +            // Add a deployment plan to initialize the MBeans
  +            DeploymentTask initTask = new InitializeMBeanInstance(plans, server, actualName, parent, metadata, loaderName);
  +            plans.add(new DeploymentPlan(initTask));
           } catch (DeploymentException e) {
               undo();
               throw e;
  @@ -316,23 +220,6 @@
           }
   
           try {
  -            if (createCalled) {
  -                server.invoke(actualName, "destroy", null, null);
  -            }
  -        } catch (InstanceNotFoundException e) {
  -            log.warn("MBean was already removed " + actualName, e);
  -            return;
  -        } catch (MBeanException e) {
  -            log.error("Error while destroying MBean " + actualName, e);
  -        } catch (ReflectionException e) {
  -            if (e.getTargetException() instanceof NoSuchMethodException) {
  -                // did not have a destroy method - ok
  -            } else {
  -                log.error("Error while destroying MBean " + actualName, e);
  -            }
  -        }
  -
  -        try {
               server.invoke(parent, "removeChild", new Object[]{actualName}, new String[]{"javax.management.ObjectName"});
           } catch (InstanceNotFoundException e) {
               log.warn("Could not remove from parent", e);
  @@ -341,6 +228,7 @@
           } catch (ReflectionException e) {
               log.error("Error while removing MBean " + actualName + " from parent", e);
           }
  +
           try {
               server.unregisterMBean(actualName);
           } catch (InstanceNotFoundException e) {
  
  
  
  1.2       +17 -1     incubator-geronimo/modules/core/src/java/org/apache/geronimo/deployment/plan/DeploymentPlan.java
  
  Index: DeploymentPlan.java
  ===================================================================
  RCS file: /home/cvs/incubator-geronimo/modules/core/src/java/org/apache/geronimo/deployment/plan/DeploymentPlan.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DeploymentPlan.java	11 Aug 2003 17:59:10 -0000	1.1
  +++ DeploymentPlan.java	14 Aug 2003 00:02:38 -0000	1.2
  @@ -75,8 +75,24 @@
       public DeploymentPlan() {
       }
   
  +    public DeploymentPlan(DeploymentTask task) {
  +        tasks.add(task);
  +    }
  +
       public void addTask(DeploymentTask task) {
           tasks.add(task);
  +    }
  +
  +    public boolean canRun() throws DeploymentException {
  +        boolean canRun = true;
  +        for (Iterator i = tasks.iterator(); i.hasNext();) {
  +            DeploymentTask task = (DeploymentTask) i.next();
  +            log.trace("Checking if task can run " + task);
  +
  +            // always check each task, so the task can throw an exception if the task can never run
  +            canRun = canRun && task.canRun();
  +        }
  +        return canRun;
       }
   
       public void execute() throws DeploymentException {
  
  
  
  1.2       +26 -5     incubator-geronimo/modules/core/src/java/org/apache/geronimo/deployment/plan/DeploymentTask.java
  
  Index: DeploymentTask.java
  ===================================================================
  RCS file: /home/cvs/incubator-geronimo/modules/core/src/java/org/apache/geronimo/deployment/plan/DeploymentTask.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DeploymentTask.java	11 Aug 2003 17:59:10 -0000	1.1
  +++ DeploymentTask.java	14 Aug 2003 00:02:38 -0000	1.2
  @@ -58,12 +58,33 @@
   import org.apache.geronimo.deployment.DeploymentException;
   
   /**
  - *
  + * DeploymenTask is a single unit of work in a plan.  The plan checks is all tasks canRun() before
  + * executing the plan and performing all the tasks.  I this task throws an exception during perform,
  + * it must clean up after itself before throwing the exception as undo will not be called.  If this
  + * task completes successfully but a subsequent task throws an exception the undo method will be
  + * called so the task can rollback any changes.
    *
    * @version $Revision$ $Date$
    */
  -public abstract class DeploymentTask {
  -    public abstract void perform() throws DeploymentException;
  +public interface DeploymentTask {
  +    /**
  +     * Can this task complete now?
  +     * @return true if the can can complete now; otherwise false and the plan should wait
  +     * @throws DeploymentException if a problem occurs while checking the task, if the can check
  +     * throws an exception the plan should be discarded
  +     */
  +    boolean canRun() throws DeploymentException;
  +
  +    /**
  +     * Executes the task.  If a DeploymentException is throw undo will not be called, so task
  +     * should clean up after itself before throwing the exception
  +     * @throws DeploymentException if an unrecoverable problem occurs in the task, plan should
  +     * be rolled back
  +     */
  +    void perform() throws DeploymentException;
   
  -    public abstract void undo();
  +    /**
  +     * Undo all operations performed during the perform method.
  +     */
  +    void undo();
   }
  
  
  
  1.2       +7 -2      incubator-geronimo/modules/core/src/java/org/apache/geronimo/deployment/plan/DestroyMBeanInstance.java
  
  Index: DestroyMBeanInstance.java
  ===================================================================
  RCS file: /home/cvs/incubator-geronimo/modules/core/src/java/org/apache/geronimo/deployment/plan/DestroyMBeanInstance.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DestroyMBeanInstance.java	11 Aug 2003 17:59:10 -0000	1.1
  +++ DestroyMBeanInstance.java	14 Aug 2003 00:02:38 -0000	1.2
  @@ -64,13 +64,14 @@
   
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogFactory;
  +import org.apache.geronimo.deployment.DeploymentException;
   
   /**
    *
    *
    * @version $Revision$ $Date$
    */
  -public class DestroyMBeanInstance extends DeploymentTask {
  +public class DestroyMBeanInstance implements DeploymentTask {
       private final Log log = LogFactory.getLog(this.getClass());
       private final MBeanServer server;
       private final ObjectName name;
  @@ -78,6 +79,10 @@
       public DestroyMBeanInstance(MBeanServer server, ObjectName name) {
           this.server = server;
           this.name = name;
  +    }
  +
  +    public boolean canRun() throws DeploymentException {
  +        return true;
       }
   
       public void perform() {
  
  
  
  1.2       +8 -4      incubator-geronimo/modules/core/src/java/org/apache/geronimo/deployment/plan/InvokeMBeanOperation.java
  
  Index: InvokeMBeanOperation.java
  ===================================================================
  RCS file: /home/cvs/incubator-geronimo/modules/core/src/java/org/apache/geronimo/deployment/plan/InvokeMBeanOperation.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- InvokeMBeanOperation.java	11 Aug 2003 19:46:28 -0000	1.1
  +++ InvokeMBeanOperation.java	14 Aug 2003 00:02:38 -0000	1.2
  @@ -64,11 +64,11 @@
   import org.apache.geronimo.deployment.DeploymentException;
   
   /**
  - * 
  - * 
  + *
  + *
    * @version $Revision$ $Date$
    */
  -public class InvokeMBeanOperation extends DeploymentTask {
  +public class InvokeMBeanOperation implements DeploymentTask {
       private final MBeanServer server;
       private final ObjectName name;
       private final String operation;
  @@ -81,6 +81,10 @@
           this.operation = operation;
           this.argTypes = argTypes;
           this.args = args;
  +    }
  +
  +    public boolean canRun() throws DeploymentException {
  +        return true;
       }
   
       public void perform() throws DeploymentException {
  
  
  
  1.2       +6 -2      incubator-geronimo/modules/core/src/java/org/apache/geronimo/deployment/plan/RegisterMBeanInstance.java
  
  Index: RegisterMBeanInstance.java
  ===================================================================
  RCS file: /home/cvs/incubator-geronimo/modules/core/src/java/org/apache/geronimo/deployment/plan/RegisterMBeanInstance.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- RegisterMBeanInstance.java	11 Aug 2003 17:59:10 -0000	1.1
  +++ RegisterMBeanInstance.java	14 Aug 2003 00:02:38 -0000	1.2
  @@ -69,7 +69,7 @@
    *
    * @version $Revision$ $Date$
    */
  -public class RegisterMBeanInstance extends DeploymentTask {
  +public class RegisterMBeanInstance implements DeploymentTask {
       private final MBeanServer server;
       private final ObjectName name;
       private final Object instance;
  @@ -79,6 +79,10 @@
           this.server = server;
           this.name = name;
           this.instance = instance;
  +    }
  +
  +    public boolean canRun() throws DeploymentException {
  +        return true;
       }
   
       public void perform() throws DeploymentException {
  
  
  
  1.2       +6 -2      incubator-geronimo/modules/core/src/java/org/apache/geronimo/deployment/plan/UnregisterMBeanInstance.java
  
  Index: UnregisterMBeanInstance.java
  ===================================================================
  RCS file: /home/cvs/incubator-geronimo/modules/core/src/java/org/apache/geronimo/deployment/plan/UnregisterMBeanInstance.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- UnregisterMBeanInstance.java	11 Aug 2003 17:59:10 -0000	1.1
  +++ UnregisterMBeanInstance.java	14 Aug 2003 00:02:38 -0000	1.2
  @@ -67,13 +67,17 @@
    *
    * @version $Revision$ $Date$
    */
  -public class UnregisterMBeanInstance extends DeploymentTask {
  +public class UnregisterMBeanInstance implements DeploymentTask {
       private final MBeanServer server;
       private final ObjectName name;
   
       public UnregisterMBeanInstance(MBeanServer server, ObjectName name) {
           this.server = server;
           this.name = name;
  +    }
  +
  +    public boolean canRun() throws DeploymentException {
  +        return true;
       }
   
       public void perform() throws DeploymentException {
  
  
  
  1.2       +6 -2      incubator-geronimo/modules/core/src/java/org/apache/geronimo/deployment/plan/CreateClassSpace.java
  
  Index: CreateClassSpace.java
  ===================================================================
  RCS file: /home/cvs/incubator-geronimo/modules/core/src/java/org/apache/geronimo/deployment/plan/CreateClassSpace.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- CreateClassSpace.java	11 Aug 2003 17:59:10 -0000	1.1
  +++ CreateClassSpace.java	14 Aug 2003 00:02:38 -0000	1.2
  @@ -77,7 +77,7 @@
    *
    * @version $Revision$ $Date$
    */
  -public class CreateClassSpace extends DeploymentTask {
  +public class CreateClassSpace implements DeploymentTask {
       private final Log log = LogFactory.getLog(this.getClass());
       private final MBeanServer server;
       private final ClassSpaceMetadata metadata;
  @@ -86,6 +86,10 @@
       public CreateClassSpace(MBeanServer server, ClassSpaceMetadata metadata) {
           this.server = server;
           this.metadata = metadata;
  +    }
  +
  +    public boolean canRun() throws DeploymentException {
  +        return true;
       }
   
       public void perform() throws DeploymentException {
  
  
  
  1.2       +6 -2      incubator-geronimo/modules/core/src/java/org/apache/geronimo/deployment/plan/StartMBeanInstance.java
  
  Index: StartMBeanInstance.java
  ===================================================================
  RCS file: /home/cvs/incubator-geronimo/modules/core/src/java/org/apache/geronimo/deployment/plan/StartMBeanInstance.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- StartMBeanInstance.java	11 Aug 2003 17:59:10 -0000	1.1
  +++ StartMBeanInstance.java	14 Aug 2003 00:02:38 -0000	1.2
  @@ -68,13 +68,17 @@
    *
    * @version $Revision$ $Date$
    */
  -public class StartMBeanInstance extends DeploymentTask {
  +public class StartMBeanInstance implements DeploymentTask {
       private final MBeanServer server;
       private final ObjectName name;
   
       public StartMBeanInstance(MBeanServer server, ObjectName name) {
           this.server = server;
           this.name = name;
  +    }
  +
  +    public boolean canRun() throws DeploymentException {
  +        return true;
       }
   
       public void perform() throws DeploymentException {
  
  
  
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/deployment/plan/InitializeMBeanInstance.java
  
  Index: InitializeMBeanInstance.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Geronimo", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * ====================================================================
   */
  package org.apache.geronimo.deployment.plan;
  
  import java.beans.PropertyEditor;
  import java.beans.PropertyEditorManager;
  import java.lang.reflect.Constructor;
  import java.util.Collections;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Set;
  import javax.management.InstanceNotFoundException;
  import javax.management.MBeanException;
  import javax.management.MBeanRegistrationException;
  import javax.management.MBeanServer;
  import javax.management.MalformedObjectNameException;
  import javax.management.ObjectName;
  import javax.management.ReflectionException;
  import javax.management.relation.RelationServiceMBean;
  import javax.management.relation.Role;
  import javax.management.relation.RoleInfo;
  import javax.management.relation.RoleList;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.apache.geronimo.core.util.ClassUtil;
  import org.apache.geronimo.deployment.DeploymentException;
  import org.apache.geronimo.deployment.service.MBeanMetadata;
  import org.apache.geronimo.deployment.service.MBeanOperation;
  import org.apache.geronimo.deployment.service.MBeanRelationship;
  import org.apache.geronimo.jmx.JMXUtil;
  
  /**
   *
   *
   * @version $Revision: 1.1 $ $Date: 2003/08/14 00:02:38 $
   */
  public class InitializeMBeanInstance implements DeploymentTask {
      private final Log log = LogFactory.getLog(this.getClass());
      private final Set plans;
      private final MBeanServer server;
      private final RelationServiceMBean relationService;
      private final ObjectName parent;
      private final ObjectName loaderName;
      private final MBeanMetadata metadata;
      private ObjectName objectName;
      private boolean createCalled;
  
      public InitializeMBeanInstance(Set plans, MBeanServer server, ObjectName objectName, ObjectName parent, MBeanMetadata metadata, ObjectName loaderName) {
          this.plans = plans;
          this.server = server;
          this.objectName = objectName;
          this.parent = parent;
          this.metadata = metadata;
          this.loaderName = loaderName;
          relationService = JMXUtil.getRelationService(server);
      }
  
      public boolean canRun() throws DeploymentException {
          boolean canRun = true;
  
          if (!server.isRegistered(objectName)) {
              log.trace("Plan can run because MBean has been unregistered.  Plan will execute but will do nothing");
              return true;
          }
  
          Set relationships = metadata.getRelationships();
          for (Iterator i = relationships.iterator(); i.hasNext();) {
              MBeanRelationship relationship = (MBeanRelationship) i.next();
  
              // if there is no existing relationship...
              String relationshipName = relationship.getName();
              if (!relationService.hasRelation(relationshipName).booleanValue()) {
                  // check if the relationship type has been registered
                  String relationshipType = relationship.getType();
                  if (!relationService.getAllRelationTypeNames().contains(relationshipType)) {
                      log.trace("Cannot run because relationship type is not registered: relationType=" + relationshipType);
                      canRun = false;
                  }
  
                  // if we have a target, check that is is registered
                  String target = relationship.getTarget();
                  if (target != null && target.length() > 0) {
                      try {
                          if (!server.isRegistered(new ObjectName(target))) {
                              log.trace("Cannot run because relationship target object is not registered: target=" + target);
                              canRun = false;
                          }
                      } catch (MalformedObjectNameException e) {
                          throw new DeploymentException("Target is not a valid ObjectName: target=" + target);
                      }
                  }
              }
          }
          return canRun;
      }
  
      public void perform() throws DeploymentException {
          if (!server.isRegistered(objectName)) {
              return;
          }
  
          ClassLoader oldCL = Thread.currentThread().getContextClassLoader();
          ClassLoader newCL;
  
          // create an MBean instance
          try {
              // Get the class loader
              try {
                  newCL = server.getClassLoader(loaderName);
                  Thread.currentThread().setContextClassLoader(newCL);
              } catch (InstanceNotFoundException e) {
                  throw new DeploymentException(e);
              }
  
  
              // Resolve and enroll in all relationships
              Set relationships = metadata.getRelationships();
              try {
                  for (Iterator i = relationships.iterator(); i.hasNext();) {
                      MBeanRelationship relationship = (MBeanRelationship) i.next();
  
                      // if we don't have a relationship instance create one
                      String relationshipName = relationship.getName();
                      String relationshipRole = relationship.getRole();
                      if (!relationService.hasRelation(relationshipName).booleanValue()) {
                          // if  we don't have a relationship of the
                          String relationshipType = relationship.getType();
                          if (!relationService.getAllRelationTypeNames().contains(relationshipType)) {
                              throw new DeploymentException("Relationship type is not registered: relationType=" + relationshipType);
                          }
  
                          RoleList roleList = new RoleList();
                          roleList.add(new Role(relationshipRole, Collections.singletonList(objectName)));
  
                          // if we have a target we need to add it to the role list
                          String target = relationship.getTarget();
                          if (target != null && target.length() > 0) {
                              String targetRoleName = relationship.getTargetRole();
                              if (targetRoleName == null || targetRoleName.length() == 0) {
                                  List roles = relationService.getRoleInfos(relationshipType);
                                  if (roles.size() < 2) {
                                      throw new DeploymentException("Relationship has less than two roles. You cannot specify a target");
                                  }
                                  if (roles.size() > 2) {
                                      throw new DeploymentException("Relationship has more than two roles. You must use targetRoleName");
                                  }
                                  if (((RoleInfo) roles.get(0)).getName().equals(relationshipRole)) {
                                      targetRoleName = ((RoleInfo) roles.get(1)).getName();
                                  } else {
                                      targetRoleName = ((RoleInfo) roles.get(0)).getName();
                                  }
                              }
  
                              roleList.add(new Role(targetRoleName, Collections.singletonList(new ObjectName(target))));
                          }
                          relationService.createRelation(relationshipName, relationshipType, roleList);
                      } else {
                          // We have an exiting relationship -- just add to the existing role
                          List members = relationService.getRole(relationshipName, relationshipRole);
                          members.add(objectName);
                          relationService.setRole(relationshipName, new Role(relationshipRole, members));
                      }
                  }
              } catch (DeploymentException e) {
                  throw e;
              } catch (Exception e) {
                  throw new DeploymentException(e);
              }
  
              // Invoke the create callback method
              try {
                  server.invoke(objectName, "create", null, null);
                  createCalled = true;
              } catch (RuntimeException e) {
                  throw new DeploymentException(e);
              } catch (InstanceNotFoundException e) {
                  throw new DeploymentException(e);
              } catch (MBeanException e) {
                  throw new DeploymentException(e);
              } catch (ReflectionException e) {
                  if (e.getTargetException() instanceof NoSuchMethodException) {
                      // did not have a create method - ok
                  } else {
                      throw new DeploymentException(e);
                  }
              }
  
              // Add a deployment plan to start the MBean
              DeploymentPlan startPlan = new DeploymentPlan();
              startPlan.addTask(new StartMBeanInstance(server, objectName));
              List operations = metadata.getOperations();
              for (Iterator i = operations.iterator(); i.hasNext();) {
                  MBeanOperation operation = (MBeanOperation) i.next();
                  int argCount = operation.getTypes().size();
                  String[] argTypes = (String[]) operation.getTypes().toArray(new String[argCount]);
                  List values = operation.getArgs();
                  Object[] args = new Object[argCount];
                  for (int j = 0; j < argCount; j++) {
                      Object value = values.get(j);
                      if (value instanceof String) {
                          value = getValue(newCL, argTypes[j], (String) value);
                      }
                      args[j] = value;
                  }
                  startPlan.addTask(new InvokeMBeanOperation(server, objectName, operation.getOperation(), argTypes, args));
              }
              plans.add(startPlan);
          } catch (DeploymentException e) {
              undo();
              throw e;
          } finally {
              Thread.currentThread().setContextClassLoader(oldCL);
          }
      }
  
      public void undo() {
          if (objectName == null) {
              return;
          }
  
          try {
              if (createCalled) {
                  server.invoke(objectName, "destroy", null, null);
              }
          } catch (InstanceNotFoundException e) {
              log.warn("MBean was already removed " + objectName, e);
              return;
          } catch (MBeanException e) {
              log.error("Error while destroying MBean " + objectName, e);
          } catch (ReflectionException e) {
              if (e.getTargetException() instanceof NoSuchMethodException) {
                  // did not have a destroy method - ok
              } else {
                  log.error("Error while destroying MBean " + objectName, e);
              }
          }
  
          try {
              server.invoke(parent, "removeChild", new Object[]{objectName}, new String[]{"javax.management.ObjectName"});
          } catch (InstanceNotFoundException e) {
              log.warn("Could not remove from parent", e);
          } catch (MBeanException e) {
              log.error("Error while removing MBean " + objectName + " from parent", e);
          } catch (ReflectionException e) {
              log.error("Error while removing MBean " + objectName + " from parent", e);
          }
  
          try {
              server.unregisterMBean(objectName);
          } catch (InstanceNotFoundException e) {
              log.warn("MBean was already removed " + objectName, e);
              return;
          } catch (MBeanRegistrationException e) {
              log.error("Error while unregistering MBean " + objectName, e);
          }
      }
  
      private static final Class[] stringArg = new Class[]{String.class};
  
      private Object getValue(ClassLoader cl, String typeName, String value) throws DeploymentException {
          Class attrType = null;
          try {
              attrType = ClassUtil.getClassForName(cl, typeName);
          } catch (ClassNotFoundException e) {
              throw new DeploymentException(e);
          }
  
          // try a property editor
          PropertyEditor editor = PropertyEditorManager.findEditor(attrType);
          if (editor != null) {
              editor.setAsText(value);
              return editor.getValue();
          }
  
          // try a String constructor
          try {
              Constructor cons = attrType.getConstructor(stringArg);
              return cons.newInstance(new Object[]{value});
          } catch (Exception e) {
              throw new DeploymentException("Could not create value of type " + typeName);
          }
      }
  
      public String toString() {
          return "InitailizeMBeanInstance " + metadata.getName();
      }
  }