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: * @(#)AutoAdminTask.java
0025: * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
0026: *
0027: * END_HEADER - DO NOT EDIT
0028: */
0029: package com.sun.jbi.management.system;
0030:
0031: import com.sun.jbi.JBIProvider;
0032: import com.sun.jbi.StringTranslator;
0033: import com.sun.jbi.management.config.DeploymentConfigurationFactory;
0034: import com.sun.jbi.management.config.InstallationConfigurationFactory;
0035: import com.sun.jbi.management.LocalStringKeys;
0036: import com.sun.jbi.management.MBeanNames;
0037: import com.sun.jbi.management.repository.Archive;
0038: import com.sun.jbi.management.repository.ArchiveType;
0039: import com.sun.jbi.ui.common.JBIManagementMessage;
0040: import com.sun.org.apache.xpath.internal.XPathAPI;
0041: import java.io.File;
0042: import java.io.FilenameFilter;
0043: import java.io.FileOutputStream;
0044: import java.io.StringReader;
0045: import java.util.ArrayList;
0046: import java.util.Properties;
0047: import java.util.logging.Logger;
0048: import javax.jbi.management.DeploymentServiceMBean;
0049: import javax.management.ObjectName;
0050: import javax.xml.parsers.DocumentBuilder;
0051: import javax.xml.parsers.DocumentBuilderFactory;
0052: import org.w3c.dom.Document;
0053: import org.w3c.dom.Text;
0054: import org.xml.sax.InputSource;
0055:
0056: /**
0057: * This is the JBI Framework Auto Admin Task, which helps with autodeploy and
0058: * autoinstall functionality.
0059: *
0060: * @author Sun Microsystems, Inc.
0061: */
0062: public class AutoAdminTask {
0063: /** Root directory for autoinstall. */
0064: public static final String AUTOINSTALL_DIR = "autoinstall";
0065:
0066: /** Working directory for installer. */
0067: private static final String INSTALL_STATUS_DIR = ".autoinstallstatus";
0068:
0069: /** File name suffix for a successful autoinstall operation. */
0070: private static final String INSTALL_SUCCESS = "_installed";
0071:
0072: /** File name suffix for an unsuccessful autoinstall operation. */
0073: private static final String INSTALL_FAILURE = "_notInstalled";
0074:
0075: /** File name suffix for a successful autouninstall operation. */
0076: private static final String UNINSTALL_SUCCESS = "_uninstalled";
0077:
0078: /** File name suffix for an unsuccessful autouninstall operation. */
0079: private static final String UNINSTALL_FAILURE = "_notUninstalled";
0080:
0081: /** Root directory for autodeploy. */
0082: public static final String AUTODEPLOY_DIR = "autodeploy";
0083:
0084: /** Working directory for deployer. */
0085: private static final String DEPLOY_STATUS_DIR = ".autodeploystatus";
0086:
0087: /** File name suffix for a successful autodeploy operation. */
0088: private static final String DEPLOY_SUCCESS = "_deployed";
0089:
0090: /** File name suffix for an unsuccessful autodeploy operation. */
0091: private static final String DEPLOY_FAILURE = "_notDeployed";
0092:
0093: /** File name suffix for a successful autoundeploy operation. */
0094: private static final String UNDEPLOY_SUCCESS = "_undeployed";
0095:
0096: /** File name suffix for an unsuccessful autoundeploy operation. */
0097: private static final String UNDEPLOY_FAILURE = "_notUndeployed";
0098:
0099: /** Separates the autodeployed file's name from the SA name */
0100: public static final String DELIMITER = "--";
0101:
0102: /** Separates the autoinstalled file's name from the component's name */
0103: public static final String COMP_DELIMITER = DELIMITER + "comp"
0104: + DELIMITER;
0105:
0106: /** Separates the autoinstalled file's name from the shared library's name */
0107: public static final String SL_DELIMITER = DELIMITER + "sl"
0108: + DELIMITER;
0109:
0110: /**
0111: * Management context
0112: */
0113: private ManagementContext mContext;
0114:
0115: //where to log messages:
0116: private Logger mLogger;
0117:
0118: // Directory from where JBI picks up installable jars
0119: private File mAutoInstallDir;
0120: private String mAutoInstallDirName;
0121:
0122: // Directory from where JBI picks up deployable zips
0123: private File mAutoDeployDir;
0124: private String mAutoDeployDirName;
0125:
0126: // Work directory for installation (where timestamps and associations are kept)
0127: private File mInstallTimestampsDir;
0128:
0129: // Work directory for deployment (where timestamps and associations are kept)
0130: private File mDeployTimestampsDir;
0131:
0132: //DocumentBuilder
0133: private DocumentBuilder mDocBuilder;
0134:
0135: /** is auto install currently enabled? */
0136: private boolean mAutoInstallEnabled;
0137:
0138: /** is auto reinstall currently enabled? */
0139: private boolean mAutoReinstallEnabled;
0140:
0141: /** is auto uninstall currently enabled? */
0142: private boolean mAutoUninstallEnabled;
0143:
0144: /** is auto deploy currently enabled? */
0145: private boolean mAutoDeployEnabled = false; // always false for Glassfish
0146:
0147: /** is auto redeploy currently enabled? */
0148: private boolean mAutoRedeployEnabled;
0149:
0150: /** is auto undeploy currently enabled? */
0151: private boolean mAutoUndeployEnabled;
0152:
0153: /** ObjectName for InstallationService */
0154: private ObjectName mInstallationMBean;
0155:
0156: /** ObjectName for DeploymentService */
0157: private ObjectName mDeploymentMBean;
0158:
0159: /** ObjectName for Installation ConfigurationService */
0160: private ObjectName mInstallConfigSvcMBean;
0161:
0162: /** ObjectName for Deployment ConfigurationService */
0163: private ObjectName mDeployConfigSvcMBean;
0164:
0165: /**
0166: * Handle to StringTranslator for message translation
0167: */
0168: private StringTranslator mTranslator;
0169:
0170: /**
0171: * The three different types of query for the pollAutoDirectory function
0172: */
0173: public enum PollFunction {
0174: NEW_FILES, DELETED_FILES, UPDATED_FILES
0175: }
0176:
0177: /**
0178: * Filters out all status files except for those starting with the given prefix.
0179: */
0180: private class NamedFileFinder implements FilenameFilter {
0181: String prefix = null;
0182:
0183: NamedFileFinder(String p) {
0184: prefix = p;
0185: }
0186:
0187: public boolean accept(File dir, String name) {
0188: if (name.startsWith(prefix + DELIMITER)) {
0189: return true;
0190: }
0191: return false;
0192: }
0193: }
0194:
0195: /**
0196: * Constructs a AutoAdminTask.
0197: * @param anEnv is the ManagementContext.
0198: */
0199: public AutoAdminTask(ManagementContext anEnv) {
0200: mContext = anEnv;
0201: mLogger = mContext.getLogger();
0202: mTranslator = (StringTranslator) anEnv.getEnvironmentContext()
0203: .getStringTranslator("com.sun.jbi.management");
0204:
0205: // Autoinstall and Autodeploy always target the local instance
0206: mInstallationMBean = mContext
0207: .getMBeanNames()
0208: .getSystemServiceMBeanName(
0209: MBeanNames.ServiceName.InstallationService,
0210: MBeanNames.ServiceType.Installation,
0211: mContext.getEnvironmentContext()
0212: .getPlatformContext().getInstanceName());
0213:
0214: mDeploymentMBean = mContext
0215: .getMBeanNames()
0216: .getSystemServiceMBeanName(
0217: MBeanNames.ServiceName.DeploymentService,
0218: MBeanNames.ServiceType.Deployment,
0219: mContext.getEnvironmentContext()
0220: .getPlatformContext().getInstanceName());
0221:
0222: mInstallConfigSvcMBean = mContext
0223: .getMBeanNames()
0224: .getSystemServiceMBeanName(
0225: MBeanNames.ServiceName.ConfigurationService,
0226: MBeanNames.ServiceType.Installation,
0227: mContext.getEnvironmentContext()
0228: .getPlatformContext().getInstanceName());
0229:
0230: mDeployConfigSvcMBean = mContext
0231: .getMBeanNames()
0232: .getSystemServiceMBeanName(
0233: MBeanNames.ServiceName.ConfigurationService,
0234: MBeanNames.ServiceType.Deployment,
0235: mContext.getEnvironmentContext()
0236: .getPlatformContext().getInstanceName());
0237:
0238: }
0239:
0240: /**
0241: * Constructs a AutoAdminTask for use by junit tests.
0242: * @param anEnv is the ManagementContext.
0243: * @param autoInstallDir Directory for auto install dir
0244: * @param autoDeployDir Directory for auto deploy dir
0245: * @param isAutoInstallEnabled true iff the auto install permission bit set.
0246: * @param isAutoDeployEnabled true iff the auto deploy permission bit set.
0247: */
0248: public AutoAdminTask(ManagementContext anEnv,
0249: String aDirectoryForAutoInstall,
0250: String aDirectoryForAutoDeploy,
0251: boolean isAutoInstallEnabled, boolean isAutoDeployEnabled) {
0252: this (anEnv);
0253: mAutoInstallDirName = aDirectoryForAutoInstall;
0254: mAutoDeployDirName = aDirectoryForAutoDeploy;
0255: mAutoInstallEnabled = isAutoInstallEnabled;
0256: mAutoReinstallEnabled = isAutoInstallEnabled;
0257: mAutoUninstallEnabled = isAutoInstallEnabled;
0258: mAutoDeployEnabled = isAutoDeployEnabled;
0259: mAutoRedeployEnabled = isAutoDeployEnabled;
0260: mAutoUndeployEnabled = isAutoDeployEnabled;
0261: }
0262:
0263: /**
0264: * Process autoinstall and autodeploy directories.
0265: * @throws Exception unexpectedly.
0266: */
0267: public synchronized void performAutoFunctions() throws Exception {
0268: // for efficiency, check configuration settings once per heartbeat
0269:
0270: mAutoInstallDirName = getConfigAttribute(
0271: mInstallConfigSvcMBean,
0272: InstallationConfigurationFactory.AUTO_INSTALL_DIR);
0273: mAutoDeployDirName = getConfigAttribute(mDeployConfigSvcMBean,
0274: DeploymentConfigurationFactory.AUTO_DEPLOY_DIR);
0275: mAutoInstallEnabled = checkConfigPermission(
0276: mInstallConfigSvcMBean,
0277: InstallationConfigurationFactory.ENABLE_AUTO_INSTALL);
0278: mAutoReinstallEnabled = checkConfigPermission(
0279: mInstallConfigSvcMBean,
0280: InstallationConfigurationFactory.ENABLE_AUTO_REINSTALL);
0281: mAutoUninstallEnabled = checkConfigPermission(
0282: mInstallConfigSvcMBean,
0283: InstallationConfigurationFactory.ENABLE_AUTO_UNINSTALL);
0284: // Glassfish handles autodeploy on its own
0285: if (mContext.getEnvironmentContext().getProvider() != JBIProvider.SUNAS) {
0286: mAutoDeployEnabled = checkConfigPermission(
0287: mDeployConfigSvcMBean,
0288: DeploymentConfigurationFactory.ENABLE_AUTO_DEPLOY);
0289: mAutoRedeployEnabled = checkConfigPermission(
0290: mDeployConfigSvcMBean,
0291: DeploymentConfigurationFactory.ENABLE_AUTO_REDEPLOY);
0292: mAutoUndeployEnabled = checkConfigPermission(
0293: mDeployConfigSvcMBean,
0294: DeploymentConfigurationFactory.ENABLE_AUTO_UNDEPLOY);
0295: }
0296:
0297: initDirectories(mAutoInstallEnabled, mAutoDeployEnabled);
0298:
0299: if (mAutoInstallEnabled) {
0300: performAutoInstall();
0301: // only perform autouninstall if autoinstall is also enabled
0302: if (mAutoUninstallEnabled) {
0303: performAutoUninstall();
0304: // only perform autoreinstall if autoinstall and autouninstall
0305: // are also enabled
0306: if (mAutoUninstallEnabled) {
0307: performAutoReinstall();
0308: }
0309: }
0310: }
0311:
0312: if (mAutoDeployEnabled) {
0313: performAutoDeploy();
0314: // only perform autoundeploy if autodeploy is also enabled
0315: if (mAutoUndeployEnabled) {
0316: performAutoUndeploy();
0317: // only perform autoredeploy if autodeploy and autoundeploy
0318: // are also enabled
0319: if (mAutoRedeployEnabled) {
0320: performAutoRedeploy();
0321: }
0322: }
0323: }
0324: }
0325:
0326: /**
0327: * Process autoinstall directory for new files.
0328: * @throws Exception unexpectedly.
0329: */
0330: public void performAutoInstall() {
0331: File installFile;
0332: while ((installFile = pollAutoDirectory(PollFunction.NEW_FILES,
0333: mAutoInstallDir, mInstallTimestampsDir)) != null) {
0334: doInstall(installFile);
0335: }
0336: }
0337:
0338: /**
0339: * Routine called by both performAutoInstall() and performAutoReinstall()
0340: * to do the installation of a specific component file.
0341: * @param installFile the File to install.
0342: */
0343: private void doInstall(File installFile) {
0344: Archive installArchive;
0345: String componentName;
0346:
0347: try {
0348: // create timestamp for this file -- copy time from existing one
0349: String fileName = installFile.getName();
0350: File timeStamp = new File(mInstallTimestampsDir, fileName);
0351: timeStamp.createNewFile();
0352: timeStamp.setLastModified(installFile.lastModified());
0353:
0354: installArchive = new Archive(installFile, true);
0355: if (installArchive.getType().equals(ArchiveType.COMPONENT)) {
0356: componentName = installComponent(installFile
0357: .getAbsolutePath());
0358: // store the name in an empty file
0359: File storedNameFile = new File(mInstallTimestampsDir,
0360: fileName + COMP_DELIMITER + componentName);
0361: if (null != componentName) {
0362: storedNameFile.createNewFile();
0363: storedNameFile.setLastModified(installFile
0364: .lastModified());
0365: }
0366: } else if (installArchive.getType().equals(
0367: ArchiveType.SHARED_LIBRARY)) {
0368: componentName = installSharedLibrary(installFile
0369: .getAbsolutePath());
0370: // store the name in an empty file
0371: File storedNameFile = new File(mInstallTimestampsDir,
0372: fileName + SL_DELIMITER + componentName);
0373: if (null != componentName) {
0374: storedNameFile.createNewFile();
0375: storedNameFile.setLastModified(installFile
0376: .lastModified());
0377: }
0378: } else if (installArchive.getType().equals(
0379: ArchiveType.SERVICE_ASSEMBLY)) {
0380: removeInstallLogs(installFile.getAbsolutePath());
0381: writeLog(
0382: installFile.getAbsolutePath() + INSTALL_FAILURE,
0383: mTranslator
0384: .getString(LocalStringKeys.AA_DEPLOY_NOT_SUPPORTED));
0385: }
0386: } catch (Exception ex) {
0387: removeInstallLogs(installFile.getAbsolutePath());
0388: writeLog(installFile.getAbsolutePath() + INSTALL_FAILURE,
0389: ex.toString());
0390: }
0391: }
0392:
0393: /**
0394: * Process autodeploy directory for new files.
0395: * @throws Exception unexpectedly.
0396: */
0397: public void performAutoDeploy() {
0398: File deployFile;
0399:
0400: while ((deployFile = pollAutoDirectory(PollFunction.NEW_FILES,
0401: mAutoDeployDir, mDeployTimestampsDir)) != null) {
0402: doDeploy(deployFile);
0403: }
0404: }
0405:
0406: /**
0407: * Routine called by both performAutoDeploy() and performAutoRedeploy()
0408: * to do the deployment of a specific service assembly
0409: * @param deployFile the File to install.
0410: */
0411: private void doDeploy(File deployFile) {
0412: Archive deployArchive;
0413: String componentName;
0414:
0415: try {
0416: // create timestamp for this file -- copy time from existing one
0417: String fileName = deployFile.getName();
0418: File timeStamp = new File(mDeployTimestampsDir, fileName);
0419: timeStamp.createNewFile();
0420: timeStamp.setLastModified(deployFile.lastModified());
0421:
0422: deployArchive = new Archive(deployFile, true);
0423: if (deployArchive.getType().equals(
0424: ArchiveType.SERVICE_ASSEMBLY)) {
0425: String serviceAssemblyName = deployArchive.getJbiName();
0426: deployServiceAssembly(serviceAssemblyName, deployFile
0427: .getAbsolutePath());
0428: // store the name in an empty file
0429: File storedNameFile = new File(mDeployTimestampsDir,
0430: fileName + DELIMITER + serviceAssemblyName);
0431: if (null != storedNameFile) {
0432: storedNameFile.createNewFile();
0433: storedNameFile.setLastModified(deployFile
0434: .lastModified());
0435: }
0436:
0437: } else {
0438: removeDeployLogs(deployFile.getAbsolutePath());
0439: writeLog(
0440: deployFile.getAbsolutePath() + DEPLOY_FAILURE,
0441: mTranslator
0442: .getString(LocalStringKeys.AA_INSTALL_NOT_SUPPORTED));
0443: }
0444: } catch (Exception ex) {
0445: removeDeployLogs(deployFile.getAbsolutePath());
0446: writeLog(deployFile.getAbsolutePath() + DEPLOY_FAILURE, ex
0447: .toString());
0448: }
0449: }
0450:
0451: /**
0452: * Process autoinstall directory for deleted files.
0453: * @throws Exception unexpectedly.
0454: */
0455: public void performAutoUninstall() {
0456: File deletedFile;
0457:
0458: while ((deletedFile = pollAutoDirectory(
0459: PollFunction.DELETED_FILES, mAutoInstallDir,
0460: mInstallTimestampsDir)) != null) {
0461: doUninstall(deletedFile);
0462: }
0463: }
0464:
0465: /**
0466: * Routine called by both performAutoUninstall() and performAutoReinstall()
0467: * to do the uninstallation of a specific component file.
0468: * @param deletedFile the File to uninstall.
0469: * @returns true iff the uninstall was successful.
0470: */
0471: private boolean doUninstall(File deletedFile) {
0472: String fileName = null;
0473:
0474: try {
0475: // delete timestamp for this file
0476: fileName = deletedFile.getName();
0477: mLogger.finer("doUninstall() deleting file " + fileName);
0478: deletedFile.delete();
0479:
0480: // find the file (if present) that specified if this was a
0481: // shared library or component, and what its name was.
0482: for (File deletedData : mInstallTimestampsDir
0483: .listFiles(new NamedFileFinder(fileName))) {
0484: deletedData.delete();
0485: mLogger.finer("doUninstall() on "
0486: + deletedData.getName());
0487: String cSuffix = suffix(deletedData.getName(), fileName
0488: + COMP_DELIMITER);
0489: String slSuffix = suffix(deletedData.getName(),
0490: fileName + SL_DELIMITER);
0491: if (null != cSuffix) {
0492: uninstallComponent(cSuffix);
0493: }
0494: if (null != slSuffix) {
0495: uninstallSharedLibrary(slSuffix);
0496: }
0497: }
0498: // put new log file in mAutoInstallDir, not timestamp dir.
0499: fileName = mAutoInstallDir.getAbsolutePath()
0500: + File.separator + fileName;
0501: removeInstallLogs(fileName);
0502: writeLog(fileName + UNINSTALL_SUCCESS, "");
0503: return true;
0504: } catch (Exception ex) {
0505: if (null != fileName) {
0506: // put new log file in mAutoInstallDir, not timestamp dir.
0507: fileName = mAutoInstallDir.getAbsolutePath()
0508: + File.separator + fileName;
0509: removeInstallLogs(fileName);
0510: writeLog(fileName + UNINSTALL_FAILURE, ex.toString());
0511: }
0512: return false;
0513: }
0514: }
0515:
0516: /**
0517: * Process autodeploy directory for deleted files.
0518: * @throws Exception unexpectedly.
0519: */
0520: public void performAutoUndeploy() {
0521: File deletedFile;
0522:
0523: while ((deletedFile = pollAutoDirectory(
0524: PollFunction.DELETED_FILES, mAutoDeployDir,
0525: mDeployTimestampsDir)) != null) {
0526: doUndeploy(deletedFile);
0527: }
0528: }
0529:
0530: /**
0531: * Routine called by both performAutoUndeploy() and performAutoRedeploy()
0532: * to do the undeployment of a specific service assembly.
0533: * @param deletedFile the File to undeploy.
0534: * @returns true iff the undeploy was successful.
0535: */
0536: private boolean doUndeploy(File deletedFile) {
0537: String fileName = null;
0538: boolean results = true;
0539:
0540: try {
0541: // delete timestamp for this file
0542: fileName = deletedFile.getName();
0543: mLogger.finer("doUndeploy() deleting file " + fileName);
0544: deletedFile.delete();
0545:
0546: // find the file (if present) that specified
0547: // the name of the deployed service assembly.
0548: for (File deletedData : mDeployTimestampsDir
0549: .listFiles(new NamedFileFinder(fileName))) {
0550: deletedData.delete();
0551: mLogger.finer("doUndeploy() on "
0552: + deletedData.getName());
0553: String saName = suffix(deletedData.getName(), fileName
0554: + DELIMITER);
0555: if (null != saName) {
0556: results = undeployServiceAssembly(saName);
0557: }
0558: }
0559: // put new log file in mAutoDeployDir, not timestamp dir.
0560: fileName = mAutoDeployDir.getAbsolutePath()
0561: + File.separator + fileName;
0562: removeDeployLogs(fileName);
0563: writeLog(fileName + UNDEPLOY_SUCCESS, "");
0564: return results;
0565: } catch (Exception ex) {
0566: if (null != fileName) {
0567: // put new log file in mAutoDeployDir, not timestamp dir.
0568: fileName = mAutoDeployDir.getAbsolutePath()
0569: + File.separator + fileName;
0570: removeDeployLogs(fileName);
0571: writeLog(fileName + UNDEPLOY_FAILURE, ex.toString());
0572: }
0573: return false;
0574: }
0575: }
0576:
0577: /**
0578: * Process autoinstall directory for updated files.
0579: * @throws java.io.IOException unexpectedly.
0580: */
0581: public void performAutoReinstall() throws java.io.IOException {
0582: File updatedFile;
0583:
0584: while ((updatedFile = pollAutoDirectory(
0585: PollFunction.UPDATED_FILES, mAutoInstallDir,
0586: mInstallTimestampsDir)) != null) {
0587: String fileName = updatedFile.getName();
0588: File timeStamp = new File(mInstallTimestampsDir, fileName);
0589:
0590: if (doUninstall(timeStamp)) {
0591: doInstall(updatedFile);
0592: } else {
0593: // change the timestamp of our status file so that we do not
0594: // try to install the new version of the file
0595: timeStamp.createNewFile(); // it was deleted by doUninstall().
0596: timeStamp.setLastModified(updatedFile.lastModified());
0597: }
0598: }
0599: }
0600:
0601: /**
0602: * Process autodeploy directory for updated files.
0603: * @throws java.io.IOException unexpectedly.
0604: */
0605: public void performAutoRedeploy() throws java.io.IOException {
0606: File updatedFile;
0607:
0608: while ((updatedFile = pollAutoDirectory(
0609: PollFunction.UPDATED_FILES, mAutoDeployDir,
0610: mDeployTimestampsDir)) != null) {
0611: String fileName = updatedFile.getName();
0612: File timeStamp = new File(mDeployTimestampsDir, fileName);
0613:
0614: if (doUndeploy(timeStamp)) {
0615: doDeploy(updatedFile);
0616: } else {
0617: // change the timestamp of our status file so that we do not
0618: // try to deploy the new version of the file
0619: timeStamp.createNewFile(); // it was deleted by doUndeploy().
0620: timeStamp.setLastModified(updatedFile.lastModified());
0621: }
0622: }
0623: }
0624:
0625: /**
0626: * Routine to parse the result of an install or deploy operation.
0627: * @param aResultString the task result result to parse.
0628: * @return true iff the task was executed successfully.
0629: *
0630: */
0631: private boolean parseResultAsSuccess(String aResultString) {
0632: Document doc;
0633: Text resultText;
0634:
0635: try {
0636: doc = getDocument(new InputSource((new StringReader(
0637: aResultString))));
0638: resultText = (Text) XPathAPI
0639: .selectNodeList(
0640: doc,
0641: "jbi-task/jbi-task-result/frmwk-task-result/"
0642: + "frmwk-task-result-details/task-result-details/task-result")
0643: .item(0).getFirstChild();
0644: return ("SUCCESS".equalsIgnoreCase(resultText.getData()
0645: .trim()));
0646: } catch (Throwable t) {
0647: // by default, consider the operation as a failure.
0648: t.printStackTrace();
0649: return false;
0650: }
0651: }
0652:
0653: /** Synchronized wrapper for non-thread-safe JAXP DocumentBuilder. */
0654: private synchronized Document getDocument(InputSource source)
0655: throws Exception {
0656: if (mDocBuilder == null) {
0657: DocumentBuilderFactory dbf = DocumentBuilderFactory
0658: .newInstance();
0659: dbf.setValidating(false);
0660: mDocBuilder = dbf.newDocumentBuilder();
0661: }
0662:
0663: return mDocBuilder.parse(source);
0664: }
0665:
0666: /** Install a component.
0667: * @param location path to the component installation archive
0668: * @return the name of the component
0669: */
0670: private String installComponent(String location) {
0671: ObjectName installerMBean;
0672: ObjectName lifecycleMBean = null;
0673: String compId = null;
0674: String errorMsg = "";
0675: boolean installSuccessful;
0676:
0677: // Autoinstall consists of two phases:
0678: // Phase 1: installation
0679: // Phase 2: installer clean-up and starting the installed component
0680: // A failure is phase 1 is considered a failed installation. A failure
0681: // in phase 2 is considered a success, but any error information is
0682: // included in the success log file.
0683:
0684: // Phase 1: installation
0685: try {
0686: // load the component's installer MBean
0687: installerMBean = (ObjectName) mContext.getMBeanServer()
0688: .invoke(mInstallationMBean, "loadNewInstaller",
0689: new Object[] { location },
0690: new String[] { "java.lang.String" });
0691:
0692: // get the component id
0693: compId = installerMBean.getKeyProperty(mContext
0694: .getMBeanNames().COMPONENT_ID_KEY);
0695:
0696: // install the component using its installer MBean
0697: lifecycleMBean = (ObjectName) mContext.getMBeanServer()
0698: .invoke(installerMBean, "install", new Object[] {},
0699: new String[] {});
0700:
0701: installSuccessful = true;
0702: } catch (Exception ex) {
0703: installSuccessful = false;
0704: errorMsg = ex.getMessage();
0705: }
0706:
0707: // Phase 2: clean-up and start
0708: try {
0709: // If the installer was loaded, we need to clean it up
0710: if (compId != null) {
0711: mContext.getMBeanServer().invoke(mInstallationMBean,
0712: "unloadInstaller",
0713: new Object[] { compId, !installSuccessful },
0714: new String[] { "java.lang.String", "boolean" });
0715: }
0716:
0717: // Only start the component if the installation was successful
0718: if (installSuccessful && lifecycleMBean != null) {
0719: mContext.getMBeanServer().invoke(lifecycleMBean,
0720: "start", new Object[] {}, new String[] {});
0721: }
0722: } catch (Exception ex) {
0723: errorMsg = ex.getMessage();
0724: }
0725:
0726: removeInstallLogs(location);
0727: writeLog(location
0728: + (installSuccessful ? INSTALL_SUCCESS
0729: : INSTALL_FAILURE), errorMsg);
0730: return compId;
0731: }
0732:
0733: /** Uninstall a component.
0734: * @param componentName the name of the component to uninstall
0735: * @throws Exception unexpectedly.
0736: */
0737: private void uninstallComponent(String componentName)
0738: throws Exception {
0739: ObjectName adminMBean;
0740: ObjectName lifecycleMBean;
0741: ObjectName installerMBean;
0742:
0743: adminMBean = mContext
0744: .getMBeanNames()
0745: .getSystemServiceMBeanName(
0746: MBeanNames.ServiceName.AdminService,
0747: MBeanNames.ServiceType.Admin,
0748: mContext.getEnvironmentContext()
0749: .getPlatformContext().getInstanceName());
0750:
0751: // load the component's lifecycle MBean
0752: lifecycleMBean = (ObjectName) mContext.getMBeanServer().invoke(
0753: adminMBean, "getComponentByName",
0754: new Object[] { componentName },
0755: new String[] { "java.lang.String" });
0756:
0757: // invoke shutdown on the component lifecycle
0758: if (lifecycleMBean == null) {
0759: // the component is not installed
0760: mLogger.finer("No need to autouninstall component "
0761: + componentName
0762: + ", as it has already been uninstalled.");
0763: return;
0764: }
0765:
0766: mContext.getMBeanServer().invoke(lifecycleMBean, "shutDown",
0767: new Object[] {}, new String[] {});
0768:
0769: // create a new installer MBean for the component
0770: installerMBean = (ObjectName) mContext.getMBeanServer().invoke(
0771: mInstallationMBean, "loadInstaller",
0772: new Object[] { componentName },
0773: new String[] { "java.lang.String" });
0774:
0775: // invoke uninstall on that MBean
0776: lifecycleMBean = (ObjectName) mContext.getMBeanServer().invoke(
0777: installerMBean, "uninstall", new Object[] {},
0778: new String[] {});
0779:
0780: // now clean up using the unloadInstaller call
0781: mContext.getMBeanServer().invoke(mInstallationMBean,
0782: "unloadInstaller",
0783: new Object[] { componentName, true },
0784: new String[] { "java.lang.String", "boolean" });
0785: }
0786:
0787: /** Undeploy a service assembly.
0788: * @param saName the name of the service assembly to undeploy
0789: * @throws Exception unexpectedly.
0790: */
0791: private boolean undeployServiceAssembly(String saName)
0792: throws Exception {
0793: String results = null;
0794: String state = "not found";
0795:
0796: boolean deployed = getRegistry().getGenericQuery()
0797: .isServiceAssemblyDeployed(saName);
0798: if (!deployed) {
0799: return true;
0800: }
0801:
0802: try {
0803: state = (String) mContext.getMBeanServer().invoke(
0804: mDeploymentMBean, "getState",
0805: new Object[] { saName },
0806: new String[] { "java.lang.String" });
0807: } catch (Exception e) {
0808: mLogger.finer("getState(" + saName + ") threw " + e + ".");
0809: return true;
0810: }
0811:
0812: // if it's already shut down, don't reshut it down
0813: if (state.equalsIgnoreCase(DeploymentServiceMBean.STARTED)
0814: || state
0815: .equalsIgnoreCase(DeploymentServiceMBean.STOPPED)) {
0816: // shutDown will invoke stop when needed
0817: mContext.getMBeanServer().invoke(mDeploymentMBean,
0818: "shutDown", new Object[] { saName },
0819: new String[] { "java.lang.String" });
0820: }
0821:
0822: results = (String) mContext.getMBeanServer().invoke(
0823: mDeploymentMBean, "undeploy", new Object[] { saName },
0824: new String[] { "java.lang.String" });
0825:
0826: return parseResultAsSuccess(results);
0827: }
0828:
0829: /** Install a shared library.
0830: * @param location path to the shared library installation archive
0831: * @return the name of the shared library
0832: */
0833: private String installSharedLibrary(String location) {
0834: String slId = null;
0835: try {
0836: // install the shared library
0837: slId = (String) mContext.getMBeanServer().invoke(
0838: mInstallationMBean, "installSharedLibrary",
0839: new Object[] { location },
0840: new String[] { "java.lang.String" });
0841:
0842: removeInstallLogs(location);
0843: writeLog(location + INSTALL_SUCCESS, "");
0844: } catch (Exception ex) {
0845: removeInstallLogs(location);
0846: writeLog(location + INSTALL_FAILURE, ex.getMessage());
0847: }
0848: return slId;
0849: }
0850:
0851: /** Uninstall a shared library.
0852: * @param slName name of the shared library
0853: * @throws Exception unexpectedly.
0854: */
0855: private void uninstallSharedLibrary(String slName) throws Exception {
0856: boolean installed = getRegistry().getGenericQuery()
0857: .isSharedLibraryInstalled(slName);
0858: if (installed) {
0859: mContext.getMBeanServer().invoke(mInstallationMBean,
0860: "uninstallSharedLibrary", new Object[] { slName },
0861: new String[] { "java.lang.String" });
0862: }
0863: }
0864:
0865: /** Deploy a service assembly.
0866: * @param saName service assembly name
0867: * @param location path to the service assembly archive
0868: */
0869: private void deployServiceAssembly(String saName, String location) {
0870: boolean deploySuccessful;
0871: String result;
0872:
0873: // Autodeploy consists of two phases:
0874: // Phase 1: deployment
0875: // Phase 2: starting the deploy service assembly
0876: // A failure is phase 1 is considered a failed deployment. A failure
0877: // in phase 2 is considered a success, but any error information is
0878: // included in the success log file.
0879:
0880: // Phase 1: deployment
0881: try {
0882: // deploy the service assembly
0883: result = (String) mContext.getMBeanServer().invoke(
0884: mDeploymentMBean, "deploy",
0885: new Object[] { location },
0886: new String[] { "java.lang.String" });
0887:
0888: deploySuccessful = parseResultAsSuccess(result);
0889: } catch (Exception ex) {
0890: deploySuccessful = false;
0891: result = ex.getMessage();
0892: }
0893:
0894: // Phase 2: start the assembly
0895: if (deploySuccessful) {
0896: try {
0897: result = (String) mContext.getMBeanServer().invoke(
0898: mDeploymentMBean, "start",
0899: new Object[] { saName },
0900: new String[] { "java.lang.String" });
0901: } catch (Exception ex) {
0902: result = ex.getMessage();
0903: }
0904: }
0905:
0906: removeDeployLogs(location);
0907: writeLog(location
0908: + (deploySuccessful ? DEPLOY_SUCCESS : DEPLOY_FAILURE),
0909: result);
0910: }
0911:
0912: /** Creates a log file with the specified message. The caller is
0913: * responsible for creating a path with a .success or .failed suffix
0914: * consistent with the content of the message.
0915: */
0916: private void writeLog(String path, String message) {
0917: FileOutputStream fos = null;
0918: JBIManagementMessage prettyMessage = JBIManagementMessage
0919: .createJBIManagementMessage(message);
0920:
0921: // use JBIManagementMessage to pretty print the XML (if possible)
0922: if (prettyMessage != null) {
0923: message = prettyMessage.getMessage();
0924: }
0925:
0926: try {
0927: fos = new FileOutputStream(path);
0928: fos.write(message.getBytes());
0929: fos.flush();
0930: } catch (java.io.IOException ioEx) {
0931: ioEx.printStackTrace();
0932: } finally {
0933: if (fos != null) {
0934: try {
0935: fos.close();
0936: } catch (Exception ex) {
0937: }
0938: }
0939: }
0940: }
0941:
0942: /** Checks the autoinstall or autodeploy directory for candidate files. If a
0943: * file is found, we check the file suffix (to make sure we are not trying
0944: * to install or deploy a status file), and we also check that an existing
0945: * timestamp file doesn't already exist, with the same filename.
0946: *
0947: * @param queryType (enum) the type of file we are polling for.
0948: * @param topLevelDir the directory to scan for candidate files.
0949: * @param statusDir the directory for timestamp files (to exclude matches).
0950: * @return a File that is a *not* a status file, nor that already exists
0951: * in the status directory.
0952: */
0953: synchronized File pollAutoDirectory(PollFunction queryType,
0954: File topLevelDir, File statusDir) {
0955: File candidate = null;
0956:
0957: if (queryType == PollFunction.NEW_FILES) {
0958: if (topLevelDir != null && topLevelDir.isDirectory()) {
0959: mLogger.finest("pollAutoDirectory(new) called on "
0960: + topLevelDir);
0961: for (File archive : topLevelDir.listFiles()) {
0962: if (archive.isFile()) {
0963: String fileName = archive.getName();
0964: mLogger
0965: .finest("pollAutoDirectory(new) Found file: "
0966: + fileName);
0967: String fileType = fileName.substring(fileName
0968: .lastIndexOf(".") + 1);
0969: mLogger
0970: .finest("pollAutoDirectory(new): File type of the above is: "
0971: + fileType);
0972: if (fileType.indexOf("_") == -1) {
0973: File timeStamp = new File(statusDir,
0974: fileName);
0975: if (!timeStamp.exists()) {
0976: mLogger
0977: .finer("pollAutoDirectory(new): Ready to handle "
0978: + fileName);
0979: candidate = archive;
0980: break;
0981: }
0982: }
0983: }
0984: }
0985: }
0986: } else if (queryType == PollFunction.DELETED_FILES) {
0987: if (statusDir != null && statusDir.isDirectory()) {
0988: mLogger.finest("pollAutoDirectory(deleted) called on "
0989: + statusDir);
0990: for (File archive : statusDir.listFiles()) {
0991: if (archive.isFile()) {
0992: String fileName = archive.getName();
0993: mLogger
0994: .finest("pollAutoDirectory(deleted) Found file: "
0995: + fileName);
0996: String fileType = fileName.substring(fileName
0997: .lastIndexOf(".") + 1);
0998: mLogger
0999: .finest("pollAutoDirectory(deleted): File type of the above is: "
1000: + fileType);
1001: if ((fileType.indexOf("_") == -1)
1002: && (fileType.indexOf(DELIMITER) == -1)) {
1003: File topFile = new File(topLevelDir,
1004: fileName);
1005: if (!topFile.exists()) {
1006: mLogger
1007: .finer("pollAutoDirectory(deleted): Ready to handle "
1008: + fileName);
1009: candidate = archive;
1010: break;
1011: }
1012: }
1013: }
1014: }
1015: }
1016: } else if (queryType == PollFunction.UPDATED_FILES) {
1017: if (topLevelDir != null && topLevelDir.isDirectory()) {
1018: mLogger.finest("pollAutoDirectory(updated) called on "
1019: + topLevelDir);
1020: for (File archive : topLevelDir.listFiles()) {
1021: if (archive.isFile()) {
1022: String fileName = archive.getName();
1023: mLogger
1024: .finest("pollAutoDirectory(updated) Found file: "
1025: + fileName);
1026: String fileType = fileName.substring(fileName
1027: .lastIndexOf(".") + 1);
1028: mLogger
1029: .finest("pollAutoDirectory(updated): File type of the above is: "
1030: + fileType);
1031: if (fileType.indexOf("_") == -1) {
1032: File timeStamp = new File(statusDir,
1033: fileName);
1034: if (timeStamp.exists()
1035: && (archive.lastModified() > timeStamp
1036: .lastModified())) {
1037: mLogger
1038: .finer("pollAutoDirectory(updated): Ready to handle "
1039: + fileName);
1040: candidate = archive;
1041: break;
1042: }
1043: }
1044: }
1045: }
1046: }
1047: }
1048:
1049: return candidate;
1050: }
1051:
1052: /** Check the Configuration MBean for the specified Boolean property.
1053: * @param aConfigSvcName the name of the config service MBean to query.
1054: * @param aPermissionName is the name of the attribute to examine.
1055: * @return "true" or "false" as found in the attribute.
1056: */
1057: boolean checkConfigPermission(ObjectName aConfigSvcName,
1058: String aPermissionName) {
1059: try {
1060: // Query configuration server for permission bit.
1061: Object attr = mContext.getMBeanServer().getAttribute(
1062: aConfigSvcName, aPermissionName);
1063:
1064: return ((Boolean) attr).booleanValue();
1065: } catch (Exception e) {
1066: mLogger.finer("checkConfigPermission(" + aConfigSvcName
1067: + ", " + aPermissionName + ") returned " + e
1068: + ". Returning default 'false' value.");
1069: return false;
1070: }
1071: }
1072:
1073: /** Check the Configuration MBean for the specified String property.
1074: * @param aConfigSvcName the name of the config service MBean to query.
1075: * @param anAttributeName is the name of the attribute to examine.
1076: * @return the String value from the Configuration MBean attribute.
1077: */
1078: String getConfigAttribute(ObjectName aConfigSvcName,
1079: String anAttributeName) {
1080: try {
1081: Object attr = mContext.getMBeanServer().getAttribute(
1082: aConfigSvcName, anAttributeName);
1083:
1084: return (String) attr;
1085: } catch (Exception e) {
1086: mLogger.finer("checkConfigPermission(" + aConfigSvcName
1087: + ", " + anAttributeName + ") returned " + e
1088: + ". Returning default 'null' value.");
1089: return null;
1090: }
1091: }
1092:
1093: /** Initializes autoinstall and autodeploy directories.
1094: * @param isAutoInstallEnabled true iff the auto install permission bit set.
1095: * @param isAutoDeployEnabled true iff the auto deploy permission bit set.
1096: */
1097: void initDirectories(boolean isAutoInstallEnabled,
1098: boolean isAutoDeployEnabled) {
1099: // make sure all required directories exist
1100: if (isAutoInstallEnabled) {
1101: if (null != mAutoInstallDirName) {
1102: if (mAutoInstallDirName.startsWith(File.separator)
1103: || ":".equals(mAutoInstallDirName.substring(1,
1104: 2))) // C:/blah/blah
1105: {
1106: // treat the directory as an absolute path
1107: mAutoInstallDir = new File(mAutoInstallDirName);
1108: } else // test it as a relative path from the jbi install root
1109: {
1110: mAutoInstallDir = new File(mContext
1111: .getJbiInstallRoot(), mAutoInstallDirName);
1112: }
1113: mInstallTimestampsDir = new File(mAutoInstallDir,
1114: INSTALL_STATUS_DIR);
1115: if (!mInstallTimestampsDir.exists()) {
1116: mLogger.fine("initDirectories() creating "
1117: + mInstallTimestampsDir);
1118: mInstallTimestampsDir.mkdirs();
1119: }
1120: }
1121: }
1122:
1123: // make sure all required directories exist
1124: if (isAutoDeployEnabled) {
1125: if (null != mAutoDeployDirName) {
1126: if (mAutoDeployDirName.startsWith(File.separator)
1127: || ":".equals(mAutoDeployDirName
1128: .substring(1, 2))) // C:/blah/blah
1129: {
1130: // treat the directory as an absolute path
1131: mAutoDeployDir = new File(mAutoDeployDirName);
1132: } else // test it as a relative path from the jbi install root
1133: {
1134: mAutoDeployDir = new File(mContext
1135: .getJbiInstallRoot(), mAutoDeployDirName);
1136: }
1137: mDeployTimestampsDir = new File(mAutoDeployDir,
1138: DEPLOY_STATUS_DIR);
1139: if (!mDeployTimestampsDir.exists()) {
1140: mLogger.fine("initDirectories() creating "
1141: + mDeployTimestampsDir);
1142: mDeployTimestampsDir.mkdirs();
1143: }
1144: }
1145: }
1146: }
1147:
1148: /**
1149: * Return the suffix of the string (that comes after the prefix)
1150: * @param anInputString the string to return the suffix from
1151: * @param aPrefix the prefix to remove
1152: * @return the string starting after the prefix
1153: */
1154: private String suffix(String anInputString, String aPrefix) {
1155: String[] splitNames = anInputString.split(aPrefix, 2);
1156: try {
1157: return splitNames[1];
1158: } catch (java.lang.ArrayIndexOutOfBoundsException aioobe) {
1159: mLogger.finer("suffix(" + anInputString + ", " + aPrefix
1160: + ") threw " + aioobe);
1161: return null;
1162: }
1163: }
1164:
1165: /**
1166: * Remove all old install logs, in preparation for a new log to be written.
1167: * @param location the filename to base the log name on.
1168: */
1169: private void removeInstallLogs(String location) {
1170: try {
1171: File f1 = new File(location + INSTALL_SUCCESS);
1172: File f2 = new File(location + INSTALL_FAILURE);
1173: File f3 = new File(location + UNINSTALL_SUCCESS);
1174: File f4 = new File(location + UNINSTALL_FAILURE);
1175: f1.delete();
1176: f2.delete();
1177: f3.delete();
1178: f4.delete();
1179: } catch (Exception e) {
1180: mLogger.finer("removeInstallLogs(" + location + ") threw "
1181: + e);
1182: }
1183: }
1184:
1185: /**
1186: * Remove all old deploy logs, in preparation for a new log to be written.
1187: * @param location the filename to base the log name on.
1188: */
1189: private void removeDeployLogs(String location) {
1190: try {
1191: File f1 = new File(location + DEPLOY_SUCCESS);
1192: File f2 = new File(location + DEPLOY_FAILURE);
1193: File f3 = new File(location + UNDEPLOY_SUCCESS);
1194: File f4 = new File(location + UNDEPLOY_FAILURE);
1195: f1.delete();
1196: f2.delete();
1197: f3.delete();
1198: f4.delete();
1199: } catch (Exception e) {
1200: mLogger.finer("removeDeployLogs(" + location + ") threw "
1201: + e);
1202: }
1203: }
1204:
1205: /**
1206: * Get a handle to the registry
1207: *
1208: * @return the persisted registry instance
1209: */
1210: private com.sun.jbi.management.registry.Registry getRegistry() {
1211: return (com.sun.jbi.management.registry.Registry) mContext
1212: .getEnvironmentContext().getRegistry();
1213: }
1214:
1215: }
|