0001: /*
0002: * BEGIN_HEADER - DO NOT EDIT
0003: *
0004: * The contents of this file are subject to the terms
0005: * of the Common Development and Distribution License
0006: * (the "License"). You may not use this file except
0007: * in compliance with the License.
0008: *
0009: * You can obtain a copy of the license at
0010: * https://open-esb.dev.java.net/public/CDDLv1.0.html.
0011: * See the License for the specific language governing
0012: * permissions and limitations under the License.
0013: *
0014: * When distributing Covered Code, include this CDDL
0015: * HEADER in each file and include the License file at
0016: * https://open-esb.dev.java.net/public/CDDLv1.0.html.
0017: * If applicable add the following below this CDDL HEADER,
0018: * with the fields enclosed by brackets "[]" replaced with
0019: * your own identifying information: Portions Copyright
0020: * [year] [name of copyright owner]
0021: */
0022:
0023: /*
0024: * @(#)ComponentFramework.java
0025: * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
0026: *
0027: * END_HEADER - DO NOT EDIT
0028: */
0029: package com.sun.jbi.framework;
0030:
0031: import com.sun.jbi.ComponentState;
0032: import com.sun.jbi.ComponentInfo;
0033: import com.sun.jbi.ServiceUnitInfo;
0034: import com.sun.jbi.ServiceUnitState;
0035: import com.sun.jbi.framework.DeployerMBean;
0036: import com.sun.jbi.component.InstallationContext;
0037: import com.sun.jbi.framework.ComponentLifeCycleMBean;
0038: import com.sun.jbi.management.MBeanNames;
0039: import com.sun.jbi.management.registry.Updater;
0040: import com.sun.jbi.messaging.MessageService;
0041:
0042: import java.io.File;
0043: import java.io.InputStream;
0044:
0045: import java.util.ArrayList;
0046: import java.util.Date;
0047: import java.util.HashMap;
0048: import java.util.Iterator;
0049: import java.util.List;
0050: import java.util.ListIterator;
0051: import java.util.Map;
0052: import java.util.logging.Level;
0053: import java.util.logging.Logger;
0054:
0055: import javax.jbi.component.Bootstrap;
0056:
0057: import javax.management.MBeanServer;
0058: import javax.management.ObjectName;
0059: import javax.management.StandardMBean;
0060:
0061: /**
0062: * This is the implementation of the Component Framework, which provides
0063: * for the installation, uninstallation, and runtime management of Binding
0064: * Components, Service Engines, and Shared Libraries within the JBI framework.
0065: *
0066: * @author Sun Microsystems, Inc.
0067: */
0068: public class ComponentFramework implements
0069: com.sun.jbi.ComponentManager, com.sun.jbi.ServiceLifecycle {
0070: /**
0071: * Local handle to EnvironmentContext
0072: */
0073: private EnvironmentContext mContext;
0074:
0075: /**
0076: * Local handle to ClassLoaderFactory
0077: */
0078: private ClassLoaderFactory mClassLoaderFactory;
0079:
0080: /**
0081: * Local handle to ComponentRegistry
0082: */
0083: private ComponentRegistry mCompReg;
0084:
0085: /**
0086: * Local handle to ServiceUnitFramework
0087: */
0088: private ServiceUnitFramework mSUFramework;
0089:
0090: /**
0091: * Local handle to Logger
0092: */
0093: private Logger mLog;
0094:
0095: /**
0096: * Local flag for start/stop checking
0097: */
0098: private Boolean mStarted = null;
0099:
0100: /**
0101: * Startup type for component processing at service startup. Defaults to
0102: * "AUTO".
0103: */
0104: private int mStartup = STARTUP_AUTO;
0105:
0106: /**
0107: * Local handle to StringTranslator
0108: */
0109: private StringTranslator mTranslator;
0110:
0111: /**
0112: * Local handle to registry updater.
0113: */
0114: private Updater mUpdater;
0115:
0116: /**
0117: * Localized string "Binding"
0118: */
0119: private String mBinding;
0120:
0121: /**
0122: * Localized string "component"
0123: */
0124: private String mComponent;
0125:
0126: /**
0127: * Localized string "Engine"
0128: */
0129: private String mEngine;
0130:
0131: /**
0132: * Last known state.
0133: */
0134: private int mStartupState;
0135:
0136: /**
0137: * Startup type for auto startup of all installed components.
0138: */
0139: public static final int STARTUP_ALL = 0;
0140:
0141: /**
0142: * Startup type for auto startup of installed components that were
0143: * running at the time of the last shutdown.
0144: */
0145: public static final int STARTUP_AUTO = 1;
0146:
0147: /**
0148: * Startup type for no startup of components.
0149: */
0150: public static final int STARTUP_NONE = 2;
0151:
0152: /**
0153: * Commands for startupAll()
0154: */
0155: public static final int PREPARE = 1;
0156: public static final int START = 2;
0157:
0158: /**
0159: * Startup value for auto startup of all installed components.
0160: */
0161: private static final String STARTUP_ALL_STR = "ALL";
0162:
0163: /**
0164: * Startup value for auto startup of installed components that were
0165: * running at the time of the last shutdown.
0166: */
0167: private static final String STARTUP_AUTO_STR = "AUTO";
0168:
0169: /**
0170: * Startup value for no startup of components.
0171: */
0172: private static final String STARTUP_NONE_STR = "NONE";
0173:
0174: /**
0175: * Property key for component startup options.
0176: */
0177: private static final String STARTUP_PROPERTY = "com.sun.jbi.framework.ComponentStartup";
0178:
0179: /**
0180: * Default timeout interval for component startup and shutdown. The
0181: * value is in milliseconds and is set to 4 minutes.
0182: */
0183: private static final long TIMEOUT_DEFAULT = 240000;
0184:
0185: /**
0186: * XML tag for the component logger section in the installation descriptor
0187: * extension.
0188: */
0189: private static final String TAG_LOGGING_SECTION = "logging:Logging";
0190:
0191: /**
0192: * XML tag for the root attribute of the component logger section in the
0193: * installation descriptor extension.
0194: */
0195: private static final String TAG_LOGGING_ROOT = "root";
0196:
0197: /**
0198: * XML tag for a component logger definition in the component logger section
0199: * of the installation descriptor extension.
0200: */
0201: private static final String TAG_LOGGER_DEFINITION = "logging:logger";
0202:
0203: /**
0204: * XML tag for the displayName attribute of a component logger definition in
0205: * the component logger section of the installation descriptor extension.
0206: */
0207: private static final String TAG_DISPLAY_NAME = "displayName";
0208:
0209: /**
0210: * XML tag for the addPrefix attribute of a component logger definition in
0211: * the component logger section of the installation descriptor extension.
0212: */
0213: private static final String TAG_ADD_PREFIX = "addPrefix";
0214:
0215: // ------------------------- ServiceLifecycle methods -------------------------
0216:
0217: /**
0218: * Initialize the Component Framework service.
0219: * @param context The JBI environment context created by the JBI framework.
0220: * @throws javax.jbi.JBIException If an error occurs during initialization.
0221: */
0222: public void initService(com.sun.jbi.EnvironmentContext context)
0223: throws javax.jbi.JBIException {
0224: if (null != mStarted) {
0225: throw new java.lang.IllegalStateException(
0226: mTranslator
0227: .getString(
0228: LocalStringKeys.SERVICE_ALREADY_INITIALIZED,
0229: mTranslator
0230: .getString(LocalStringKeys.CF_NAME)));
0231: }
0232: mContext = (EnvironmentContext) context;
0233: mCompReg = (ComponentRegistry) mContext.getComponentRegistry();
0234: mClassLoaderFactory = ClassLoaderFactory.getInstance();
0235: mSUFramework = new ServiceUnitFramework(mContext);
0236: mLog = mContext.getLogger();
0237: mTranslator = (StringTranslator) mContext
0238: .getStringTranslatorFor(this );
0239: mBinding = mTranslator.getString(LocalStringKeys.BINDING);
0240: mComponent = mTranslator.getString(LocalStringKeys.COMPONENT);
0241: mEngine = mTranslator.getString(LocalStringKeys.ENGINE);
0242:
0243: String startup = mContext.getInitialProperties().getProperty(
0244: STARTUP_PROPERTY);
0245: if (null != startup) {
0246: if (startup.equalsIgnoreCase(STARTUP_ALL_STR)) {
0247: mStartup = STARTUP_ALL;
0248: } else if (startup.equalsIgnoreCase(STARTUP_AUTO_STR)) {
0249: mStartup = STARTUP_AUTO;
0250: } else if (startup.equalsIgnoreCase(STARTUP_NONE_STR)) {
0251: mStartup = STARTUP_NONE;
0252: } else {
0253: mLog.warning(mTranslator.getString(
0254: LocalStringKeys.CF_INVALID_STARTUP_PROPERTY,
0255: startup, STARTUP_PROPERTY, STARTUP_ALL_STR));
0256: }
0257: }
0258: mStarted = mStarted.FALSE;
0259: mLog.fine(mTranslator.getString(
0260: LocalStringKeys.SERVICE_INITIALIZED, mTranslator
0261: .getString(LocalStringKeys.CF_NAME)));
0262: }
0263:
0264: /**
0265: * Start the Component Framework service.
0266: * @throws javax.jbi.JBIException If an error occurs starting the service.
0267: */
0268: public void startService() throws javax.jbi.JBIException {
0269: if (mStarted.booleanValue()) {
0270: throw new java.lang.IllegalStateException(
0271: mTranslator
0272: .getString(
0273: LocalStringKeys.SERVICE_ALREADY_STARTED,
0274: mTranslator
0275: .getString(LocalStringKeys.CR_NAME)));
0276: }
0277:
0278: // Indicate that the Component Framework is now stared.
0279:
0280: mStarted = mStarted.TRUE;
0281:
0282: mLog.fine(mTranslator.getString(
0283: LocalStringKeys.SERVICE_STARTED, mTranslator
0284: .getString(LocalStringKeys.CF_NAME)));
0285: }
0286:
0287: /**
0288: * Stop the Component Framework service. All BCs and SEs that are still
0289: * started are stopped and shut down here.
0290: * @throws javax.jbi.JBIException If an error occurs stopping the service.
0291: */
0292: public void stopService() throws javax.jbi.JBIException {
0293: if (!mStarted.booleanValue()) {
0294: mLog.warning(mTranslator.getString(
0295: LocalStringKeys.SERVICE_ALREADY_STOPPED,
0296: mTranslator.getString(LocalStringKeys.CF_NAME)));
0297: return;
0298: }
0299: mStarted = mStarted.FALSE;
0300: long timeOut = mContext.getComponentTimeout();
0301:
0302: // Get a list of all installed bindings and engines and shut them down.
0303:
0304: List comps = mCompReg.getAllComponents();
0305: ListIterator c = comps.listIterator();
0306: Component comp = null;
0307: mLog.fine(mTranslator
0308: .getString(LocalStringKeys.CF_STOPPING_ALL));
0309: ArrayList shutdowns = new ArrayList();
0310: ComponentOperation shutdown;
0311: OperationCounter oc = new OperationCounter();
0312: while (c.hasNext()) {
0313: comp = (Component) c.next();
0314: if (comp.isStarted() || comp.isStopped()) {
0315: shutdown = new ComponentOperation(oc, comp,
0316: ComponentOperation.SHUTDOWN);
0317: shutdowns.add(shutdown);
0318: new Thread(shutdown, comp.getName()).start();
0319: }
0320: }
0321: if (0 < shutdowns.size()) {
0322: synchronized (oc) {
0323: try {
0324: if (0 < oc.getValue()) {
0325: oc.wait(timeOut);
0326: }
0327: } catch (java.lang.InterruptedException iEx) {
0328: mLog
0329: .warning(mTranslator
0330: .getString(LocalStringKeys.CF_SHUTDOWN_INTERRUPTED));
0331: }
0332: }
0333: Iterator shutdownIter = shutdowns.iterator();
0334: while (shutdownIter.hasNext()) {
0335: shutdown = (ComponentOperation) shutdownIter.next();
0336: if (!shutdown.completed()) {
0337: comp = shutdown.getComponent();
0338: shutdown.getThread().interrupt();
0339: mLog.warning(mTranslator.getString(
0340: LocalStringKeys.CF_COMP_SHUTDOWN_TIMEOUT,
0341: comp.getComponentTypeAsString(), comp
0342: .getName(), new Long(timeOut)));
0343: }
0344: }
0345: }
0346:
0347: mLog.fine(mTranslator.getString(
0348: LocalStringKeys.SERVICE_STOPPED, mTranslator
0349: .getString(LocalStringKeys.CF_NAME)));
0350: }
0351:
0352: // ---------------------------- Public IPI methods ----------------------------
0353:
0354: /**
0355: * Get the instance of javax.jbi.component.Component for the specified
0356: * component, if it exists.
0357: * @param componentName the unique name of the component.
0358: * @return the javax.jbi.component.Component instance or null if no such
0359: * component exists or if the component is inactive.
0360: */
0361: public javax.jbi.component.Component getComponentInstance(
0362: String componentName) {
0363: Component comp = mCompReg.getComponent(componentName);
0364: if (null != comp) {
0365: return comp.getComponentInstance();
0366: } else {
0367: return null;
0368: }
0369: }
0370:
0371: /**
0372: * Get the instance of com.sun.jbi.framework.DeployerMBean for the specified
0373: * component, if it exists.
0374: * @param componentName the unique name of the component.
0375: * @return the com.sun.jbi.framework.DeployerMBean instance or null if no
0376: * such component exists or if the component has no Deployer instance.
0377: */
0378: public DeployerMBean getDeployerInstance(String componentName) {
0379: DeployerMBean deployer = null;
0380: Component comp = mCompReg.getComponent(componentName);
0381: if (null != comp) {
0382: deployer = comp.getDeployerInstance();
0383: }
0384: return deployer;
0385: }
0386:
0387: /**
0388: * Install a Shared Library into the JBI framework.
0389: * @param name The unique name assigned to this Shared Library.
0390: * @param description The description of the Shared Library.
0391: * @param componentRoot The root directory for the Shared Library.
0392: * @param isSelfFirst Set to true to force the class loader for this Shared
0393: * Library to use a self-first hierarchy, or false for parent-first.
0394: * @param elements The list of jar and class files included in this
0395: * Shared Library, in a List of Strings in the order in which they
0396: * should appear in the class path.
0397: * @throws javax.jbi.JBIException If the installation fails.
0398: */
0399: public synchronized void installSharedLibrary(String name,
0400: String description, String componentRoot,
0401: boolean isSelfFirst, List elements)
0402: throws javax.jbi.JBIException {
0403: // Check the parameters for validity. All parameters are required
0404: // and values must not be null.
0405:
0406: if (null == name) {
0407: throw new java.lang.IllegalArgumentException(mTranslator
0408: .getString(LocalStringKeys.NULL_ARGUMENT, "name"));
0409: }
0410:
0411: if (0 == name.length()) {
0412: throw new java.lang.IllegalArgumentException(mTranslator
0413: .getString(LocalStringKeys.EMPTY_STRING_ARGUMENT,
0414: "name"));
0415: }
0416:
0417: if (null == componentRoot) {
0418: throw new java.lang.IllegalArgumentException(mTranslator
0419: .getString(LocalStringKeys.NULL_ARGUMENT,
0420: "componentRoot"));
0421: }
0422:
0423: if (0 == componentRoot.length()) {
0424: throw new java.lang.IllegalArgumentException(mTranslator
0425: .getString(LocalStringKeys.EMPTY_STRING_ARGUMENT,
0426: "componentRoot"));
0427: }
0428:
0429: if (null == elements) {
0430: throw new java.lang.IllegalArgumentException(mTranslator
0431: .getString(LocalStringKeys.NULL_ARGUMENT,
0432: "elements"));
0433: }
0434:
0435: if (0 == elements.size()) {
0436: throw new java.lang.IllegalArgumentException(mTranslator
0437: .getString(LocalStringKeys.EMPTY_LIST_ARGUMENT,
0438: "elements"));
0439: }
0440:
0441: // Be sure that there is not already a Shared Library registered with
0442: // the same name.
0443:
0444: if (mCompReg.isSharedLibraryRegistered(name)) {
0445: throw new javax.jbi.JBIException(mTranslator.getString(
0446: LocalStringKeys.CF_SL_ALREADY_REGISTERED, name));
0447: }
0448:
0449: // Create a new SharedLibrary instance.
0450:
0451: SharedLibrary sl = new SharedLibrary(name, description,
0452: componentRoot, isSelfFirst, elements);
0453:
0454: // Create the shared class loader for this Shared Library
0455: try {
0456: mClassLoaderFactory.createSharedClassLoader(sl);
0457: mLog.fine("Created class loader for Shared Library " + name
0458: + " with class path " + sl.getClassPathAsString());
0459: } catch (javax.jbi.JBIException jbiEx) {
0460: throw new javax.jbi.JBIException(mTranslator.getString(
0461: LocalStringKeys.CF_SL_INSTALL_FAILED, name), jbiEx);
0462: }
0463:
0464: // Register the Shared Library
0465: mCompReg.registerSharedLibrary(sl);
0466:
0467: String installMsg = mTranslator.getString(
0468: LocalStringKeys.CF_SL_INSTALL_SUCCESSFUL, name);
0469: mLog.info(installMsg);
0470:
0471: // Send an MBean notification that the install has completed.
0472: mContext.getNotifier().emitComponentNotification(
0473: EventNotifier.EventType.Installed,
0474: EventNotifier.SourceType.SharedLibrary, name,
0475: installMsg);
0476: }
0477:
0478: /**
0479: * Load a component's bootstrap into the JBI framework. This is the first
0480: * step in the installation and uninstallation processes. It creates and
0481: * registers the ComponentInstaller MBean that is used to complete the
0482: * installation or uninstallation.
0483: * @param installContext The InstallationContext created by the Installer
0484: * Service.
0485: * @param bootClassName The name of the bootstrap class for the component.
0486: * @param bootClassPathElements A List of elements comprising the
0487: * class path for loading the bootstrap class. Each element is a String
0488: * containing the full path to either a jar file or a directory containing
0489: * class files.
0490: * @param sharedLibraryNames A List of String objects containing the names
0491: * of the Shared Libraries required by the component.
0492: * @return The MBean object name of an installation configuration MBean or
0493: * null if the component didn't provide one.
0494: * @throws javax.jbi.JBIException If the component's bootstrap cannot be
0495: * loaded.
0496: */
0497: public synchronized ObjectName loadBootstrap(
0498: InstallationContext installContext, String bootClassName,
0499: List bootClassPathElements, List sharedLibraryNames)
0500: throws javax.jbi.JBIException {
0501: // Check the parameters for validity. All parameters are required
0502: // and values must not be null. The installContext must contain
0503: // valid information.
0504:
0505: if (null == installContext) {
0506: throw new java.lang.IllegalArgumentException(mTranslator
0507: .getString(LocalStringKeys.NULL_ARGUMENT,
0508: "installContext"));
0509: }
0510: if (null == bootClassName) {
0511: throw new java.lang.IllegalArgumentException(mTranslator
0512: .getString(LocalStringKeys.NULL_ARGUMENT,
0513: "bootClassName"));
0514: }
0515: if (null == bootClassPathElements) {
0516: throw new java.lang.IllegalArgumentException(mTranslator
0517: .getString(LocalStringKeys.NULL_ARGUMENT,
0518: "bootClassPathElements"));
0519: }
0520: if (0 == bootClassName.length()) {
0521: throw new java.lang.IllegalArgumentException(mTranslator
0522: .getString(LocalStringKeys.EMPTY_STRING_ARGUMENT,
0523: "bootClassName"));
0524: }
0525: if (0 == bootClassPathElements.size()) {
0526: throw new java.lang.IllegalArgumentException(mTranslator
0527: .getString(LocalStringKeys.EMPTY_LIST_ARGUMENT,
0528: "bootClassPathElements"));
0529: }
0530:
0531: String msg = null;
0532: String componentName = installContext.getComponentName();
0533: String componentType = installContext.isBinding() ? mBinding
0534: : mEngine;
0535:
0536: mLog.fine("Loading bootstrap for " + componentType + " "
0537: + componentName);
0538:
0539: // Get the Component represented by the component name from the registry
0540: // if it exists. The registry returns null if there is none.
0541:
0542: Component comp = mCompReg.getComponent(componentName);
0543: boolean existed = false;
0544:
0545: if (installContext.isInstall()) {
0546: msg = mTranslator.getString(
0547: LocalStringKeys.CF_COMP_INSTALL_FAILED,
0548: componentType, componentName)
0549: + " ";
0550:
0551: // This is an installation. If no Component instance exists, create
0552: // a new one. If a Component instance exists and is in any state
0553: // other than LOADED, abort the installation.
0554:
0555: if (null == comp) {
0556: comp = new Component();
0557: } else if (!comp.isLoaded()) {
0558: throw new javax.jbi.JBIException(
0559: msg
0560: + mTranslator
0561: .getString(
0562: LocalStringKeys.CF_COMP_ALREADY_REGISTERED,
0563: comp
0564: .getComponentTypeAsString()));
0565: } else {
0566: existed = true;
0567: comp.clearBootstrapInstance();
0568: comp.clearLifeCycleInstance();
0569: }
0570:
0571: // Initialize the Component instance for this component.
0572:
0573: initComponent(comp, installContext, bootClassName,
0574: bootClassPathElements, sharedLibraryNames);
0575:
0576: // Check for required Shared Libraries. If any of them are not
0577: // installed, abort the installation.
0578:
0579: checkSharedLibraries(comp);
0580: } else {
0581: msg = mTranslator.getString(
0582: LocalStringKeys.CF_COMP_UNINSTALL_FAILED,
0583: componentType, componentName)
0584: + " ";
0585:
0586: // This is an uninstall. Verify that the component is installed.
0587:
0588: if (null == comp || comp.isLoaded()) {
0589: throw new javax.jbi.JBIException(
0590: msg
0591: + mTranslator
0592: .getString(LocalStringKeys.CF_COMP_NOT_INSTALLED));
0593: }
0594: }
0595:
0596: // Load and initialize the bootstrap instance, and register the
0597: // InstallerMBean for it.
0598:
0599: ObjectName instMBeanName = initBootstrap(comp, msg,
0600: installContext);
0601:
0602: // For an installation, the component must be registered to prevent
0603: // another installation from attempting to install another component
0604: // with the same component name.
0605:
0606: if (installContext.isInstall()) {
0607: if (!existed) {
0608: mCompReg.registerComponent(comp);
0609: }
0610: }
0611:
0612: mLog.fine("Bootstrap for " + componentType + " "
0613: + componentName + " has been loaded");
0614: return instMBeanName;
0615: }
0616:
0617: /**
0618: * Uninstall a Shared Library from the JBI framework. A Shared Library
0619: * cannot be uninstalled until all dependent components have been shut down.
0620: * If any running dependent components are found, the uninstall of the
0621: * Shared Library is aborted.
0622: * @param sharedLibraryName The unique name of the Shared Library.
0623: * @throws javax.jbi.JBIException If the uninstall fails or is denied.
0624: */
0625: public void uninstallSharedLibrary(String sharedLibraryName)
0626: throws javax.jbi.JBIException {
0627: // Be sure that there is a Shared Library registered with this name.
0628:
0629: SharedLibrary sl = mCompReg.getSharedLibrary(sharedLibraryName);
0630: if (null == sl) {
0631: throw new javax.jbi.JBIException(mTranslator.getString(
0632: LocalStringKeys.CF_SL_UNINSTALL_NONEXISTENT,
0633: sharedLibraryName));
0634: }
0635:
0636: // First check to be sure there are no running components that
0637: // reference this Shared Library. If any are found, abort the
0638: // uninstall. The string returned by checkForActiveDependents()
0639: // is used only when there are no running components that reference
0640: // this Shared Library, for providing a list of components that
0641: // cannot be started until this Shared Library is reinstalled.
0642:
0643: String dependents;
0644: try {
0645: dependents = checkForActiveDependents(sharedLibraryName);
0646: } catch (javax.jbi.JBIException ex) {
0647: throw new javax.jbi.JBIException(mTranslator.getString(
0648: LocalStringKeys.CF_SL_UNINSTALL_FAILED_DEPENDENTS,
0649: sharedLibraryName), ex);
0650: }
0651:
0652: // Destroy the class loader for this Shared Library.
0653:
0654: try {
0655: mClassLoaderFactory
0656: .removeSharedClassLoader(sharedLibraryName);
0657: } catch (javax.jbi.JBIException ex) {
0658: // This only happens if the class loader did not exist, and
0659: // can be ignored during uninstall. Just log the error.
0660:
0661: mLog.info(mTranslator.getString(
0662: LocalStringKeys.CF_SL_UNINSTALL_CLASSLOADER, ex
0663: .toString()));
0664: }
0665:
0666: // Remove this Shared Library from the registry.
0667:
0668: mCompReg.unregisterSharedLibrary(sharedLibraryName);
0669:
0670: // Construct an appropriate messaage based on whether or not there are
0671: // dependent components. Log the message and send an MBean notification
0672: // of the event.
0673: String uninstallMsg;
0674: if (dependents.length() > 0) {
0675: uninstallMsg = mTranslator.getString(
0676: LocalStringKeys.CF_SL_UNINSTALL_OK_DEPENDENTS,
0677: sharedLibraryName, dependents);
0678: } else {
0679: uninstallMsg = mTranslator.getString(
0680: LocalStringKeys.CF_SL_UNINSTALL_SUCCESSFUL,
0681: sharedLibraryName);
0682: }
0683: mLog.info(uninstallMsg);
0684: mContext.getNotifier().emitComponentNotification(
0685: EventNotifier.EventType.Uninstalled,
0686: EventNotifier.SourceType.SharedLibrary,
0687: sharedLibraryName, uninstallMsg);
0688:
0689: // If there are any components installed that require this Shared
0690: // Library, throw a warning exception to inform the user.
0691:
0692: if (dependents.length() > 0) {
0693: throw new com.sun.jbi.framework.FrameworkWarningException(
0694: uninstallMsg);
0695: }
0696: }
0697:
0698: /**
0699: * Unload a component's bootstrap from the JBI framework. This is the last
0700: * step in the installation and uninstallation processes. It unregisters
0701: * the InstallerMBean that was used to complete the installation or
0702: * uninstallation, and calls the bootstrap cleanUp() method if it has not
0703: * yet been called. Note that in the case where this method is called
0704: * after loadBootstrap() for a new component, without an intervening call to
0705: * installComponent(), the Component instance is removed here.
0706: * @param componentName The unique name of the component.
0707: * @throws javax.jbi.JBIException if the bootstrap cannot be unloaded.
0708: */
0709: public void unloadBootstrap(String componentName)
0710: throws javax.jbi.JBIException {
0711: if (null == componentName) {
0712: throw new java.lang.IllegalArgumentException(mTranslator
0713: .getString(LocalStringKeys.NULL_ARGUMENT,
0714: "componentName"));
0715: }
0716: if (0 == componentName.length()) {
0717: throw new java.lang.IllegalArgumentException(mTranslator
0718: .getString(LocalStringKeys.EMPTY_STRING_ARGUMENT,
0719: "componentName"));
0720: }
0721:
0722: // Get the Component instance for this component. If none exists,
0723: // there is nothing to do here, as this means that uninstallComponent()
0724: // completed and cleaned up everything.
0725:
0726: Component comp = mCompReg.getComponent(componentName);
0727: if (null == comp) {
0728: mLog
0729: .finer("Component "
0730: + componentName
0731: + " is not present in the component cache, nothing to unload");
0732: return;
0733: }
0734:
0735: // Unregister the InstallerMBean for this component, if one is still
0736: // registered. Any failure is logged but doesn't throw an exception.
0737:
0738: MBeanServer mbs = mContext.getMBeanServer();
0739: ObjectName instMBeanName = comp.getInstallerMBeanName();
0740: if (null != mbs && null != instMBeanName) {
0741: try {
0742: if (mbs.isRegistered(instMBeanName)) {
0743: mLog.fine("Unregistering installer MBean"
0744: + instMBeanName);
0745: mbs.unregisterMBean(instMBeanName);
0746: comp.setInstallerMBeanName(null);
0747: }
0748: } catch (javax.management.InstanceNotFoundException infEx) {
0749: mLog.warning(infEx.getMessage());
0750: ; // This can be ignored.
0751: } catch (javax.management.MBeanRegistrationException mbrEx) {
0752: mLog.warning(mbrEx.getMessage());
0753: ; // This can be ignored.
0754: }
0755: }
0756:
0757: // Get the bootstrap class instance that was loaded by the
0758: // loadBootstrap() method, if present. If found, and its cleanUp()
0759: // method has not yet been called, call it here.
0760:
0761: Bootstrap bootInstance = comp.getBootstrapInstance(false);
0762:
0763: if (null != bootInstance) {
0764: try {
0765: if (comp.isBootstrapCleanUpNeeded()) {
0766: bootInstance.cleanUp();
0767: }
0768: } catch (Throwable ex) {
0769: String msg = mTranslator
0770: .getString(
0771: LocalStringKeys.CF_BOOTSTRAP_UNLOAD_CLEANUP_FAILED,
0772: comp.getComponentTypeAsString(),
0773: componentName, ex.getClass().getName(),
0774: ex.getMessage());
0775: mLog.warning(msg);
0776: mLog.warning(mTranslator.stackTraceToString(ex));
0777: throw new javax.jbi.JBIException(msg, ex);
0778: } finally {
0779: comp.clearBootstrapInstance();
0780: comp.setBootstrapCleanUpNeeded(false);
0781: }
0782: }
0783:
0784: // If the component is in LOADED state, this means that the component
0785: // is not installed, so the Component instance can be removed from
0786: // the Component Registry.
0787:
0788: if (comp.isLoaded()) {
0789: mCompReg.removeComponent(componentName);
0790: }
0791: }
0792:
0793: /**
0794: * Cancel a pending component upgrade. This is called when some failure
0795: * has occurred after <code>validateComponentForUpgrade()</code> has already
0796: * been called but before <code>upgradeComponent()</code> is called. All
0797: * this method does is return the component to the <code>SHUTDOWN</code>
0798: * state and remove the busy indicator from the component entry in the
0799: * runtime registry cache.
0800: * @param componentName The name of the component.
0801: * @throws javax.jbi.JBIException if the component does not exist.
0802: */
0803: public synchronized void cancelComponentUpgrade(String componentName)
0804: throws javax.jbi.JBIException {
0805: if (null == componentName) {
0806: throw new java.lang.IllegalArgumentException(mTranslator
0807: .getString(LocalStringKeys.NULL_ARGUMENT,
0808: "componentName"));
0809: }
0810: if (0 == componentName.length()) {
0811: throw new java.lang.IllegalArgumentException(mTranslator
0812: .getString(LocalStringKeys.EMPTY_STRING_ARGUMENT,
0813: "componentName"));
0814: }
0815:
0816: Component comp = mCompReg.getComponent(componentName);
0817: if (null == comp) {
0818: throw new javax.jbi.JBIException(mTranslator.getString(
0819: LocalStringKeys.CF_COMP_UPGRADE_CANCEL_NOT_FOUND,
0820: componentName));
0821: }
0822:
0823: // Clear the component busy and component updating indicators.
0824: comp.clearUpdating();
0825: }
0826:
0827: /**
0828: * Upgrade an installed component. This is used to upgrade a component to a
0829: * newer version without requiring the component to be uninstalled (which
0830: * requires undeployment of all Service Assemblies that have Service Units
0831: * deployed to the component). There are two ways a component can be updated.
0832: * If the component does not provide an <code>upgrade()</code> method in its
0833: * bootstrap class, then the runtime jar files are updated and any changes
0834: * to the component's installation descriptor in jbi.xml are propagated. If
0835: * the component provides an <code>upgrade()</code> method, that method is
0836: * called to give the component the opportunity to upgrade its workspace
0837: * and all SUs deployed to it to a new version. In this case, it is the
0838: * responsibility of the component to perform all version verification, and
0839: * to provide any recovery processing required in the event of a failed
0840: * upgrade.
0841: *
0842: * @param installContext The InstallationContext created by the Installer
0843: * Service.
0844: * @param bootClassName The name of the bootstrap class for the component.
0845: * @param bootClassPathElements A List of elements comprising the
0846: * class path for loading the bootstrap class. Each element is a String
0847: * containing the full path to either a jar file or a directory containing
0848: * class files.
0849: * @param sharedLibraryNames A List of String objects containing the names
0850: * of the Shared Libraries required by the component.
0851: * @throws javax.jbi.JBIException if the component cannot be updated for
0852: * any reason.
0853: * @throws javax.jbi.JBIException if the update fails for some reason.
0854: */
0855: public synchronized void upgradeComponent(
0856: InstallationContext installContext, String bootClassName,
0857: List<String> bootClassPathElements,
0858: List<String> sharedLibraryNames)
0859: throws javax.jbi.JBIException {
0860: // Check the parameters for validity. All parameters are required
0861: // and values must not be null.
0862:
0863: if (null == installContext) {
0864: throw new java.lang.IllegalArgumentException(mTranslator
0865: .getString(LocalStringKeys.NULL_ARGUMENT,
0866: "installContext"));
0867: }
0868: if (null == bootClassName) {
0869: throw new java.lang.IllegalArgumentException(mTranslator
0870: .getString(LocalStringKeys.NULL_ARGUMENT,
0871: "bootClassName"));
0872: }
0873: if (null == bootClassPathElements) {
0874: throw new java.lang.IllegalArgumentException(mTranslator
0875: .getString(LocalStringKeys.NULL_ARGUMENT,
0876: "bootClassPathElements"));
0877: }
0878: if (0 == bootClassName.length()) {
0879: throw new java.lang.IllegalArgumentException(mTranslator
0880: .getString(LocalStringKeys.EMPTY_STRING_ARGUMENT,
0881: "bootClassName"));
0882: }
0883: if (0 == bootClassPathElements.size()) {
0884: throw new java.lang.IllegalArgumentException(mTranslator
0885: .getString(LocalStringKeys.EMPTY_LIST_ARGUMENT,
0886: "bootClassPathElements"));
0887: }
0888:
0889: String componentName = installContext.getComponentName();
0890: String componentType = installContext.isBinding() ? mBinding
0891: : mEngine;
0892:
0893: // Get the Component represented by the component name from the registry
0894: // if it exists. The component must already exist in the registry. If it
0895: // is not found, abort the request.
0896:
0897: Component comp = mCompReg.getComponent(componentName);
0898: if (null == comp) {
0899: throw new javax.jbi.JBIException(mTranslator.getString(
0900: LocalStringKeys.CF_COMP_UPGRADE_NOT_FOUND,
0901: componentType, componentName));
0902: }
0903:
0904: // Make sure the component updating flag is set. If it is not, abort
0905: // the update, as this means the component has not been validated for
0906: // update.
0907:
0908: if (!comp.isUpdating()) {
0909: throw new javax.jbi.JBIException(mTranslator.getString(
0910: LocalStringKeys.CF_COMP_UPGRADE_NOT_VALIDATED,
0911: componentType, componentName));
0912: }
0913:
0914: // Create a new Component instance for the upgrade so that if the
0915: // upgrade fails, the existing Component instance can remain unchanged.
0916:
0917: Component newComp = new Component();
0918: initComponent(newComp, installContext, bootClassName,
0919: bootClassPathElements, sharedLibraryNames);
0920: newComp.setUpdating();
0921:
0922: // Verify that all required Shared Libraries are installed.
0923:
0924: checkSharedLibraries(newComp);
0925:
0926: // Load the bootstrap class and call the component's upgrade method
0927: // if it provided one.
0928:
0929: javax.jbi.component.Bootstrap bootInstance;
0930: try {
0931: bootInstance = newComp.getBootstrapInstance(true);
0932: } catch (javax.jbi.JBIException ex) {
0933: comp.clearUpdating();
0934: String msg = mTranslator.getString(
0935: LocalStringKeys.CF_COMP_UPGRADE_LOAD_FAILED,
0936: componentType, componentName, ex.getMessage());
0937: mLog.warning(msg);
0938: throw new javax.jbi.JBIException(msg, ex);
0939: }
0940: String msgKey = null;
0941: try {
0942: java.lang.reflect.Method upgrade = getUpgradeMethod(bootInstance);
0943: if (null != upgrade) {
0944: List<ServiceUnitInfo> suList = comp
0945: .getServiceUnitList();
0946: ArrayList<String> suRoots = new ArrayList(0);
0947: for (ServiceUnitInfo su : suList) {
0948: suRoots.add(su.getFilePath());
0949: }
0950: Object[] params = { newComp.getWorkspaceRoot(), suRoots };
0951: upgrade.invoke(bootInstance, params);
0952: msgKey = LocalStringKeys.CF_COMP_UPGRADE_COMPLETE;
0953: } else {
0954: msgKey = LocalStringKeys.CF_COMP_UPDATE_COMPLETE;
0955: }
0956: } catch (java.lang.reflect.InvocationTargetException itEx) {
0957: Throwable compEx = itEx.getTargetException();
0958: throw new javax.jbi.JBIException(mTranslator.getString(
0959: LocalStringKeys.CF_COMP_UPGRADE_FAILED,
0960: componentType, componentName, compEx.getClass()
0961: .getName(), compEx.getMessage()), compEx);
0962: } catch (java.lang.IllegalAccessException iaEx) {
0963: String msg = mTranslator.getString(
0964: LocalStringKeys.CF_COMP_UPGRADE_ILLEGAL_ACCESS,
0965: componentType, componentName);
0966: mLog.log(Level.WARNING, msg, iaEx);
0967: throw new javax.jbi.JBIException(msg, iaEx);
0968: } finally {
0969: comp.clearUpdating();
0970: newComp.clearBootstrapInstance();
0971: }
0972:
0973: // Now that the upgrade has completed, update the Component instance
0974: // with the information for the new version.
0975:
0976: initComponent(comp, installContext, bootClassName,
0977: bootClassPathElements, sharedLibraryNames);
0978: comp.setShutdown();
0979:
0980: // Check for any pre-defined logger names and add them to the Logger
0981: // MBean for the component.
0982: getLoggerNames(installContext, comp);
0983:
0984: // Construct an appropriate message an log it, then send an MBean
0985: // notification of the upgrade.
0986: String installMsg = mTranslator.getString(msgKey,
0987: componentType, componentName);
0988: mLog.info(installMsg);
0989: mContext
0990: .getNotifier()
0991: .emitComponentNotification(
0992: EventNotifier.EventType.Upgraded,
0993: (comp.isBinding() ? EventNotifier.SourceType.BindingComponent
0994: : EventNotifier.SourceType.ServiceEngine),
0995: componentName, installMsg);
0996: }
0997:
0998: /**
0999: * Validate a component for upgrade. This validates that the runtime jar
1000: * files provided for the upgrade contain valid implementations of the
1001: * required interfaces and the component classes will load correctly. This
1002: * also verifies that all Shared Library dependencies are met. It also
1003: * determines whether or not the component has provided an implementation
1004: * of the <code>upgrade()</code> method and returns an indicator of that to
1005: * the caller.
1006: *
1007: * @param installContext The InstallationContext created by the Installer
1008: * Service.
1009: * @param bootClassName The name of the bootstrap class for the component.
1010: * @param bootClassPathElements A List of elements comprising the
1011: * class path for loading the bootstrap class. Each element is a String
1012: * containing the full path to either a jar file or a directory containing
1013: * class files.
1014: * @param sharedLibraryNames A List of String objects containing the names
1015: * of the Shared Libraries required by the component.
1016: * @return <code>true</code> if the component provided an <code>upgrade()
1017: * </code> method in its bootstrap implementation, <code>false</code> if it
1018: * did not.
1019: * @throws javax.jbi.JBIException if the component cannot be updated for
1020: * any reason.
1021: */
1022: public synchronized boolean validateComponentForUpgrade(
1023: InstallationContext installContext, String bootClassName,
1024: List bootClassPathElements, List sharedLibraryNames)
1025: throws javax.jbi.JBIException {
1026: // Check the parameters for validity. All parameters are required
1027: // and values must not be null.
1028:
1029: if (null == installContext) {
1030: throw new java.lang.IllegalArgumentException(mTranslator
1031: .getString(LocalStringKeys.NULL_ARGUMENT,
1032: "installContext"));
1033: }
1034: if (null == bootClassName) {
1035: throw new java.lang.IllegalArgumentException(mTranslator
1036: .getString(LocalStringKeys.NULL_ARGUMENT,
1037: "bootClassName"));
1038: }
1039: if (0 == bootClassName.length()) {
1040: throw new java.lang.IllegalArgumentException(mTranslator
1041: .getString(LocalStringKeys.EMPTY_STRING_ARGUMENT,
1042: "bootClassName"));
1043: }
1044: if (null == bootClassPathElements) {
1045: throw new java.lang.IllegalArgumentException(mTranslator
1046: .getString(LocalStringKeys.NULL_ARGUMENT,
1047: "bootClassPathElements"));
1048: }
1049: if (0 == bootClassPathElements.size()) {
1050: throw new java.lang.IllegalArgumentException(mTranslator
1051: .getString(LocalStringKeys.EMPTY_LIST_ARGUMENT,
1052: "bootClassPathElements"));
1053: }
1054:
1055: String componentName = installContext.getComponentName();
1056: String componentType = installContext.isBinding() ? mBinding
1057: : mEngine;
1058:
1059: // Get the Component represented by the component name from the registry
1060: // if it exists. The component must already exist in the registry. If it
1061: // is not found, abort the request.
1062:
1063: Component comp = mCompReg.getComponent(componentName);
1064: if (null == comp) {
1065: throw new javax.jbi.JBIException(mTranslator.getString(
1066: LocalStringKeys.CF_COMP_UPDATE_NOT_FOUND,
1067: componentType, componentName));
1068: }
1069:
1070: // Set the component updating flag to indicate that the validation call
1071: // has been made. This in turn marks the component busy so that no life
1072: // cycle operations can be performed on it. If the component is already
1073: // busy, the call to set the updating flag will throw an exception and
1074: // the validation will fail.
1075:
1076: comp.setUpdating();
1077:
1078: mLog.fine("Validating " + componentType + " " + componentName
1079: + " for upgrade");
1080:
1081: // The component must be in shutdown state to be updated. If it is not,
1082: // abort the request.
1083:
1084: if (!comp.isShutDown()) {
1085: comp.clearUpdating();
1086: throw new javax.jbi.JBIException(mTranslator.getString(
1087: LocalStringKeys.CF_COMP_UPDATE_NOT_SHUT_DOWN,
1088: componentType, componentName));
1089: }
1090:
1091: // Validate the component using the temporary install root where it has
1092: // been unzipped by the Installation Service. Create a new Component
1093: // instance for performing the validation, and update all fields that
1094: // could have been changed in the component's installation descriptor
1095: // (jbi.xml). Set the "updating" flag in this instance so that the
1096: // Shared Library dependency check knows this is for an upgrade.
1097:
1098: Component newComp = new Component();
1099: initComponent(newComp, installContext, bootClassName,
1100: bootClassPathElements, sharedLibraryNames);
1101: newComp.setUpdating();
1102:
1103: // Verify that all required Shared Libraries are installed.
1104:
1105: checkSharedLibraries(newComp);
1106:
1107: // Verify that the bootstrap and life cycle classes can be loaded and
1108: // are valid. Determine whether or not the component supports upgrade.
1109: javax.jbi.component.Bootstrap bootInstance;
1110: javax.jbi.component.ComponentLifeCycle lifeInstance;
1111: boolean supportsUpgrade = false;
1112: try {
1113: bootInstance = newComp.getBootstrapInstance(true);
1114: lifeInstance = newComp.getLifeCycleInstance(true);
1115: if (null != getUpgradeMethod(bootInstance)) {
1116: supportsUpgrade = true;
1117: }
1118: } catch (javax.jbi.JBIException ex) {
1119: comp.clearUpdating();
1120: mLog.warning(mTranslator.getString(
1121: LocalStringKeys.CF_COMP_UPDATE_VALIDATE_FAILED,
1122: componentType, componentName));
1123: mLog.warning(ex.getMessage());
1124: throw ex;
1125: } finally {
1126: newComp.clearBootstrapInstance();
1127: newComp.clearLifeCycleInstance();
1128: }
1129:
1130: return supportsUpgrade;
1131: }
1132:
1133: // ------------------------- Package-Visible methods --------------------------
1134:
1135: /**
1136: * Get the JMX ObjectName of the InstallerConfigurationMBean for a component.
1137: * @param componentName the unique name of the component.
1138: * @return The JMX ObjectName of the InstallerConfigurationMBean.
1139: * @throws javax.jbi.JBIException If the component is not found.
1140: */
1141: ObjectName getInstallerConfigurationMBeanName(String componentName)
1142: throws javax.jbi.JBIException {
1143: Component comp = mCompReg.getComponent(componentName);
1144: if (null == comp) {
1145: throw new javax.jbi.JBIException(mTranslator.getString(
1146: LocalStringKeys.CF_COMP_NOT_FOUND, componentName));
1147: }
1148:
1149: return comp.getExtensionMBeanName();
1150: }
1151:
1152: /**
1153: * Get the logger for this service.
1154: * @return The Logger instance.
1155: */
1156: Logger getLogger() {
1157: return mLog;
1158: }
1159:
1160: /**
1161: * Initialize a Component.
1162: * @param comp The Component instance.
1163: * @throws javax.jbi.JBIException If the initialization failed.
1164: */
1165: void initializeComponent(Component comp)
1166: throws javax.jbi.JBIException {
1167: javax.jbi.component.ComponentLifeCycle compInstance = comp
1168: .getLifeCycleInstance(false);
1169: initializeComponent(comp, compInstance);
1170: }
1171:
1172: /**
1173: * Initialize a Component.
1174: * @param comp The Component instance for this component.
1175: * @param compInstance The LifeCycle instance for this component.
1176: * @throws javax.jbi.JBIException If the initialization failed.
1177: */
1178: void initializeComponent(Component comp,
1179: javax.jbi.component.ComponentLifeCycle compInstance)
1180: throws javax.jbi.JBIException {
1181: mLog.fine("Initializing " + comp.getComponentTypeAsString()
1182: + " " + comp.getName());
1183:
1184: // Create the ComponentContext for this component.
1185:
1186: ComponentContext context = new ComponentContext(comp, mContext);
1187: comp.setContext(context);
1188: context.getDeliveryChannel(true);
1189:
1190: // Call the life cycle class init() method. A failure at this
1191: // point fails the originating command.
1192:
1193: ComponentStatistics stats = comp.getStatisticsInstance();
1194: ClassLoader cl = Thread.currentThread().getContextClassLoader();
1195: try {
1196: if (stats.isEnabled()) {
1197: stats.incrementInitRequests();
1198: }
1199: Thread.currentThread().setContextClassLoader(
1200: ClassLoaderFactory.getInstance()
1201: .getComponentClassLoader(comp.getName()));
1202: compInstance.init(context);
1203: } catch (Throwable ex) {
1204: if (stats.isEnabled()) {
1205: stats.incrementFailedRequests();
1206: }
1207: String msg = mTranslator
1208: .getString(
1209: LocalStringKeys.CF_COMP_INITIALIZATION_FAILED_EXCEPTION,
1210: comp.getComponentTypeAsString(), comp
1211: .getName(),
1212: ex.getClass().getName(), ex.getMessage());
1213: mLog.warning(msg);
1214: mLog.warning(mTranslator.stackTraceToString(ex));
1215: throw new javax.jbi.JBIException(msg, ex);
1216: } finally {
1217: Thread.currentThread().setContextClassLoader(cl);
1218: }
1219: comp.setStopped();
1220: comp.getDeployerInstance().setServiceUnitManager(
1221: comp.getServiceUnitManager());
1222: }
1223:
1224: /**
1225: * Install a Component into the JBI framework.
1226: * @param installContext The InstallationContext created by the
1227: * Installer Service.
1228: * @return The MBean object name of the LifeCycle MBean for this component.
1229: * @throws javax.jbi.JBIException If the installation fails.
1230: */
1231: synchronized ObjectName installComponent(
1232: InstallationContext installContext)
1233: throws javax.jbi.JBIException {
1234: // Make sure an InstallationContext is provided.
1235:
1236: if (null == installContext) {
1237: throw new java.lang.IllegalArgumentException(mTranslator
1238: .getString(LocalStringKeys.NULL_ARGUMENT,
1239: "installContext"));
1240: }
1241:
1242: String componentName = installContext.getComponentName();
1243: String componentType = installContext.isBinding() ? mBinding
1244: : mEngine;
1245:
1246: String msg = mTranslator.getString(
1247: LocalStringKeys.CF_COMP_INSTALL_FAILED, componentType,
1248: componentName)
1249: + " ";
1250:
1251: mLog.fine("Installing " + componentType + " " + componentName);
1252:
1253: // A Component instance representing this component must be in the
1254: // Component Registry in order to proceed. If one is not found, it
1255: // means that the loadBootstrap() method either was not called or did
1256: // not complete successfully. Also, the state of the component must be
1257: // "loaded". If it is in any other state the installation fails.
1258:
1259: Component comp = mCompReg.getComponent(componentName);
1260: if (null == comp) {
1261: throw new javax.jbi.JBIException(
1262: msg
1263: + mTranslator
1264: .getString(LocalStringKeys.CF_COMP_NOT_LOADED));
1265: } else {
1266: if (!comp.isLoaded()) {
1267: throw new javax.jbi.JBIException(
1268: msg
1269: + mTranslator
1270: .getString(LocalStringKeys.CF_COMP_ALREADY_INSTALLED));
1271: }
1272: }
1273:
1274: // Get the bootstrap instance and call its onInstall() method.
1275:
1276: doInstall(comp, msg, installContext);
1277:
1278: // Verify that the life cycle class can be loaded. This must be done
1279: // after calling the bootstrap onInstall() method so that if the
1280: // bootstrap modified the component's runtime class path, those changes
1281: // will be picked up when the component's class loader is created.
1282: // After verifying, remove the class loader and life cycle class
1283: // reference.
1284:
1285: javax.jbi.component.ComponentLifeCycle lifeInstance;
1286: try {
1287: lifeInstance = comp.getLifeCycleInstance(true);
1288: } catch (javax.jbi.JBIException ex) {
1289: comp.clearLifeCycleInstance();
1290: mCompReg.removeComponent(componentName);
1291: mLog.warning(msg + ex.getMessage());
1292: throw new javax.jbi.JBIException(msg, ex);
1293: }
1294:
1295: // Create and register the LifeCycleMBean for this component.
1296:
1297: ObjectName lifeMBeanName = null;
1298: ComponentLifeCycle lifeMBean = new ComponentLifeCycle(comp,
1299: this );
1300: try {
1301: lifeMBeanName = registerMBean(comp, lifeMBean,
1302: ComponentLifeCycleMBean.class,
1303: MBeanNames.CONTROL_TYPE_LIFECYCLE);
1304: } catch (javax.jbi.JBIException ex) {
1305: comp.clearLifeCycleInstance();
1306: mCompReg.removeComponent(componentName);
1307: throw new javax.jbi.JBIException(
1308: msg
1309: + mTranslator
1310: .getString(LocalStringKeys.CF_LIFECYCLE_MBEAN_REGISTRATION_FAILED),
1311: ex);
1312: }
1313: comp.setLifeCycleMBeanName(lifeMBeanName);
1314:
1315: // Installation was successful, permanently register the component in
1316: // the persistent registry and sent an MBean notification of the event.
1317:
1318: comp.setShutdown();
1319: mCompReg.commitComponent(componentName);
1320:
1321: String installMsg = mTranslator.getString(
1322: LocalStringKeys.CF_COMP_INSTALL_SUCCESSFUL,
1323: componentType, componentName);
1324: mLog.info(installMsg);
1325: mContext
1326: .getNotifier()
1327: .emitComponentNotification(
1328: EventNotifier.EventType.Installed,
1329: (comp.isBinding() ? EventNotifier.SourceType.BindingComponent
1330: : EventNotifier.SourceType.ServiceEngine),
1331: componentName, installMsg);
1332:
1333: // Create and register the ComponentStatisticsMBean for this component.
1334: // If this fails, do not fail the install, just log the error.
1335:
1336: try {
1337: createStatisticsMBean(comp);
1338: } catch (javax.jbi.JBIException ex) {
1339: mLog.warning(ex.getMessage());
1340: }
1341:
1342: // Create and register the DeployerMBean for this component. If this
1343: // fails, do not fail the install, just log the error.
1344:
1345: try {
1346: createDeployerMBean(comp);
1347: } catch (javax.jbi.JBIException ex) {
1348: mLog.warning(ex.getMessage());
1349: }
1350:
1351: // Create and register the LoggerMBean for this component. If this
1352: // fails, do not fail the install, just log the error. If this succeeds
1353: // check the installation descriptor to see if any loggers were declared
1354: // and if so, register them with the LoggerMBean.
1355:
1356: try {
1357: createLoggerMBean(comp);
1358: getLoggerNames(installContext, comp);
1359: } catch (javax.jbi.JBIException ex) {
1360: mLog.warning(ex.getMessage());
1361: }
1362:
1363: // Create and register the ConfigurationMBean for this component. If
1364: // this fails, do not fail the install, just log the error.
1365:
1366: try {
1367: createConfigurationMBean(comp);
1368: } catch (javax.jbi.JBIException ex) {
1369: mLog.warning(ex.getMessage());
1370: }
1371:
1372: // Clear the lifecycle instance.
1373: comp.clearLifeCycleInstance();
1374:
1375: return lifeMBeanName;
1376: }
1377:
1378: /**
1379: * This method is called by the JBI framework at the very beginning of its
1380: * startup so that components can create any local XAResources that might
1381: * be needed for recovery. If recovery is not enabled this phase will not be
1382: * called. We wait for the prepare phase to complete before
1383: * continuing. This method creats a new thread to run the
1384: * <code>ComponentStartup</code> class, and starts the thread. The
1385: *<code>run()</code> method of <code>ComponentStartup</code> will call
1386: * <code>startupAll()</code> with the <code>PREPARE</code> option to perform
1387: * the tasks required for components' XAResource recovery to proceed.
1388: */
1389: void prepare() {
1390: startupAll(PREPARE);
1391: }
1392:
1393: /**
1394: * This method is called by the JBI framework at the very end of its starup
1395: * processing to kick off the processing of component startup after any optional
1396: * XAResource recovery processing has been completed. When the <code>wait
1397: * </code> argument is set to <code>true</code>, the <code>startupAll()
1398: * </code> method is called directly with the <code>START</code> option to
1399: * perform automatic component startup processing. When the <code>wait</code>
1400: * argument is set to <code>false</code>, this method creates a new thread
1401: * to run the <code>ComponentStartup</code> class, and starts the thread.
1402: * The <code>run()</code> method of <code>ComponentStartup</code> will call
1403: * <code>startupAll()</code> with the <code>START</code> option to perform
1404: * the automatic component startup processing.
1405: *
1406: * @param wait when set to <code>true</code>, perform startup processing on
1407: * the current thread; when set to <code>false</code>, perform startup
1408: * processing on a new thread.
1409: */
1410: void ready(boolean wait) {
1411: if (wait) {
1412: startupAll(START);
1413: } else {
1414: ComponentStartup cs = new ComponentStartup(this , START);
1415: Thread t = new Thread(cs, "ComponentStartup");
1416: t.start();
1417: }
1418: }
1419:
1420: /**
1421: * Set the startup type. This is used in junit tests to allow the testing
1422: * of service startup and shutdown with different component startup types.
1423: * @param startup The component startup type to be set.
1424: */
1425: void setStartup(int startup) {
1426: mStartup = startup;
1427: }
1428:
1429: /**
1430: * Perform automatic startup processing. This is where all installed Shared
1431: * Libraries have their class loaders set up, and all components are brought
1432: * to the desired state, based on the ComponentStartup property setting.
1433: */
1434: void startupAll(int command) {
1435: // Get a list of all installed bindings and engines.
1436:
1437: List compList = mCompReg.getAllComponents();
1438:
1439: // If this is PREPARE or this is START and PREPARED wasn't seen.
1440: if (command == PREPARE
1441: || (mStartupState == 0 && command == START)) {
1442: mStartupState = command;
1443:
1444: // Get a list of all installed Shared Libraries, and recreate their
1445: // class loaders.
1446:
1447: List sLibList = mCompReg.getAllSharedLibraries();
1448: ListIterator s = sLibList.listIterator();
1449: SharedLibrary sl = null;
1450: while (s.hasNext()) {
1451: sl = (SharedLibrary) s.next();
1452: try {
1453: mClassLoaderFactory.createSharedClassLoader(sl);
1454: } catch (javax.jbi.JBIException jbiEx) {
1455: mLog
1456: .severe(mTranslator
1457: .getString(
1458: LocalStringKeys.CF_SL_CLASSLOADER_CREATION_FAILED,
1459: sl.getName(), jbiEx
1460: .getMessage()));
1461: continue;
1462: }
1463: }
1464:
1465: // Load the life cycle class and create a new instance for each
1466: // component in the list. Any component for which a failure occurs
1467: // is removed from the list to exclude it from further processing.
1468:
1469: createAllInstances(compList);
1470:
1471: // Create and register the required MBeans for each component in
1472: // the list. Any component for which a failure occurs is removed
1473: // from the list to exclude it from further processing.
1474:
1475: createAllMBeans(compList);
1476: }
1477:
1478: if (command == PREPARE) {
1479: // Components must be initialized during the prepare phase so that
1480: // any local XAResources used by components can be registered with
1481: // the runtime framework.
1482:
1483: prepareComponents(compList);
1484: } else {
1485: // Components that need to be started are started here during the
1486: // start phase. The prepare phase may or may not have run, but any
1487: // uninitialized components are initialized automatically.
1488:
1489: startComponents(compList);
1490: }
1491: }
1492:
1493: /**
1494: * Shut down a Component.
1495: * @param comp The Component instance representing the component.
1496: * @throws javax.jbi.JBIException If the shutdown fails.
1497: */
1498: void shutdownComponent(Component comp)
1499: throws javax.jbi.JBIException {
1500: shutdownComponent(comp, false);
1501: }
1502:
1503: /**
1504: * Shut down a Component.
1505: * @param comp The Component instance representing the component.
1506: * @param force Set to true to force the shutdown even if the component's
1507: * shutDown method fails.
1508: * @throws javax.jbi.JBIException If the shutdown fails.
1509: */
1510: void shutdownComponent(Component comp, boolean force)
1511: throws javax.jbi.JBIException {
1512: String componentName = comp.getName();
1513: String componentType = comp.getComponentTypeAsString();
1514: javax.jbi.component.ComponentLifeCycle compInstance = comp
1515: .getLifeCycleInstance(false);
1516: ComponentStatistics stats = comp.getStatisticsInstance();
1517:
1518: if (comp.isStarted()) {
1519: // Stop all Service Units deployed to this component.
1520: mSUFramework.stopServiceUnits(comp);
1521:
1522: // Call the life cycle class stop() method. A failure at this
1523: // point fails the shutdown command, unless force was specified.
1524: String stopMsg = mTranslator.getString(
1525: LocalStringKeys.CF_COMP_STOP_SUCCESSFUL,
1526: componentType, componentName);
1527: ClassLoader cl = Thread.currentThread()
1528: .getContextClassLoader();
1529: try {
1530: mLog.fine("Stopping " + componentType + " "
1531: + componentName);
1532: if (stats.isEnabled()) {
1533: stats.incrementStopRequests();
1534: }
1535: Thread.currentThread()
1536: .setContextClassLoader(
1537: ClassLoaderFactory.getInstance()
1538: .getComponentClassLoader(
1539: comp.getName()));
1540: compInstance.stop();
1541: mLog.info(stopMsg);
1542: } catch (Throwable ex) {
1543: if (stats.isEnabled()) {
1544: stats.incrementFailedRequests();
1545: }
1546: String msg = mTranslator.getString(
1547: LocalStringKeys.CF_LIFECYCLE_STOP_EXCEPTION,
1548: componentType, componentName, ex.getClass()
1549: .getName(), ex.getMessage());
1550: mLog.warning(msg);
1551: mLog.warning(mTranslator.stackTraceToString(ex));
1552: if (!force) {
1553: throw new javax.jbi.JBIException(msg, ex);
1554: }
1555: } finally {
1556: Thread.currentThread().setContextClassLoader(cl);
1557: }
1558: comp.setStopped();
1559: mContext
1560: .getNotifier()
1561: .emitComponentNotification(
1562: EventNotifier.EventType.Stopped,
1563: (comp.isBinding() ? EventNotifier.SourceType.BindingComponent
1564: : EventNotifier.SourceType.ServiceEngine),
1565: componentName, stopMsg);
1566: }
1567: if (comp.isStopped()) {
1568: // Shut down all Service Units. Errors here are just logged and do
1569: // not prevent the shutdown processing from proceeding.
1570: mSUFramework.shutDownServiceUnits(comp);
1571:
1572: // Call the life cycle class shutdown() method. A failure at this
1573: // point fails the shutdown command.
1574: ClassLoader cl = Thread.currentThread()
1575: .getContextClassLoader();
1576: try {
1577: mLog.fine("Shutting down " + componentType + " "
1578: + componentName);
1579: if (stats.isEnabled()) {
1580: stats.incrementShutDownRequests();
1581: }
1582: ComponentContext ctx = comp.getContext();
1583: if (comp.isObserver() && null != ctx) {
1584: mContext
1585: .getNormalizedMessageService()
1586: .removeObserver(
1587: (com.sun.jbi.messaging.DeliveryChannel) ctx
1588: .getDeliveryChannel());
1589: }
1590: Thread.currentThread()
1591: .setContextClassLoader(
1592: ClassLoaderFactory.getInstance()
1593: .getComponentClassLoader(
1594: comp.getName()));
1595: compInstance.shutDown();
1596: } catch (Throwable ex) {
1597: if (stats.isEnabled()) {
1598: stats.incrementFailedRequests();
1599: }
1600: String msg = mTranslator
1601: .getString(
1602: LocalStringKeys.CF_LIFECYCLE_SHUTDOWN_EXCEPTION,
1603: componentType, componentName, ex
1604: .getClass().getName(), ex
1605: .getMessage());
1606: mLog.warning(msg);
1607: mLog.warning(mTranslator.stackTraceToString(ex));
1608: if (!force) {
1609: throw new javax.jbi.JBIException(msg, ex);
1610: }
1611: } finally {
1612: Thread.currentThread().setContextClassLoader(cl);
1613: }
1614:
1615: // Reset the component to shutdown (installed) state, clear its
1616: // instance references, remove its class loader, close its NMR
1617: // channel if one is present, and clear its context.
1618:
1619: comp.setShutdown();
1620: comp.clearLifeCycleInstance();
1621: ComponentContext ctx = comp.getContext();
1622: if (null != ctx) {
1623: javax.jbi.messaging.DeliveryChannel dc = ctx
1624: .getDeliveryChannel(false);
1625: if (null != dc) {
1626: dc.close();
1627: }
1628: comp.setContext(null);
1629: }
1630:
1631: // Log a message that the component was shut down and send an
1632: // MBean notification of the event.
1633:
1634: String shutDownMsg;
1635: if (!force) {
1636: shutDownMsg = mTranslator.getString(
1637: LocalStringKeys.CF_COMP_SHUTDOWN_SUCCESSFUL,
1638: componentType, componentName);
1639: } else {
1640: shutDownMsg = mTranslator.getString(
1641: LocalStringKeys.CF_COMP_SHUTDOWN_FORCED,
1642: componentType, componentName);
1643: }
1644: mLog.info(shutDownMsg);
1645: mContext
1646: .getNotifier()
1647: .emitComponentNotification(
1648: EventNotifier.EventType.ShutDown,
1649: (comp.isBinding() ? EventNotifier.SourceType.BindingComponent
1650: : EventNotifier.SourceType.ServiceEngine),
1651: componentName, shutDownMsg);
1652: } else {
1653: if (comp.isLoaded()) {
1654: throw new javax.jbi.JBIException(mTranslator.getString(
1655: LocalStringKeys.CF_COMP_CANNOT_SHUTDOWN,
1656: componentType, componentName));
1657: } else {
1658: mLog
1659: .fine("Shutdown of " + componentType + " "
1660: + componentName
1661: + " ignored, already shut down");
1662: }
1663: }
1664: }
1665:
1666: /**
1667: * Start a Component.
1668: * @param comp The Component instance representing the component.
1669: * @throws javax.jbi.JBIException If the component cannot be started.
1670: */
1671: void startComponent(Component comp) throws javax.jbi.JBIException {
1672: startComponent(comp, false);
1673: }
1674:
1675: /**
1676: * Start a Component.
1677: * @param comp The Component instance representing the component.
1678: * @param startSUs When <code>true</code>, also brings deployed SUs to
1679: * their desired states.
1680: * @throws javax.jbi.JBIException If the component cannot be started.
1681: */
1682: void startComponent(Component comp, boolean startSUs)
1683: throws javax.jbi.JBIException {
1684: String componentName = comp.getName();
1685: String componentType = comp.getComponentTypeAsString();
1686:
1687: if (comp.isLoaded()) {
1688: throw new javax.jbi.JBIException(mTranslator.getString(
1689: LocalStringKeys.CF_COMP_CANNOT_START,
1690: componentType, componentName));
1691: }
1692:
1693: ComponentStatistics stats = comp.getStatisticsInstance();
1694:
1695: if (!comp.isStarted()) {
1696: // Check to be sure all required Shared Libraries are installed.
1697: // If any are missing, the start fails.
1698: checkSharedLibraries(comp);
1699:
1700: javax.jbi.component.ComponentLifeCycle compInstance;
1701:
1702: compInstance = comp.getLifeCycleInstance(true);
1703:
1704: mLog
1705: .fine("Starting " + componentType + " "
1706: + componentName);
1707:
1708: if (!comp.isInitialized()) {
1709: initializeComponent(comp, compInstance);
1710: }
1711:
1712: // Call the life cycle class start() method. A failure at this
1713: // point fails the start command.
1714: ClassLoader cl = Thread.currentThread()
1715: .getContextClassLoader();
1716: try {
1717: if (stats.isEnabled()) {
1718: stats.incrementStartRequests();
1719: }
1720: Thread.currentThread()
1721: .setContextClassLoader(
1722: ClassLoaderFactory.getInstance()
1723: .getComponentClassLoader(
1724: comp.getName()));
1725: compInstance.start();
1726: } catch (Throwable ex) {
1727: if (stats.isEnabled()) {
1728: stats.incrementFailedRequests();
1729: }
1730: String msg = mTranslator.getString(
1731: LocalStringKeys.CF_LIFECYCLE_START_EXCEPTION,
1732: componentType, componentName, ex.getClass()
1733: .getName(), ex.getMessage());
1734: mLog.warning(msg);
1735: mLog.warning(mTranslator.stackTraceToString(ex));
1736: throw new javax.jbi.JBIException(msg, ex);
1737: } finally {
1738: Thread.currentThread().setContextClassLoader(cl);
1739: }
1740:
1741: // The component is now started. Save the restart time and set the
1742: // state. Send an MBean notification about the event.
1743:
1744: stats.setLastRestartTime(new Date());
1745: comp.setStarted();
1746:
1747: String startMsg = mTranslator.getString(
1748: LocalStringKeys.CF_COMP_START_SUCCESSFUL,
1749: componentType, componentName);
1750: mLog.info(startMsg);
1751:
1752: mContext
1753: .getNotifier()
1754: .emitComponentNotification(
1755: EventNotifier.EventType.Started,
1756: (comp.isBinding() ? EventNotifier.SourceType.BindingComponent
1757: : EventNotifier.SourceType.ServiceEngine),
1758: componentName, startMsg);
1759:
1760: // Check the Observer flag for this component. If it is set to
1761: // true, set up the component as an NMR observer.
1762:
1763: if (comp.isObserver()) {
1764: mContext.getNormalizedMessageService().addObserver(
1765: (com.sun.jbi.messaging.DeliveryChannel) comp
1766: .getContext().getDeliveryChannel());
1767: }
1768:
1769: // If requested, initialize and start all of the SUs deployed to
1770: // the component.
1771:
1772: if (startSUs) {
1773: mSUFramework.initializeServiceUnits(comp);
1774: mSUFramework.startServiceUnits(comp);
1775: }
1776: } else {
1777: mLog.fine("Start of " + componentType + " " + componentName
1778: + " ignored, already started");
1779: }
1780: }
1781:
1782: /**
1783: * Stop a Component.
1784: * @param comp The Component instance representing the component.
1785: * @throws javax.jbi.JBIException If the component cannot be stopped.
1786: */
1787: void stopComponent(Component comp) throws javax.jbi.JBIException {
1788: String componentName = comp.getName();
1789: String componentType = comp.getComponentTypeAsString();
1790: javax.jbi.component.ComponentLifeCycle compInstance = comp
1791: .getLifeCycleInstance(false);
1792: ComponentStatistics stats = comp.getStatisticsInstance();
1793:
1794: if (comp.isStarted()) {
1795: mLog
1796: .fine("Stopping " + componentType + " "
1797: + componentName);
1798:
1799: mSUFramework.stopServiceUnits(comp);
1800:
1801: // Call the life cycle class stop() method. A failure at this
1802: // point fails the stop command.
1803: ClassLoader cl = Thread.currentThread()
1804: .getContextClassLoader();
1805: try {
1806: if (stats.isEnabled()) {
1807: stats.incrementStopRequests();
1808: }
1809: Thread.currentThread()
1810: .setContextClassLoader(
1811: ClassLoaderFactory.getInstance()
1812: .getComponentClassLoader(
1813: comp.getName()));
1814: compInstance.stop();
1815: } catch (Throwable ex) {
1816: if (stats.isEnabled()) {
1817: stats.incrementFailedRequests();
1818: }
1819: String msg = mTranslator.getString(
1820: LocalStringKeys.CF_LIFECYCLE_STOP_EXCEPTION,
1821: componentType, componentName, ex.getClass()
1822: .getName(), ex.getMessage());
1823: mLog.warning(msg);
1824: mLog.warning(mTranslator.stackTraceToString(ex));
1825: throw new javax.jbi.JBIException(msg, ex);
1826: } finally {
1827: Thread.currentThread().setContextClassLoader(cl);
1828: }
1829:
1830: // The component is now stopped. Set the state and send an MBean
1831: // notification about the event.
1832:
1833: comp.setStopped();
1834: String stopMsg = mTranslator.getString(
1835: LocalStringKeys.CF_COMP_STOP_SUCCESSFUL,
1836: componentType, componentName);
1837: mLog.info(stopMsg);
1838: mContext
1839: .getNotifier()
1840: .emitComponentNotification(
1841: EventNotifier.EventType.Stopped,
1842: (comp.isBinding() ? EventNotifier.SourceType.BindingComponent
1843: : EventNotifier.SourceType.ServiceEngine),
1844: componentName, stopMsg);
1845: } else {
1846: if (comp.isLoaded()) {
1847: throw new javax.jbi.JBIException(mTranslator.getString(
1848: LocalStringKeys.CF_COMP_CANNOT_STOP,
1849: componentType, componentName));
1850: } else if (comp.isStopped()) {
1851: mLog.fine("Stop of " + componentType + " "
1852: + componentName + " ignored, already stopped");
1853: } else // comp.isShutDown()
1854: {
1855: throw new javax.jbi.JBIException(mTranslator.getString(
1856: LocalStringKeys.CF_COMP_STOP_NOT_ACTIVE,
1857: componentType, componentName));
1858: }
1859: }
1860: }
1861:
1862: /**
1863: * Uninstall a Component from the JBI framework.
1864: * @param installContext The <code>InstallationContext</code> created by the
1865: * Installation Service.
1866: * @param force Set to <code>true</code> to proceed with the uninstall
1867: * regardless of any errors encountered.
1868: * @throws javax.jbi.JBIException If the uninstall fails.
1869: */
1870: synchronized void uninstallComponent(
1871: InstallationContext installContext, boolean force)
1872: throws javax.jbi.JBIException {
1873: // Check for null arguments.
1874:
1875: if (null == installContext) {
1876: throw new java.lang.IllegalArgumentException(mTranslator
1877: .getString(LocalStringKeys.NULL_ARGUMENT,
1878: "installContext"));
1879: }
1880:
1881: String componentName = installContext.getComponentName();
1882: String componentType = installContext.isBinding() ? mBinding
1883: : mEngine;
1884: String msg = mTranslator.getString(
1885: LocalStringKeys.CF_COMP_UNINSTALL_FAILED,
1886: componentType, componentName)
1887: + " ";
1888:
1889: mLog
1890: .fine("Uninstalling " + componentType + " "
1891: + componentName);
1892:
1893: // Get the Component instance for this component.
1894:
1895: Component comp = mCompReg.getComponent(componentName);
1896: if (null == comp) {
1897: throw new javax.jbi.JBIException(msg
1898: + mTranslator.getString(
1899: LocalStringKeys.CF_COMP_NO_COMP_INSTALLED,
1900: componentType));
1901: }
1902:
1903: // If the component is still running, deny the request to uninstall.
1904:
1905: if (comp.isStarted()) {
1906: throw new javax.jbi.JBIException(msg
1907: + mTranslator.getString(
1908: LocalStringKeys.CF_COMP_UNINSTALL_RUNNING,
1909: componentType));
1910: }
1911: if (comp.isStopped()) {
1912: throw new javax.jbi.JBIException(msg
1913: + mTranslator.getString(
1914: LocalStringKeys.CF_COMP_UNINSTALL_STOPPED,
1915: componentType));
1916: }
1917:
1918: // If the component has any Service Units still deployed to it, deny
1919: // the request to uninstall.
1920:
1921: List suList = comp.getServiceUnitList();
1922: if (!suList.isEmpty()) {
1923: int i = 0;
1924: StringBuffer suNames = new StringBuffer();
1925: Iterator sui = suList.iterator();
1926: while (sui.hasNext()) {
1927: if (suNames.length() > 0) {
1928: suNames.append(", ");
1929: }
1930: suNames.append(((ServiceUnit) sui.next()).getName());
1931: }
1932: msg = mTranslator.getString(
1933: LocalStringKeys.CF_COMP_UNINSTALL_FAILED_HAS_SUS,
1934: componentType, componentName, suNames);
1935: mLog.warning(msg);
1936: throw new javax.jbi.JBIException(msg);
1937: }
1938:
1939: // Get the bootstrap instance and call its onUninstall() method.
1940:
1941: com.sun.jbi.framework.FrameworkWarningException warning = null;
1942: try {
1943: doUninstall(comp, msg);
1944: } catch (com.sun.jbi.framework.FrameworkWarningException warnEx) {
1945: if (!force) {
1946: warning = warnEx;
1947: }
1948: } catch (javax.jbi.JBIException ex) {
1949: if (!force) {
1950: throw ex;
1951: }
1952: }
1953:
1954: // Unregister the component's runtime MBeans and mark the component
1955: // back to LOADED state so that unloadBoostrap() will remove it.
1956:
1957: unregisterMBeans(comp);
1958: comp.setLoaded();
1959:
1960: String uninstallMsg = mTranslator.getString(
1961: LocalStringKeys.CF_COMP_UNINSTALL_SUCCESSFUL,
1962: componentType, componentName);
1963: mLog.info(uninstallMsg);
1964: mContext
1965: .getNotifier()
1966: .emitComponentNotification(
1967: EventNotifier.EventType.Uninstalled,
1968: (comp.isBinding() ? EventNotifier.SourceType.BindingComponent
1969: : EventNotifier.SourceType.ServiceEngine),
1970: componentName, uninstallMsg);
1971:
1972: if (null != warning) {
1973: throw warning;
1974: }
1975: }
1976:
1977: // ----------------------------- Private Methods -----------------------------
1978:
1979: /**
1980: * Check for running dependent components that reference a SharedLibrary.
1981: * If any are found, throw an exception that lists the running dependent
1982: * components (dependent components that are not running are not listed).
1983: * If no running dependent components are found, the return value is a
1984: * string that contains the component type and name of each dependent
1985: * component, regardless of its status. This can be use to notify the
1986: * user that these components cannot be started until the Shared Library
1987: * has been reinstalled.
1988: * @param sharedLibraryName The unique name of the Shared Library.
1989: * @return A string containing a comma-separated list of Components that
1990: * depend upon this Shared Library.
1991: * @throws javax.jbi.JBIException If there are dependent components.
1992: */
1993: private String checkForActiveDependents(String sharedLibraryName)
1994: throws javax.jbi.JBIException {
1995: mLog
1996: .finer("Checking for components dependent upon Shared Library "
1997: + sharedLibraryName);
1998:
1999: boolean foundActiveDependents = false;
2000: StringBuffer actList = new StringBuffer();
2001: StringBuffer depList = new StringBuffer();
2002: List comps = mCompReg.getDependents(sharedLibraryName);
2003: ListIterator c = comps.listIterator();
2004: Component comp = null;
2005: while (c.hasNext()) {
2006: comp = (Component) c.next();
2007:
2008: // Add all dependents to the return string
2009: if (depList.length() > 0) {
2010: depList.append(", ");
2011: }
2012: depList.append(comp.getComponentTypeAsString());
2013: depList.append(" ");
2014: depList.append(comp.getName());
2015:
2016: // If the dependent is not active, skip to the next one
2017: if (comp.isLoaded() || comp.isShutDown()) {
2018: continue;
2019: }
2020: mLog.warning(mTranslator.getString(
2021: LocalStringKeys.CF_SL_REFERENCED_BY,
2022: sharedLibraryName, comp.getComponentTypeAsString(),
2023: comp.getName()));
2024: // Add active dependent to the message string
2025: if (actList.length() > 0) {
2026: actList.append(", ");
2027: }
2028: actList.append(comp.getComponentTypeAsString());
2029: actList.append(" ");
2030: actList.append(comp.getName());
2031: foundActiveDependents = true;
2032: }
2033:
2034: if (foundActiveDependents) {
2035: throw new javax.jbi.JBIException(mTranslator.getString(
2036: LocalStringKeys.CF_SL_REFERENCED_BY_LIST, actList));
2037: }
2038:
2039: return depList.toString();
2040: }
2041:
2042: /**
2043: * Check to be sure that all Shared Libraries required by this component
2044: * are already registered. Construct a list of SharedLibrary IDs that
2045: * are missing and post it in an exception message. The message issued is
2046: * based on whether the component is being installed or started, which is
2047: * determined by checking the component's state. If the component is in
2048: * LOADED state, it is being installed; otherwise, it is being started.
2049: * @param component The Component instance for this BC or SE.
2050: * @throws javax.jbi.JBIException If any of the required Shared Libraries
2051: * are not already registered.
2052: */
2053: private void checkSharedLibraries(Component component)
2054: throws javax.jbi.JBIException {
2055: // Check for required Shared Libraries. If any of them are not
2056: // installed, abort the installation.
2057:
2058: boolean missingSlib = false;
2059:
2060: List slNameList = component.getSharedLibraryNames();
2061: if (null != slNameList) {
2062: ListIterator slNameIter = slNameList.listIterator();
2063: StringBuffer slNameMissing = new StringBuffer();
2064: while (slNameIter.hasNext()) {
2065: String slName = (String) slNameIter.next();
2066: if (!mCompReg.isSharedLibraryRegistered(slName)) {
2067: mLog
2068: .warning(mTranslator
2069: .getString(
2070: LocalStringKeys.CF_COMP_MISSING_SHARED_LIBRARY,
2071: slName));
2072: if (slNameMissing.length() > 0) {
2073: slNameMissing.append(", ");
2074: }
2075: slNameMissing.append(slName);
2076: missingSlib = true;
2077: }
2078: }
2079: if (missingSlib) {
2080: if (component.isUpdating()) {
2081: throw new javax.jbi.JBIException(
2082: mTranslator
2083: .getString(
2084: LocalStringKeys.CF_COMP_UPGRADE_MISSING_SHARED_LIBRARIES,
2085: component
2086: .getComponentTypeAsString(),
2087: component.getName(),
2088: slNameMissing));
2089: } else if (component.isLoaded()) {
2090: throw new javax.jbi.JBIException(
2091: mTranslator
2092: .getString(
2093: LocalStringKeys.CF_COMP_MISSING_SHARED_LIBRARY_LIST,
2094: component
2095: .getComponentTypeAsString(),
2096: slNameMissing));
2097: } else {
2098: throw new javax.jbi.JBIException(
2099: mTranslator
2100: .getString(
2101: LocalStringKeys.CF_COMP_MISSING_SHARED_LIBRARIES_START,
2102: component
2103: .getComponentTypeAsString(),
2104: slNameMissing));
2105: }
2106: }
2107: }
2108: }
2109:
2110: /**
2111: * Create new instances of all installed components. This causes the
2112: * class loader for each component to be created, the life cycle class
2113: * to be loaded, and a new instance of that class to be created. Any
2114: * component for which an exception is encountered is removed from the
2115: * list so that it is not processed further.
2116: * @param compList The list of installed components.
2117: */
2118: private void createAllInstances(List compList) {
2119: // Load the life cycle class and create a new instance for each
2120: // component in the list. If an exception occurs at any point, log it.
2121:
2122: ListIterator c = compList.listIterator();
2123: Component comp = null;
2124:
2125: while (c.hasNext()) {
2126: comp = (Component) c.next();
2127: // Load any persisted logger settings for the component
2128: mLog.fine("Loading logger settings for "
2129: + comp.getComponentTypeAsString() + " "
2130: + comp.getName());
2131: mLog.fine("Loading life cycle for "
2132: + comp.getComponentTypeAsString() + " "
2133: + comp.getName());
2134: try {
2135: Object compInstance = comp.getLifeCycleInstance(true);
2136: } catch (javax.jbi.JBIException jbiEx) {
2137: c.remove();
2138: mLog.warning(jbiEx.getMessage());
2139: }
2140: }
2141: }
2142:
2143: /**
2144: * Create required MBeans for all loaded components. Any component for
2145: * which the lifecycle MBean cannot be created is removed from the list so
2146: * that it is not processed further. Without a lifecycle MBean, a component
2147: * cannot be operated upon.
2148: * @param compList The list of installed components.
2149: */
2150: private void createAllMBeans(List compList) {
2151: // Create and register all required MBeans for each component in the
2152: // list. If an exception occurs at any point, log it.
2153:
2154: ListIterator c = compList.listIterator();
2155: Component comp = null;
2156:
2157: while (c.hasNext()) {
2158: comp = (Component) c.next();
2159: mLog.finer("Creating LifeCycle MBean for "
2160: + comp.getComponentTypeAsString() + " "
2161: + comp.getName());
2162: try {
2163: createLifeCycleMBean(comp);
2164: } catch (javax.jbi.JBIException jbiEx) {
2165: c.remove();
2166: mLog.warning(jbiEx.getMessage());
2167: }
2168: mLog.finer("Creating Statistics MBean for "
2169: + comp.getComponentTypeAsString() + " "
2170: + comp.getName());
2171: try {
2172: createStatisticsMBean(comp);
2173: } catch (javax.jbi.JBIException jbiEx) {
2174: mLog.warning(jbiEx.getMessage());
2175: }
2176: mLog.finer("Creating Deployer MBean for "
2177: + comp.getComponentTypeAsString() + " "
2178: + comp.getName());
2179: try {
2180: createDeployerMBean(comp);
2181: } catch (javax.jbi.JBIException jbiEx) {
2182: mLog.warning(jbiEx.getMessage());
2183: }
2184: mLog.finer("Creating Logger MBean for "
2185: + comp.getComponentTypeAsString() + " "
2186: + comp.getName());
2187: try {
2188: createLoggerMBean(comp);
2189: } catch (javax.jbi.JBIException jbiEx) {
2190: mLog.warning(jbiEx.getMessage());
2191: }
2192: mLog.finer("Creating Configuration MBean for "
2193: + comp.getComponentTypeAsString() + " "
2194: + comp.getName());
2195: try {
2196: createConfigurationMBean(comp);
2197: } catch (javax.jbi.JBIException jbiEx) {
2198: mLog.warning(jbiEx.getMessage());
2199: }
2200: }
2201: }
2202:
2203: /**
2204: * Create and register a DeployerMBean for a component that supports
2205: * deployment of Service Units.
2206: * @param comp The Component instance representing the component.
2207: * @throws javax.jbi.JBIException If a failure occurs.
2208: */
2209: private void createDeployerMBean(Component comp)
2210: throws javax.jbi.JBIException {
2211: ObjectName deployerMBeanName = null;
2212: Deployer deployer = new Deployer(comp);
2213: comp.setDeployerInstance(deployer);
2214: try {
2215: deployerMBeanName = registerMBean(comp, deployer,
2216: DeployerMBean.class,
2217: MBeanNames.CONTROL_TYPE_DEPLOYER);
2218: } catch (javax.jbi.JBIException ex) {
2219: throw new javax.jbi.JBIException(
2220: mTranslator
2221: .getString(LocalStringKeys.CF_DEPLOYER_MBEAN_REGISTRATION_FAILED),
2222: ex);
2223: }
2224: comp.setDeployerMBeanName(deployerMBeanName);
2225: }
2226:
2227: /**
2228: * Create and register a LifeCycleMBean for a component.
2229: * @param comp The Component instance representing the component.
2230: * @throws javax.jbi.JBIException If a failure occurs.
2231: */
2232: void createLifeCycleMBean(Component comp)
2233: throws javax.jbi.JBIException {
2234: ObjectName lifeMBeanName = null;
2235: ComponentLifeCycle lifeMBean = new ComponentLifeCycle(comp,
2236: this );
2237: try {
2238: lifeMBeanName = registerMBean(comp, lifeMBean,
2239: ComponentLifeCycleMBean.class,
2240: MBeanNames.CONTROL_TYPE_LIFECYCLE);
2241: } catch (javax.jbi.JBIException jbiEx) {
2242: throw new javax.jbi.JBIException(mTranslator.getString(
2243: LocalStringKeys.CF_LIFECYCLE_MBEAN_NOT_REGISTERED,
2244: comp.getComponentTypeAsString(), comp.getName(),
2245: jbiEx.getMessage()));
2246: }
2247: comp.setLifeCycleMBeanName(lifeMBeanName);
2248: }
2249:
2250: /**
2251: * Create and register the ComponentLoggerMBean for the component.
2252: * @param comp The Component instance representing the component.
2253: * @throws javax.jbi.JBIException If a failure occurs.
2254: */
2255: private void createLoggerMBean(Component comp)
2256: throws javax.jbi.JBIException {
2257: ComponentLogger loggerInst = new ComponentLogger(comp);
2258: comp.setLoggerInstance(loggerInst);
2259:
2260: // Register the logger MBean
2261:
2262: ObjectName loggerMBeanName = null;
2263: ComponentLoggerMBean loggerMBean = (ComponentLoggerMBean) loggerInst;
2264: try {
2265: loggerMBeanName = registerMBean(comp, loggerMBean,
2266: ComponentLoggerMBean.class,
2267: MBeanNames.CONTROL_TYPE_LOGGER);
2268: comp.setLoggerMBeanName(loggerMBeanName);
2269: } catch (javax.jbi.JBIException ex) {
2270: throw new javax.jbi.JBIException(
2271: mTranslator
2272: .getString(LocalStringKeys.CC_LOGGER_MBEAN_REGISTRATION_FAILED),
2273: ex);
2274: }
2275: }
2276:
2277: /**
2278: * Create and register a StatisticsMBean for a component.
2279: * @param comp The Component instance representing the component.
2280: * @throws javax.jbi.JBIException If a failure occurs.
2281: */
2282: void createStatisticsMBean(Component comp)
2283: throws javax.jbi.JBIException {
2284: ObjectName statsMBeanName = null;
2285: ComponentStatistics statsMBean = new ComponentStatistics(comp
2286: .getName());
2287: comp.setStatisticsInstance(statsMBean);
2288: try {
2289: statsMBeanName = registerMBean(
2290: comp,
2291: statsMBean,
2292: com.sun.jbi.monitoring.ComponentStatisticsMBean.class,
2293: MBeanNames.CONTROL_TYPE_STATISTICS);
2294: comp.setStatisticsMBeanName(statsMBeanName);
2295: } catch (javax.jbi.JBIException ex) {
2296: throw new javax.jbi.JBIException(
2297: mTranslator
2298: .getString(
2299: LocalStringKeys.CF_STATISTICS_MBEAN_REGISTRATION_FAILED,
2300: comp.getComponentTypeAsString(),
2301: comp.getName(), ex.getMessage()));
2302: }
2303: }
2304:
2305: /**
2306: * Create and register a Component Configuration MBean for a component.
2307: * @param comp The Component instance representing the component.
2308: * @throws javax.jbi.JBIException If a failure occurs.
2309: */
2310: void createConfigurationMBean(Component comp)
2311: throws javax.jbi.JBIException {
2312: ObjectName cfgMBeanName = null;
2313: ComponentConfiguration cfgMBean = new ComponentConfiguration(
2314: mContext, comp.getName());
2315: try {
2316: cfgMBeanName = registerMBean(comp, cfgMBean,
2317: // Dynamic MBean
2318: null, MBeanNames.CONTROL_TYPE_CONFIGURATION);
2319: } catch (javax.jbi.JBIException jbiEx) {
2320: throw new javax.jbi.JBIException(
2321: mTranslator
2322: .getString(
2323: LocalStringKeys.CF_CONFIGURATION_MBEAN_REGISTRATION_FAILED,
2324: comp.getComponentTypeAsString(),
2325: comp.getName(), jbiEx.getMessage()));
2326: }
2327: comp.setConfigurationMBeanName(cfgMBeanName);
2328: }
2329:
2330: /**
2331: * Call a component's bootstrap onInstall() method to perform the install
2332: * processing for the component.
2333: * @param comp The instance of Component for this component.
2334: * @param msg The error message string for failure messages.
2335: * @param installContext The installation context.
2336: * @throws javax.jbi.JBIException If any failure occurs.
2337: */
2338: private void doInstall(Component comp, String msg,
2339: InstallationContext installContext)
2340: throws javax.jbi.JBIException {
2341: // Get the bootstrap class instance that was loaded and saved by
2342: // the loadBootstrap() method.
2343:
2344: Bootstrap bootInstance = comp.getBootstrapInstance(false);
2345:
2346: if (null == bootInstance) {
2347: mCompReg.removeComponent(comp.getName());
2348: throw new javax.jbi.JBIException(
2349: msg
2350: + mTranslator
2351: .getString(LocalStringKeys.CF_BOOTSTRAP_NOT_LOADED));
2352: }
2353:
2354: // Call the bootstrap onInstall() method. Note that this can actually
2355: // modify the component's runtime class path. This is why onInstall()
2356: // must be called before the creation of the component's class loader.
2357: // Once onInstall() completes, set the Life Cycle class path from the
2358: // values in the InstallationContext. Then call the bootstrap cleanUp()
2359: // method to clean up. Note that cleanUp() must be called even if
2360: // onInstall() fails. Also, care must be taken to preserve the original
2361: // exception from onInstall() if cleanUp() fails after onInstall()
2362: // fails. The cleanUp() exception is logged but not thrown in that case.
2363:
2364: boolean failure = false;
2365: try {
2366: bootInstance.onInstall();
2367: comp.setComponentClassPathElements(installContext
2368: .getAbsoluteClassPathElements());
2369: } catch (Throwable ex) {
2370: failure = true;
2371: mCompReg.removeComponent(comp.getName());
2372: String error = msg
2373: + mTranslator
2374: .getString(
2375: LocalStringKeys.CF_BOOTSTRAP_ONINSTALL_FAILED,
2376: ex.getClass().getName(), ex
2377: .getMessage());
2378: mLog.warning(error);
2379: mLog.warning(mTranslator.stackTraceToString(ex));
2380: throw new javax.jbi.JBIException(error, ex);
2381: } finally {
2382: try {
2383: bootInstance.cleanUp();
2384: } catch (Throwable ex) {
2385: String error = mTranslator
2386: .getString(
2387: LocalStringKeys.CF_BOOTSTRAP_INSTALL_CLEANUP_FAILED,
2388: comp.getComponentTypeAsString(), comp
2389: .getName(), ex.getClass()
2390: .getName(), ex.getMessage());
2391: mLog.warning(error);
2392: mLog.warning(mTranslator.stackTraceToString(ex));
2393: if (!failure) {
2394: throw new com.sun.jbi.framework.FrameworkWarningException(
2395: error);
2396: }
2397: } finally {
2398: comp.clearBootstrapInstance();
2399: }
2400: }
2401: }
2402:
2403: /**
2404: * Call a component's bootstrap onUninstall() method to perform the
2405: * uninstall processing for the component.
2406: * @param comp The instance of Component for this component.
2407: * @param msg The error message string for failure messages.
2408: * @throws javax.jbi.JBIException If any failure occurs.
2409: */
2410: private void doUninstall(Component comp, String msg)
2411: throws javax.jbi.JBIException {
2412: // Get the bootstrap class instance that was loaded and saved by
2413: // the loadBootstrap() method.
2414:
2415: Bootstrap bootInstance = comp.getBootstrapInstance(false);
2416: if (null == bootInstance) {
2417: throw new javax.jbi.JBIException(
2418: msg
2419: + mTranslator
2420: .getString(LocalStringKeys.CF_BOOTSTRAP_NOT_LOADED));
2421: }
2422:
2423: // Call the bootstrap class onUninstall() method. Then call the
2424: // bootstrap cleanUp() method to clean up. Note that cleanUp() must be
2425: // called even if onUninstall() fails. Also, care must be taken to
2426: // preserve the original exception from onUninstall() if cleanUp()
2427: // fails after onUninstall() fails. In that case the cleanUp() exception
2428: // is logged, but not thrown. If cleanUp() fails but onUninstall() was
2429: // successful, the exception is logged and thrown as a warning exception
2430: // so that the uninstall still succeeds but with a warning message.
2431:
2432: boolean failure = false;
2433: try {
2434: bootInstance.onUninstall();
2435: } catch (Throwable ex) {
2436: failure = true;
2437: String error = msg
2438: + mTranslator
2439: .getString(
2440: LocalStringKeys.CF_BOOTSTRAP_ONUNINSTALL_FAILED,
2441: ex.getClass().getName(), ex
2442: .getMessage());
2443: mLog.warning(error);
2444: mLog.warning(mTranslator.stackTraceToString(ex));
2445: throw new javax.jbi.JBIException(error, ex);
2446: } finally {
2447: try {
2448: bootInstance.cleanUp();
2449: } catch (Throwable ex) {
2450: String error = mTranslator
2451: .getString(
2452: LocalStringKeys.CF_BOOTSTRAP_UNINSTALL_CLEANUP_FAILED,
2453: comp.getComponentTypeAsString(), comp
2454: .getName(), ex.getClass()
2455: .getName(), ex.getMessage());
2456: mLog.warning(error);
2457: mLog.warning(mTranslator.stackTraceToString(ex));
2458: if (!failure) {
2459: throw new com.sun.jbi.framework.FrameworkWarningException(
2460: error);
2461: }
2462: } finally {
2463: comp.clearBootstrapInstance();
2464: }
2465: }
2466: }
2467:
2468: /**
2469: * Get the pre-defined logger names provided in the installation descriptor
2470: * extension for a component and add them to the logger MBean for that
2471: * component. This is done once during component installation or component
2472: * upgrade. After that, the logger names remain in the persisted list of
2473: * logger settings for the component.
2474: *
2475: * @param installContext The component installation context provided by the
2476: * Installation Service.
2477: * @param comp The Component instance representing the component.
2478: */
2479: private void getLoggerNames(InstallationContext installContext,
2480: Component comp) {
2481: // First get the installation descriptor extension. If there is none,
2482: // there is nothing to do.
2483: org.w3c.dom.DocumentFragment idext = installContext
2484: .getInstallationDescriptorExtension();
2485: if (null != idext) {
2486: try {
2487: // Get the logger definition section. If there is none, there
2488: // is nothing to do.
2489: org.w3c.dom.Node logging = XmlUtil.getElement(idext,
2490: TAG_LOGGING_SECTION, false);
2491:
2492: if (null != logging) {
2493: ComponentLogger cl = comp.getLoggerInstance();
2494: // Get the logger root if any is specified
2495: String prefix = XmlUtil.getAttribute(logging,
2496: TAG_LOGGING_ROOT);
2497: if (0 < prefix.length()) {
2498: cl.setLoggerNamePrefix(prefix);
2499: }
2500:
2501: // Now get a list of logger definitions and process them
2502: org.w3c.dom.NodeList logDefs = XmlUtil.getElements(
2503: logging, TAG_LOGGER_DEFINITION, false);
2504: if (null != logDefs) {
2505: for (int l = 0; l < logDefs.getLength(); l++) {
2506: org.w3c.dom.Node logDef = logDefs.item(l);
2507: String name = XmlUtil
2508: .getStringValue(logDef);
2509: String displayName = XmlUtil.getAttribute(
2510: logDef, TAG_DISPLAY_NAME);
2511: String addPrefixStr = XmlUtil.getAttribute(
2512: logDef, TAG_ADD_PREFIX);
2513: boolean addPrefix = true;
2514: if (0 < addPrefixStr.length()) {
2515: addPrefix = Boolean
2516: .parseBoolean(addPrefixStr);
2517: }
2518: cl.addLoggerInfo(name, displayName,
2519: addPrefix);
2520: }
2521: }
2522: cl.saveLoggerSettings();
2523: }
2524: } catch (javax.jbi.JBIException ex) {
2525: mLog.warning(ex.getMessage());
2526: }
2527: }
2528: }
2529:
2530: /**
2531: * Get the <code>upgrade()</code> method of a component's bootstrap
2532: * implementation, if it is present. This is done using reflection.
2533: * If this method is implemented, then the component supports upgrade;
2534: * otherwise the component does not support upgrade.
2535: *
2536: * @param bootInstance The Bootstrap instance of the component.
2537: * @return the upgrade method or null if upgrade is not supported by the
2538: * component.
2539: */
2540: private java.lang.reflect.Method getUpgradeMethod(
2541: Bootstrap bootInstance) {
2542: Class bootClass = bootInstance.getClass();
2543: java.lang.reflect.Method upgrade;
2544: try {
2545: Class args[] = { String.class, List.class };
2546: upgrade = bootClass.getMethod("upgrade", args);
2547: } catch (NoSuchMethodException nsmEx) {
2548: upgrade = null;
2549: }
2550: return upgrade;
2551: }
2552:
2553: /**
2554: * Load and initialize the bootstrap instance for a component, and register
2555: * an InstallerMBean for that instance.
2556: * @param comp The instance of Component representing this component.
2557: * @param msg An error message string for either installation or
2558: * uninstallation.
2559: * @param installContext The installation context.
2560: * @return The JMX object name of the InstallerMBean for the component.
2561: * @throws javax.jbi.JBIException If the bootstrap cannot be initialized.
2562: */
2563: private ObjectName initBootstrap(Component comp, String msg,
2564: InstallationContext installContext)
2565: throws javax.jbi.JBIException {
2566: // Load the bootstrap class.
2567:
2568: Bootstrap bootInstance;
2569: try {
2570: bootInstance = comp.getBootstrapInstance(true);
2571: } catch (javax.jbi.JBIException ex) {
2572: throw new javax.jbi.JBIException(msg, ex);
2573: }
2574:
2575: // Protect against an orphan bootstrap extension MBean.
2576:
2577: MBeanServer mbs = mContext.getMBeanServer();
2578: ObjectName extMBeanName = comp.getExtensionMBeanName();
2579: if (null != mbs && null != extMBeanName) {
2580: try {
2581: if (mbs.isRegistered(extMBeanName)) {
2582: mbs.unregisterMBean(extMBeanName);
2583: comp.setExtensionMBeanName(null);
2584: }
2585: } catch (javax.management.InstanceNotFoundException infEx) {
2586: ; // This can be ignored.
2587: } catch (javax.management.MBeanRegistrationException mbrEx) {
2588: ; // This can be ignored.
2589: }
2590: }
2591:
2592: // Call the bootstrap init() method.
2593:
2594: try {
2595: ComponentContext ctx = new ComponentContext(comp, mContext);
2596: installContext
2597: .setContext((javax.jbi.component.ComponentContext) ctx);
2598: bootInstance
2599: .init((javax.jbi.component.InstallationContext) installContext);
2600: } catch (Throwable ex) {
2601: String error = msg
2602: + mTranslator.getString(
2603: LocalStringKeys.CF_BOOTSTRAP_INIT_FAILED,
2604: ex.getClass().getName(), ex.getMessage());
2605: mLog.warning(error);
2606: mLog.warning(mTranslator.stackTraceToString(ex));
2607: try {
2608: bootInstance.cleanUp();
2609: } catch (Throwable cex) {
2610: String err = mTranslator.getString(
2611: LocalStringKeys.CF_BOOTSTRAP_CLEANUP_FAILED,
2612: cex.getClass().getName(), cex.getMessage());
2613: mLog.warning(msg + err);
2614: mLog.warning(mTranslator.stackTraceToString(cex));
2615: error = error + " " + err;
2616: }
2617: throw new javax.jbi.JBIException(error, ex);
2618: }
2619: try {
2620: ObjectName embn = bootInstance.getExtensionMBeanName();
2621: comp.setExtensionMBeanName(embn);
2622: } catch (Throwable ex) {
2623: String error = msg
2624: + mTranslator
2625: .getString(
2626: LocalStringKeys.CF_BOOTSTRAP_GET_EXTENSION_FAILED,
2627: ex.getClass().getName(), ex
2628: .getMessage());
2629: mLog.warning(error);
2630: mLog.warning(mTranslator.stackTraceToString(ex));
2631: try {
2632: bootInstance.cleanUp();
2633: } catch (Throwable cex) {
2634: String err = mTranslator.getString(
2635: LocalStringKeys.CF_BOOTSTRAP_CLEANUP_FAILED,
2636: cex.getClass().getName(), cex.getMessage());
2637: mLog.warning(msg + err);
2638: mLog.warning(mTranslator.stackTraceToString(cex));
2639: error = error + " " + err;
2640: }
2641: throw new javax.jbi.JBIException(error, ex);
2642: }
2643:
2644: // Create and register the InstallerMBean for this component.
2645:
2646: ObjectName instMBeanName;
2647: ComponentInstaller instMBean = new ComponentInstaller(
2648: installContext, this , mCompReg);
2649: try {
2650: instMBeanName = registerMBean(comp, instMBean,
2651: com.sun.jbi.management.InstallerMBean.class,
2652: MBeanNames.CONTROL_TYPE_INSTALLER);
2653: comp.setInstallerMBeanName(instMBeanName);
2654: } catch (javax.jbi.JBIException ex) {
2655: String error = msg
2656: + mTranslator
2657: .getString(LocalStringKeys.CF_COMP_INSTALLER_MBEAN_REGISTRATION_FAILED);
2658: mLog.warning(error);
2659: throw new javax.jbi.JBIException(error, ex);
2660: }
2661: return instMBeanName;
2662: }
2663:
2664: /**
2665: * Initialize a Component instance using data provided by the Installation
2666: * Service.
2667: * @param comp The Component instance to be initialized.
2668: * @param installContext The context created by the Installation Service.
2669: * @param bootClassName The name of the bootstrap class for the component.
2670: * @param bootClassPathElements A List of elements comprising the
2671: * class path for loading the bootstrap class. Each element is a String
2672: * containing the full path to either a jar file or a directory containing
2673: * class files.
2674: * @param sharedLibraryNames A List of String objects containing the names
2675: * of the Shared Libraries required by the component.
2676: */
2677: private void initComponent(Component comp,
2678: InstallationContext installContext, String bootClassName,
2679: List<String> bootClassPathElements,
2680: List<String> sharedLibraryNames) {
2681: comp.setName(installContext.getComponentName());
2682: comp.setDescription(installContext.getDescription());
2683: comp.setInstallRoot(installContext.getInstallRoot());
2684: String wsroot = installContext.getWorkspaceRoot();
2685: if (null != wsroot) {
2686: comp.setWorkspaceRoot(wsroot);
2687: } else {
2688: comp.setWorkspaceRoot(installContext.getInstallRoot());
2689: }
2690: if (installContext.isBinding()) {
2691: comp.setComponentTypeBinding();
2692: } else {
2693: comp.setComponentTypeEngine();
2694: }
2695: comp.setBootstrapClassLoaderSelfFirst(installContext
2696: .isBootstrapClassLoaderSelfFirst());
2697: comp.setBootstrapClassName(bootClassName);
2698: comp.setBootstrapClassPathElements(bootClassPathElements);
2699: comp.setComponentClassName(installContext
2700: .getComponentClassName());
2701: comp.setComponentClassPathElements(installContext
2702: .getAbsoluteClassPathElements());
2703: comp.setComponentClassLoaderSelfFirst(installContext
2704: .isComponentClassLoaderSelfFirst());
2705: comp.setSharedLibraryNames(sharedLibraryNames);
2706: comp.setLoaded();
2707: comp.setDesiredState(ComponentState.SHUTDOWN);
2708: }
2709:
2710: /**
2711: * Register an MBean for a component with the main MBean Server if it is
2712: * available.
2713: * @param component The Component object for this component.
2714: * @param instance The component implementation instance.
2715: * @param interfaceClass The interface implemented by the instance.
2716: * @param mbeanType The type of MBean to be registered. The value of this
2717: * is set using constants from the MBeanNames class.
2718: * @return The JMX MBean object name or null if there is no MBean Server
2719: * available.
2720: * @throws javax.jbi.JBIException If the MBean registration fails.
2721: */
2722: private ObjectName registerMBean(Component component,
2723: Object instance, Class interfaceClass, String mbeanType)
2724: throws javax.jbi.JBIException {
2725: if (null == mContext.getMBeanServer()) {
2726: return null;
2727: }
2728: mLog.finer("Registering " + mbeanType + " MBean for "
2729: + component.getComponentTypeAsString() + " "
2730: + component.getName());
2731:
2732: // Create a StandardMBean for this component instance if required.
2733:
2734: boolean isDynamicMBean = (interfaceClass == null ? true : false);
2735:
2736: StandardMBean mbean = null;
2737: if (!isDynamicMBean) {
2738: try {
2739: mbean = new StandardMBean(instance, interfaceClass);
2740: } catch (javax.management.NotCompliantMBeanException ncEx) {
2741: String exName = ncEx.getClass().getName();
2742: throw new javax.jbi.JBIException(mTranslator.getString(
2743: LocalStringKeys.CF_MBEAN_CREATION_FAILED,
2744: exName), ncEx);
2745: }
2746: }
2747:
2748: // Create the MBean ObjectName using the component name and the MBean
2749: // control type.
2750:
2751: ObjectName mbeanName = null;
2752: if (component.isBinding()) {
2753: mbeanName = mContext.getMBeanNames().getBindingMBeanName(
2754: component.getName(), mbeanType);
2755: } else {
2756: mbeanName = mContext.getMBeanNames().getEngineMBeanName(
2757: component.getName(), mbeanType);
2758: }
2759:
2760: // Register the MBean. If it is already registered, unregister it
2761: // first, as it is an old registration with a stale instance reference.
2762:
2763: try {
2764: if (mContext.getMBeanServer().isRegistered(mbeanName)) {
2765: try {
2766: mContext.getMBeanServer()
2767: .unregisterMBean(mbeanName);
2768: } catch (javax.management.InstanceNotFoundException infEx) {
2769: ; // Just ignore this error
2770: }
2771: }
2772: if (isDynamicMBean) {
2773: mContext.getMBeanServer().registerMBean(instance,
2774: mbeanName);
2775: } else {
2776: mContext.getMBeanServer().registerMBean(mbean,
2777: mbeanName);
2778: }
2779: } catch (javax.management.InstanceAlreadyExistsException iaeEx) {
2780: String exName = iaeEx.getClass().getName();
2781: throw new javax.jbi.JBIException(mTranslator.getString(
2782: LocalStringKeys.CF_MBEAN_REGISTRATION_FAILED,
2783: exName), iaeEx);
2784: } catch (javax.management.MBeanRegistrationException mbrEx) {
2785: String exName = mbrEx.getClass().getName();
2786: throw new javax.jbi.JBIException(mTranslator.getString(
2787: LocalStringKeys.CF_MBEAN_REGISTRATION_FAILED,
2788: exName), mbrEx);
2789: } catch (javax.management.NotCompliantMBeanException ncEx) {
2790: String exName = ncEx.getClass().getName();
2791: throw new javax.jbi.JBIException(mTranslator.getString(
2792: LocalStringKeys.CF_MBEAN_REGISTRATION_FAILED,
2793: exName), ncEx);
2794: }
2795:
2796: // Return the ObjectName for the new MBean.
2797: return mbeanName;
2798: }
2799:
2800: /**
2801: * Persist a change in the desired state of a component.
2802: * @param comp the Component instance representing the component.
2803: */
2804: private void persistState(Component comp) {
2805: try {
2806: ((com.sun.jbi.management.registry.Registry) mContext
2807: .getRegistry()).getUpdater().setComponentState(
2808: comp.getDesiredState(), comp.getName());
2809: } catch (com.sun.jbi.management.registry.RegistryException rEx) {
2810: mLog.log(Level.WARNING, rEx.getMessage(), rEx);
2811: }
2812: }
2813:
2814: /**
2815: * Prepare all components and set their desired states based on the
2816: * startup type. Preparing components means calling their life cycle
2817: * <code>init()</code> methods. This allows the components to create
2818: * local <code>XAResource</code>s and register them with the JBI
2819: * framework. This registration allows the <code>XAResource</code>s to
2820: * be recovered by the Transaction Manager. At the end of the prepare
2821: * phase, all components are in the <code>STOPPED</code> state.
2822: *
2823: * The startup type is handled as follows:
2824: *
2825: * STARTUP_NONE causes the desired state of all components to be set
2826: * to <code>SHUTDOWN</code>
2827: * STARTUP_ALL causes the desired state of all components to be set to
2828: * <code>STARTED</code>
2829: * STARTUP_AUTO causes the desired state of all components at the time
2830: * of the last shutdown to be retained
2831: *
2832: * When the START phase is executed, all components are brought to their
2833: * desired states.
2834: *
2835: * @param compList The list of installed components.
2836: */
2837: private void prepareComponents(List compList) {
2838: ListIterator c = compList.listIterator();
2839: Component comp = null;
2840: ComponentOperation oper;
2841: OperationCounter oc = new OperationCounter();
2842: ArrayList opers = new ArrayList();
2843: long timeOut = mContext.getComponentTimeout();
2844:
2845: while (c.hasNext()) {
2846: comp = (Component) c.next();
2847: ComponentState previousDesired = comp.getDesiredState();
2848:
2849: if (STARTUP_ALL == mStartup) {
2850: comp.setDesiredState(ComponentState.STARTED);
2851: persistState(comp);
2852:
2853: } else if (STARTUP_NONE == mStartup) {
2854: comp.setDesiredState(ComponentState.SHUTDOWN);
2855: persistState(comp);
2856: }
2857:
2858: //
2859: // Components previously in STARTED state need to be initialized
2860: // in case XA recovery needs to happen.
2861: //
2862: if (previousDesired.equals(ComponentState.STARTED)) {
2863: oper = new ComponentOperation(oc, comp,
2864: ComponentOperation.INITIALIZE, true);
2865: opers.add(oper);
2866: new Thread(oper, comp.getName()).start();
2867: }
2868: }
2869:
2870: if (0 < opers.size()) {
2871: synchronized (oc) {
2872: try {
2873: if (0 < oc.getValue()) {
2874: oc.wait(mContext.getComponentTimeout());
2875: }
2876: } catch (java.lang.InterruptedException iEx) {
2877: mLog
2878: .warning(mTranslator
2879: .getString(LocalStringKeys.CF_STARTUP_INTERRUPTED));
2880: }
2881: }
2882: Iterator opersIter = opers.iterator();
2883: while (opersIter.hasNext()) {
2884: oper = (ComponentOperation) opersIter.next();
2885: comp = oper.getComponent();
2886: if (!oper.completed()) {
2887: oper.getThread().interrupt();
2888: mLog.warning(mTranslator.getString(
2889: LocalStringKeys.CF_COMP_INIT_TIMEOUT, comp
2890: .getComponentTypeAsString(), comp
2891: .getName(), new Long(timeOut)));
2892: }
2893: }
2894: }
2895:
2896: }
2897:
2898: /**
2899: * Start components based on their desired states. The desired states were
2900: * either set by <code>prepareComponents()</code> if the XA recovery phase
2901: * was needed, or restored from their values prior to the last JBI shutdown.
2902: * if <code>prepareComponents()</code> ran, all components are in
2903: * <code>STOPPED</code> state upon entry to this method; otherwise they are
2904: * in <code>SHUTDOWN</code> state.
2905: *
2906: * In the case where <code>prepareComponents()</code> did not run, the
2907: * desired states of components must be modified based on the startup type
2908: * because the startup type has not yet been processed. In this case, the
2909: * startup type is handled as follows:
2910: *
2911: * <ul>
2912: * <li>STARTUP_NONE causes the desired state of all components to be set
2913: * to <code>SHUTDOWN</code>
2914: * </li>
2915: * <li>STARTUP_ALL causes the desired state of all components to be set to
2916: * <code>STARTED</code>
2917: * </li>
2918: * <li>STARTUP_AUTO causes the desired state of all components at the time
2919: * of the last shutdown to be retained
2920: * </li>
2921: * </ul><br>
2922: *
2923: * In order to get components into their desired states, different actions
2924: * are necessary in some cases depending on whether or not
2925: * <code>prepareComponents()</code> was called.<br>
2926: *
2927: * Actions when <code>prepareComponents()</code> was called:
2928: *
2929: * <ul>
2930: * <li>If the desired state is <code>SHUTDOWN</code>, the component's life
2931: * cycle <code>shutDown()</code> method is called.
2932: * </li>
2933: * <li>If the desired state is <code>STOPPED</code>, no action is required
2934: * </li>
2935: * <li>If the desired state is <code>STARTED</code>, the component's life
2936: * cycle <code>start()</code> method is called.
2937: * </li>
2938: * </ul><br>
2939: *
2940: * Actions when <code>prepareComponents()</code> was NOT called:
2941: *
2942: * <ul>
2943: * <li>If the desired state is <code>SHUTDOWN</code>, no action is required.
2944: * </li>
2945: * <li>If the desired state is <code>STOPPED</code>, the component's life
2946: * cycle <code>init()</code> method is called.
2947: * </li>
2948: * <li>If the desired state is (code>STARTED</code>, the component's life
2949: * cycle <code>init()</code> and <code>start()</code) methods are called.
2950: * </li>
2951: * </ul>
2952: *
2953: * @param compList The list of installed components.
2954: */
2955: private void startComponents(List compList) {
2956: mLog.finer("startComponents entered, startup state is "
2957: + ((mStartupState == PREPARE) ? "PREPARE" : "START"));
2958: ListIterator c = compList.listIterator();
2959: Component comp = null;
2960: ComponentOperation oper;
2961: OperationCounter oc = new OperationCounter();
2962: ArrayList opers = new ArrayList();
2963: long timeOut = mContext.getComponentTimeout();
2964: if (mStartupState == PREPARE) {
2965: // If we performed the PREPARE phase, some components related to XA
2966: // recovery that have a desired state of <code>STARTED</code> are in
2967: // <code>STOPPED</code> state. If the desired state is
2968: // <code>SHUTDOWN</code>, shut down the component; if the desired
2969: // state is <code>STARTED</code>, start the component; if the
2970: // desired state is <code>STOPPED</code>, initialize the component.
2971:
2972: while (c.hasNext()) {
2973: comp = (Component) c.next();
2974: mLog.finer("processing component " + comp.getName()
2975: + " with desired state "
2976: + comp.getDesiredState());
2977: if (ComponentState.STARTED == comp.getDesiredState()) {
2978: oper = new ComponentOperation(oc, comp,
2979: ComponentOperation.STARTUP, true);
2980: opers.add(oper);
2981: new Thread(oper, comp.getName()).start();
2982: } else if (ComponentState.STOPPED == comp
2983: .getDesiredState()) {
2984: oper = new ComponentOperation(oc, comp,
2985: ComponentOperation.INITIALIZE, true);
2986: opers.add(oper);
2987: new Thread(oper, comp.getName()).start();
2988: } else if (ComponentState.SHUTDOWN == comp
2989: .getDesiredState()) {
2990: oper = new ComponentOperation(oc, comp,
2991: ComponentOperation.SHUTDOWN, true);
2992: opers.add(oper);
2993: new Thread(oper, comp.getName()).start();
2994: }
2995: }
2996: } else {
2997: // If we skipped the PREPARE phase, all components are in
2998: // <code>SHUTDOWN</code> state. First set the desired state based
2999: // on the startup type. Then, if the desired state is
3000: // <code>STOPPED</code>, initialize the component; if the desired
3001: // state is <code>STARTED</code>, initialize and start the component.
3002:
3003: while (c.hasNext()) {
3004: comp = (Component) c.next();
3005:
3006: if (STARTUP_ALL == mStartup) {
3007: comp.setDesiredState(ComponentState.STARTED);
3008: persistState(comp);
3009: oper = new ComponentOperation(oc, comp,
3010: ComponentOperation.STARTUP, true);
3011: opers.add(oper);
3012: new Thread(oper, comp.getName()).start();
3013: } else if (STARTUP_AUTO == mStartup) {
3014: if (comp.getDesiredState().equals(
3015: ComponentState.STOPPED)) {
3016: oper = new ComponentOperation(oc, comp,
3017: ComponentOperation.INITIALIZE, true);
3018: opers.add(oper);
3019: new Thread(oper, comp.getName()).start();
3020: } else if (comp.getDesiredState().equals(
3021: ComponentState.STARTED)) {
3022: oper = new ComponentOperation(oc, comp,
3023: ComponentOperation.STARTUP, true);
3024: opers.add(oper);
3025: new Thread(oper, comp.getName()).start();
3026: }
3027: } else if (STARTUP_NONE == mStartup) {
3028: comp.setDesiredState(ComponentState.SHUTDOWN);
3029: persistState(comp);
3030: }
3031: }
3032: }
3033:
3034: // If any operations were performed, wait for all of them to complete
3035: // and process the results.
3036:
3037: if (0 < opers.size()) {
3038: mLog.finer("waiting for " + opers.size()
3039: + " operations to complete");
3040: synchronized (oc) {
3041: try {
3042: if (0 < oc.getValue()) {
3043: oc.wait(timeOut);
3044: }
3045: } catch (java.lang.InterruptedException iEx) {
3046: mLog
3047: .warning(mTranslator
3048: .getString(LocalStringKeys.CF_STARTUP_INTERRUPTED));
3049: }
3050: }
3051: Iterator opersIter = opers.iterator();
3052: while (opersIter.hasNext()) {
3053: oper = (ComponentOperation) opersIter.next();
3054: comp = oper.getComponent();
3055: if (!oper.completed()) {
3056: oper.getThread().interrupt();
3057: mLog.warning(mTranslator.getString(
3058: LocalStringKeys.CF_COMP_START_TIMEOUT, comp
3059: .getComponentTypeAsString(), comp
3060: .getName(), new Long(timeOut)));
3061: }
3062: }
3063: }
3064:
3065: // Now bring all Service Assemblies to their desired states. Any errors
3066: // that occur are handled and logged by the Deployment Service. There
3067: // is no need for any error checking here, because during startup of
3068: // the runtime, there's really not anything that can be done in the
3069: // event of an error in the processing other than log the error.
3070:
3071: com.sun.jbi.management.system.ManagementService ms = mContext
3072: .getManagementService();
3073: if (null != ms) {
3074: com.sun.jbi.management.system.ManagementContext mc = ms
3075: .getManagementContext();
3076: if (null != mc) {
3077: mc.getDeploymentServiceHandle()
3078: .startAllServiceAssemblies();
3079: }
3080: }
3081: }
3082:
3083: /**
3084: * Unregister all the MBeans for a component.
3085: * @param comp The Component instance representing the component.
3086: * @throws javax.jbi.JBIException If a failure occurs.
3087: */
3088: void unregisterMBeans(Component comp) throws javax.jbi.JBIException {
3089: ObjectName name;
3090: MBeanServer mbs = mContext.getMBeanServer();
3091: if (null != mbs) {
3092: // Unregister Configuration MBean
3093: try {
3094: mbs.unregisterMBean(comp.getConfigurationMBeanName());
3095: } catch (Throwable ex) {
3096: String error = mTranslator
3097: .getString(
3098: LocalStringKeys.CF_CONFIGURATION_MBEAN_UNREGISTRATION_FAILED,
3099: comp.getComponentTypeAsString(), comp
3100: .getName(), ex.getClass()
3101: .getName());
3102: mLog.warning(error);
3103: mLog.warning(mTranslator.stackTraceToString(ex));
3104: }
3105: comp.setConfigurationMBeanName(null);
3106:
3107: // Unregister LifeCycle MBean
3108: try {
3109: mbs.unregisterMBean(comp.getLifeCycleMBeanName());
3110: } catch (Throwable ex) {
3111: String error = mTranslator
3112: .getString(
3113: LocalStringKeys.CF_LIFECYCLE_MBEAN_UNREGISTRATION_FAILED,
3114: comp.getComponentTypeAsString(), comp
3115: .getName(), ex.getClass()
3116: .getName());
3117: mLog.warning(error);
3118: mLog.warning(mTranslator.stackTraceToString(ex));
3119: }
3120: comp.setLifeCycleMBeanName(null);
3121:
3122: // Unregister Deployer MBean if it exists
3123: name = comp.getDeployerMBeanName();
3124: if (null != name) {
3125: try {
3126: mbs.unregisterMBean(name);
3127: } catch (Throwable ex) {
3128: mLog
3129: .warning(mTranslator
3130: .getString(
3131: LocalStringKeys.CF_DEPLOYER_MBEAN_UNREGISTRATION_FAILED,
3132: comp
3133: .getComponentTypeAsString(),
3134: comp.getName(), ex
3135: .getClass()
3136: .getName()));
3137: mLog.warning(mTranslator.stackTraceToString(ex));
3138: }
3139: comp.setDeployerInstance(null);
3140: comp.setDeployerMBeanName(null);
3141: }
3142:
3143: // Unregister logger MBean
3144: name = comp.getLoggerMBeanName();
3145: if (null != name) {
3146: try {
3147: mbs.unregisterMBean(name);
3148: } catch (Throwable ex) {
3149: mLog
3150: .warning(mTranslator
3151: .getString(
3152: LocalStringKeys.CF_LOGGER_MBEAN_UNREGISTRATION_FAILED,
3153: comp
3154: .getComponentTypeAsString(),
3155: comp.getName(), name, ex
3156: .getClass()
3157: .getName()));
3158: mLog.warning(mTranslator.stackTraceToString(ex));
3159: }
3160: comp.setLoggerMBeanName(null);
3161: }
3162:
3163: // Unregister statistics MBean
3164: name = comp.getStatisticsMBeanName();
3165: if (null != name) {
3166: try {
3167: mbs.unregisterMBean(name);
3168: } catch (Throwable ex) {
3169: mLog
3170: .warning(mTranslator
3171: .getString(
3172: LocalStringKeys.CF_STATISTICS_MBEAN_UNREGISTRATION_FAILED,
3173: comp
3174: .getComponentTypeAsString(),
3175: comp.getName(), ex
3176: .getClass()
3177: .getName()));
3178: mLog.warning(mTranslator.stackTraceToString(ex));
3179: }
3180: comp.clearStatisticsInstance();
3181: comp.setStatisticsMBeanName(null);
3182: }
3183: }
3184: }
3185: }
|