Package com.adito.extensions

Source Code of com.adito.extensions.ExtensionBundle

        /*
*  Adito
*
*  Copyright (C) 2003-2006 3SP LTD. All Rights Reserved
*
*  This program is free software; you can redistribute it and/or
*  modify it under the terms of the GNU General Public License
*  as published by the Free Software Foundation; either version 2 of
*  the License, or (at your option) any later version.
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public
*  License along with this program; if not, write to the Free Software
*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
     
package com.adito.extensions;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdom.Attribute;
import org.jdom.DataConversionException;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import com.adito.boot.Util;
import com.adito.boot.VersionInfo;
import com.adito.boot.VersionInfo.Version;
import com.adito.extensions.store.ExtensionStore;
import com.adito.extensions.types.Plugin;
import com.adito.extensions.types.PluginType;

/**
* Extension bundles describe a collection of <i>Extension Descriptors</i>.
* <p>
* A bundle may come from one of two places, either the <i>Adito Application Store</i>
* or from an installed extension bundle retrieved via the <i>Repository</i>.
* <p>
* If from the Adito Application Store, the descriptor will not contain all
* details, only enough to determine the name, description, versions,
* dependencies and a few others pieces of information. Such bundles do not have
* a life cycle in the way local extension bundles do (i.e. be <i>Started</i>,
* <i>Stopped</i> or <i>Activated</i>).
* <p>
* Local extension bundles must go through 3 or 4 phases.
* <ul>
* <li>Phase 1. Loading. The XML extension descriptors are loaded and parsed.
* No change the state of Adito is made at this stage. Once this is
* complete we know the order the extensions should be started</li>
* <li>Phase 2. Starting. All extensions now have their
* {@link ExtensionDescriptor#start()} method called. This in turn delegates the
* start to the <i>Extension Type</i> implementation in use. For example, the
* {@link PluginType} would create the plug-in instance and invoke the
* {@link Plugin#startPlugin(com.adito.extensions.types.PluginDefinition, ExtensionDescriptor, Element)}.
* If starting fails, an exception is thrown and the extension will be
* <i>Stopped</i>. method on it.</li>
* <li>Phase 3. Activation. Only the <i>Plug-ins</i> really use this as they
* require two phases of initialisation. If activate fails, an exception is
* thrown and the extension will be <i>Stopped</i>. </li>
* <li>Phase 4. Stopping. May occur either after <i>Starting</i> or
* <i>Activation</i>. During this phase the extension should clean up as much
* as possible (deregister property definitions, user databases or any other
* extension point).
* </ul>
*/
public class ExtensionBundle extends ArrayList<ExtensionDescriptor> implements Comparable {

  final static Log log = LogFactory.getLog(ExtensionBundle.class);

  /**
   * Extension 'type' code indicating a new version is available from the Adito
   * Application Store
   */
  public static final int TYPE_UPDATEABLE = 0;

  /**
   * Extension 'type' code indicating the most up to date version in Adito
   * Application Store is already correctly installed
   */
  public static final int TYPE_INSTALLED = 1;

  /**
   * Extension 'type' code indicating the bundle is not currently installed
   * but available from the Adito Application Store
   */
  public static final int TYPE_INSTALLABLE = 2;

  /**
   * Extension 'type' code indicating the bundle is not an installable bundle,
   * merely a pointer to further instructions as to how to create a complete
   * bundle (this is for bundles that we cannot legally distribute all
   * components)
   */
  public static final int TYPE_CONFIGUREABLE = 3;

  /**
   * Extension 'type' code indicating the bundle has been removed by the
   * administrator but cannot yet be deleted from the local file system as it
   * contains plug-ins that are in use.
   */
  public static final int TYPE_PENDING_REMOVAL = 4;

  /**
   * Extension 'type' code indicating a new bundle has been installed but
   * cannot be started because it contains plug-ins. The administrator should
   * restart the entire server to complete the installation.
   */
  public static final int TYPE_PENDING_INSTALLATION = 5;

  /**
   * Extension 'type' code indicating a bundle has been updated but cannot be
   * restarted because it contains plug-ins. The administrator should restart
   * the entire server to complete the update.
   */
  public static final int TYPE_PENDING_UPDATE = 6;

  /**
   * Extension 'type' code indicating a bundle state has been changed
   * (i.e. enable or disable) but cannot be restarted because it contains
   * plug-ins. The administrator should restart the entire server to complete
   * the change.
   */
  public static final int TYPE_PENDING_STATE_CHANGE = 7;

  /**
   * Status of extension bundle
   */
  public enum ExtensionBundleStatus {
    /**
     * The extension is enabled, but stopped
     */
    ENABLED(0, "enabled"),

    /**
     * The extension is disabled
     */
    DISABLED(1, "disabled"),

    /**
     * The extension has been disabled by the system (cannot be enabled
     */
    SYSTEM_DISABLED(2, "systemDisabled"),

    /**
     * The extension is enabled and started
     */
    STARTED(3, "started"),

    /**
     * The extension is enabled and activated
     */
    ACTIVATED(4, "activated"),

        /**
     * The extension is errored
     */
    ERROR(6, "error");

    private String name;

    private ExtensionBundleStatus(int state, String name) {
      this.name = name;
    }

    /**
     * Determine if the state is {@link #STARTED} or {@link #ACTIVATED}.
     *
     * @return started or activated
     */
    public boolean isStartedOrActivated() {
      return this == ACTIVATED || this == STARTED;
    }

    /**
     * Get the status name
     *
     * @return name
     */
    public String getName() {
      return name;
    }

    /**
     * @return boolean
     */
    public boolean isDisabled() {
      return this == DISABLED || this == SYSTEM_DISABLED;
    }
  }

  // Private instance variables

  private File descriptor;
  private Document doc;
  private String description;
  private String license;
  private String productURL;
  private String instructionsURL;
  private VersionInfo.Version version;
  private int type;
  private int order;
  private String id;
  private String name;
  private boolean startOnSetupMode;
  private String licenseFilePath;
  private VersionInfo.Version requiredHostVersion;
  private ExtensionInstaller installer;
  private String category;
  private boolean mandatoryUpdate;
  private ExtensionBundleStatus status = ExtensionBundleStatus.ENABLED;
  private Collection<String> dependencyNames;
  private Throwable error;
  private boolean hidden;
  private boolean devExtension;
  private Element messageElement;
  private String changes;
  private VersionInfo.Version updateVersion;
  private String platform = "";
  private String arch = "";

  /**
   * Constructor for when creating a bundle without having a XML extension
   * descriptor stream.
   *
   * @param version
   * @param type
   * @param id
   * @param name
   * @param description
   * @param license
   * @param productURL
   * @param instructionsURL
   * @param requiredHostVersion
   * @param dependencyNames collection of dependency names or
   *        <code>null</code> for no dependencies
   * @param category
   * @param mandatoryUpdate
   * @param order
   * @param changes
   * @param password
   * @param arch
   */
  public ExtensionBundle(Version version, int type, String id, String name, String description, String license,
              String productURL, String instructionsURL, VersionInfo.Version requiredHostVersion,
              Collection<String> dependencyNames, String category, boolean mandatoryUpdate, int order,
              String changes, String platform, String arch) {
    this.version = version;
    this.type = type;
    this.id = id;
    this.name = name;
    this.description = description;
    this.license = license;
    this.productURL = productURL;
    this.order = order;
    this.instructionsURL = instructionsURL;
    this.requiredHostVersion = requiredHostVersion;
    this.dependencyNames = dependencyNames;
    this.category = category;
    this.mandatoryUpdate = mandatoryUpdate;
    this.changes = changes;
    this.platform = platform;
    this.arch = arch;
   
  }

  /**
   * Constructor for creating a new bundle given a file that contains an XML
   * extension bundle descriptor.
   *
   * @param descriptor descriptor
   * @param devExtension loaded as dev extension
   */
  public ExtensionBundle(File descriptor, boolean devExtension) {
    this.descriptor = descriptor;
    this.devExtension = devExtension;
  }
 
  /**
   * Get if this bundle was loaded as a <i>devExtension</i>.
   *
   * @return dev extension
   */
  public boolean isDevExtension() {
    return devExtension;
  }

  /**
   * Get if this bundle is hidden
   *
   * @return hidden
   */
  public boolean isHidden() {
    return hidden;
  }

  /**
   * Get the extension bundle ID.
   *
   * @return bundle ID
   */
  public String getId() {
    return id;
  }
 
  /**
   * Determines if the extension bundle is updateable.
   * @return boolean
   */
  public boolean isUpdateable() {
    return getType() == ExtensionBundle.TYPE_UPDATEABLE;
  }

  /**
   * Get the order. This determines which order the bundle will get loaded
   * started and activated in (in relative to other extensions). The lower the
   * number the earlier the extension should be loaded
   *
   * @return order
   */
  public int getOrder() {
    return order;
  }

  /**
   * Get the english name of this extension bundle.
   *
   * @return english name of bundle
   */
  public String getName() {
    return name;
  }

  /**
   * Get the extension descriptor file that represents this bundle. If the
   * bundle is not loaded locally (i.e. it came from the Adito Application
   * Store) then this will be <code>null</code>.
   *
   * @return extension descriptor file
   */
  public File getFile() {
    return descriptor;
  }

  /**
   * Get the category for this bundle. This is used in the extension manager
   * front end to group available extensions.
   *
   * @return category
   */
  public String getCategory() {
    return category;
  }

  /**
   * Get a collection of the names of the extensions bundles this bundle
   * depends on. If any of the dependencies are not satisfied the extension
   * may not be started. If there are no dependencies <code>null</code> will
   * be returned.
   *
   * @return extension bundle dependency names
   */
  public Collection<String> getDependencies() {
    return dependencyNames;
  }

  /**
   * Start all extension bundles. This method will start all extension
   * descriptors it contains and is the second phase in an extensions life
   * cycle (after loading).
   *
   * @throws ExtensionException if any bundle could not be started
   */
  public synchronized void start() throws ExtensionException {

    try {
      if (log.isInfoEnabled()) {
        log.info("Starting extension bundle " + getId());
      }

      // Check we are allowed to start this bundle
      if (getStatus() != ExtensionBundleStatus.ENABLED) {
        throw new ExtensionException(ExtensionException.INVALID_EXTENSION_BUNDLE_STATUS,
                getId(),
                "Bundle is not in enabled state.");
      }

      // Check this bundles dependencies are installed and started
      checkDependenciesStarted(this);

      // Start all extensions in this bundle
      ExtensionException ee = null;
      for (Iterator i = iterator(); i.hasNext();) {
        ExtensionDescriptor d = (ExtensionDescriptor) i.next();
        try {
          d.start();
         
          // Set any bundle messages
          setBundleMessages(d);
         
          status = ExtensionBundleStatus.STARTED;
        } catch (ExtensionException ex) {
          if (ee == null) {
            ee = ex;
          }
                }catch (Throwable t){
                    if (ee == null) {
                        ee = new ExtensionException(ExtensionException.INTERNAL_ERROR, t);
                    }
                }
      }
      if (ee != null) {
        throw ee;
      }
    } catch (ExtensionException ee) {
        log.error("Failed to start extension. ", ee);
      error = ee;
      status = ExtensionBundleStatus.ERROR;
      throw ee;
    }

    error = null;
  }

  private void setBundleMessages(ExtensionDescriptor d) throws ExtensionException {
    if(messageElement != null) {
      for (Iterator i2 = messageElement.getChildren().iterator(); i2.hasNext();) {
        Element el = (Element) i2.next();
        if (!el.getName().equals("message")) {
          throw new ExtensionException(ExtensionException.FAILED_TO_PROCESS_DESCRIPTOR,
                  "<messages> element may only contain <message> elements.");
        }
        String key = el.getAttributeValue("key");
        if (key == null) {
          throw new ExtensionException(ExtensionException.FAILED_TO_PROCESS_DESCRIPTOR,
                  "<message> element must have a key attribute.");
        }
        String aKey = "application." + d.getId() + "." + key;
        if (d.getMessageResources() != null) {
          if (!d.getMessageResources().isPresent(key)) {
            d.getMessageResources().setMessage(el.getAttributeValue("locale"), aKey, el.getText());
          }
        }
      }
    }
  }

  void checkDependenciesStarted(ExtensionBundle bundle) throws ExtensionException {
    if (bundle.getDependencies() != null) {
      for (String dep : bundle.getDependencies()) {
        if (!ExtensionStore.getInstance().isExtensionBundleLoaded(dep)) {
          throw new ExtensionException(ExtensionException.DEPENDENCY_NOT_INSTALLED, dep, getId());
        }
        ExtensionBundle depBundle = ExtensionStore.getInstance().getExtensionBundle(dep);
        if (!depBundle.getStatus().isStartedOrActivated()) {
          throw new ExtensionException(ExtensionException.DEPENDENCY_NOT_STARTED, dep, getId());
        }
        checkDependenciesStarted(depBundle);
      }
    }

  }

  void checkDependenciesActivated(ExtensionBundle bundle) throws ExtensionException {
    if (bundle.getDependencies() != null) {
      for (String dep : bundle.getDependencies()) {
        if (!ExtensionStore.getInstance().isExtensionBundleLoaded(dep)) {
          throw new ExtensionException(ExtensionException.DEPENDENCY_NOT_INSTALLED, dep, getId());
        }
        ExtensionBundle depBundle = ExtensionStore.getInstance().getExtensionBundle(dep);
        if (depBundle.getStatus() != ExtensionBundleStatus.ACTIVATED) {
          throw new ExtensionException(ExtensionException.DEPENDENCY_NOT_STARTED, dep, getId());
        }
        checkDependenciesActivated(depBundle);
      }
    }

  }

  /**
   * Activate all extension bundles. This method will active all extension
   * descriptors it contains and is the third phase in an extensions life
   * cycle (after starting).
   *
   * @throws ExtensionException if any bundle could not be activated
   */
  public synchronized void activate() throws ExtensionException {
    try {
      if (isContainsPlugin() && getStatus() != ExtensionBundleStatus.STARTED) {
        throw new ExtensionException(ExtensionException.INVALID_EXTENSION_BUNDLE_STATUS,
                getId(),
                "Bundle is not in started so cannot be activated.");
      }

      // Check this bundles dependencies are installed and started
      checkDependenciesActivated(this);
     
      ExtensionException ee = null;
      for (Iterator i = iterator(); i.hasNext();) {
        ExtensionDescriptor d = (ExtensionDescriptor) i.next();
        try {
          d.activate();
          status = ExtensionBundleStatus.ACTIVATED;
        } catch (ExtensionException ex) {
          if (ee == null) {
            ee = ex;
          }
        }catch (Throwable t){
                    if (ee == null) {
                        ee = new ExtensionException(ExtensionException.INTERNAL_ERROR, t);
                    }
                }
      }
      if (ee != null) {
        throw ee;
      }
    } catch (ExtensionException ee) {
            log.error("Failed to activate extension bundle. ", ee);
            error = ee;
            status = ExtensionBundleStatus.ERROR;
            throw ee;
    }
    error = null;
  }

  /**
   * Stop all extension bundles. This method will active all extension
   * descriptors it contains and is the second or third phase in an extensions
   * life cycle (after starting or activating).
   *
   * @throws ExtensionException if any bundle could not be stopped
   */
  public synchronized void stop() throws ExtensionException {
    ExtensionException ee = null;
    try {
      for (Iterator i = iterator(); i.hasNext();) {
        ExtensionDescriptor d = (ExtensionDescriptor) i.next();
        try {
          d.stop();
        } catch (ExtensionException ex) {
          if (ee == null) {
            ee = ex;
          }
          log.error("Failed to stop extension bundle. ", ex);
        }
      }
      if (ee != null) {
        throw ee;
      }
    } finally {
      status = ExtensionBundleStatus.ENABLED;
    }
  }

  /**
   * Stop all extension bundles. This method will load all extension
   * descriptors it contains and is the first phase in an extensions life
   * cycle.
   *
   * @throws ExtensionException on any error loading bundles
   */
  public synchronized void load() throws ExtensionException {

    try {
      if (log.isInfoEnabled()) {
        log.info("Loading bundle from " + getFile().getAbsolutePath());
      }

      installer = new ExtensionInstaller(this);
      SAXBuilder sax = new SAXBuilder();
      try {
        doc = sax.build(descriptor);
      } catch (JDOMException jde) {
        jde.printStackTrace();
        throw new ExtensionException(ExtensionException.FAILED_TO_PARSE_DESCRIPTOR, jde);
      } catch (IOException ioe) {
        throw new ExtensionException(ExtensionException.INTERNAL_ERROR, ioe,  "Failed to load descriptor for parsing.");
      }

      hidden = "true".equals(doc.getRootElement().getAttributeValue("hidden"));
      license = doc.getRootElement().getAttributeValue("license");
      license = license == null || license.equals("") ? "Unknown" : license;
      if (log.isDebugEnabled())
        log.debug("Application bundle license is " + license);

      productURL = doc.getRootElement().getAttributeValue("productURL");
      instructionsURL = doc.getRootElement().getAttributeValue("instructionsURL");

      // Dependencies if any
      dependencyNames = null;
      String dependencies = doc.getRootElement().getAttributeValue("dependencies");
      if (dependencies != null) {
        log.warn("DEPRECATED. dependencies attribute in bundle " + getFile().getAbsolutePath()
          + " should now use 'depends'.");
      } else {
        dependencies = doc.getRootElement().getAttributeValue("depends");
      }
      if (!Util.isNullOrTrimmedBlank(dependencies)) {
        dependencyNames = Arrays.asList(dependencies.split(","));
      }

      // Get the required host version
      String requiredHostVersionString = doc.getRootElement().getAttributeValue("requiredHostVersion");
      if (requiredHostVersionString != null && !"any".equalsIgnoreCase(requiredHostVersionString)) {
        requiredHostVersion = new VersionInfo.Version(requiredHostVersionString);
        int dif = requiredHostVersion.compareTo(VersionInfo.getVersion());
        if (dif > 0)
          throw new ExtensionException(ExtensionException.INSUFFICIENT_ADITO_HOST_VERSION,
                  getName(),
                  requiredHostVersionString);

      } else {
        requiredHostVersion = null;
      }

      String ver = doc.getRootElement().getAttributeValue("version");
      if (ver == null || ver.equals("")) {
        throw new ExtensionException(ExtensionException.FAILED_TO_PROCESS_DESCRIPTOR,
                "<applications> element requires the attribute 'version'.");
      }
      version = new VersionInfo.Version(ver);

      if (doc.getRootElement().getName().equals("bundle")) {

        Attribute a = doc.getRootElement().getAttribute("id");
        id = a == null ? null : a.getValue();

        if (id == null) {
          throw new ExtensionException(ExtensionException.FAILED_TO_PROCESS_DESCRIPTOR,
                  "<bundle> element requires attribute 'id'");
        }
        if (log.isDebugEnabled())
          log.debug("Application bundle id is " + id);

        name = doc.getRootElement().getAttribute("name").getValue();
        if (log.isDebugEnabled())
          log.debug("Application bundle name is " + name);

        Attribute orderAttr = doc.getRootElement().getAttribute("order");
        if (orderAttr == null) {
          log.warn("<bundle> element in " + getFile().getPath() + " now requires attribute 'order'. Assuming 99999");
          order = 99999;
        } else {
          try {
            order = orderAttr.getIntValue();
          } catch (DataConversionException dce) {
            throw new ExtensionException(ExtensionException.FAILED_TO_PROCESS_DESCRIPTOR,
                    "'order' attribute is invalid. " + dce.getMessage());
          }
        }

        licenseFilePath = doc.getRootElement().getAttributeValue("licenseAgreement");

        if (name == null) {
          throw new ExtensionException(ExtensionException.FAILED_TO_PROCESS_DESCRIPTOR,
                  "<bundle> element requires the attribute 'name'");
        }
       
        startOnSetupMode = "true".equals(doc.getRootElement().getAttributeValue("startOnSetupMode"));

        for (Iterator i = doc.getRootElement().getChildren().iterator(); i.hasNext();) {
          Element e = (Element) i.next();
          if (e.getName().equalsIgnoreCase("description")) {
            description = Util.trimmedBothOrBlank(e.getText());
          } else if (e.getName().equalsIgnoreCase("install")) {
            processInstall(e);
          } else if (e.getName().equalsIgnoreCase("messages")) {
            // processed later
            messageElement = e;
          } else if (e.getName().equals("application") || e.getName().equals("extension")) {
            ExtensionDescriptor desc = new ExtensionDescriptor();
            desc.load(this, e);
            add(desc);
          } else {
            throw new ExtensionException(ExtensionException.FAILED_TO_PROCESS_DESCRIPTOR,
                    "<bundle> element may only contain <description> or <extension> (or the deprecated <application>) elements.");
          }
        }

      } else if (doc.getRootElement().getName().equals("application") || doc.getRootElement().getName().equals("extension")) {
        log.warn("DEPRECATED. All extensions should now use the <bundle> tag, " + getFile().getPath()
          + " is using not using this tag.");
        ExtensionDescriptor desc = new ExtensionDescriptor();
        desc.load(this, doc.getRootElement());
        id = desc.getId();
        name = desc.getName();
        description = desc.getDescription();
        order = 99999;
        dependencyNames = Arrays.asList(new String[] { "adito-community-applications",
          "adito-community-tunnels" });
        add(desc);
      } else {
        throw new ExtensionException(ExtensionException.FAILED_TO_PROCESS_DESCRIPTOR,
                "Application bundle root element must be <bundle> (or the deprecated <application> or <extension>) elements.");
      }

      // All we know is that the application is
      // installed until the application store is
      // available
      setType(TYPE_INSTALLED);
    } catch (ExtensionException ee) {
      error = ee;
      throw ee;
    }

    error = null;

  }

  /**
   * Get if this bundle contains any plugins.
   *
   * @return contains plugins
   */
  public boolean isContainsPlugin() {
    boolean containsPlugin = false;
    for (ExtensionDescriptor descriptor : this) {
      if (descriptor.getTypeName().equals(PluginType.TYPE)) {
        containsPlugin = true;
      }
    }
    return containsPlugin;
  }

  /**
   * Remove this bundle. If it started, then it will be stopped first. If the
   * bundle contains plugins the actual removal of the files will be deferred
   * until restart.
   *
   * @throws Exception
   */
  public void removeBundle() throws Exception {
    if (log.isInfoEnabled())
      log.info("Removing extension bundle " + getId());
    boolean containsPlugin = isContainsPlugin();
    try {
      // Stop the bundle if no plugins are contained
      if (!containsPlugin && getStatus().isStartedOrActivated()) {
        stop();
      }

      //
      for (ExtensionDescriptor descriptor : this) {
        descriptor.removeDescriptor();
      }
    } finally {
      if (containsPlugin) {
        setType(ExtensionBundle.TYPE_PENDING_REMOVAL);
      }
    }
  }

  /**
   * Get the <i>Install</i> (if any) for this extension bundle.
   * <code>null</code> will be returned if this bundle has no installer.
   *
   * @return extension installer
   */
  public ExtensionInstaller getInstaller() {
    return installer;
  }

  public String getInstructionsURL() {
    return instructionsURL;
  }

  public String getProductURL() {
    return productURL;
  }

  public VersionInfo.Version getVersion() {
    return version;
  }

    public VersionInfo.Version getDisplayVersion() {
        return isUpdateable() ? updateVersion : version;
    }

  public String getDescription() {
    return description;
  }

  public void setDescription(String description) {
    this.description = description;
  }

  public void setLicense(String license) {
    this.license = license;
  }

  public String getLicense() {
    return license;
  }

  public int getType() {
    return type;
  }

  public void setType(int type) {
    this.type = type;
  }

  public File getBaseDir() {
    return getFile() == null ? null : getFile().getParentFile();
  }

  /**
   * @param application
   * @return
   */
  public boolean containsApplication(String application) {
    for (Iterator i = iterator(); i.hasNext();) {
      if (((ExtensionDescriptor) i.next()).getId().equals(application)) {
        return true;
      }
    }
    return false;
  }

  /**
   * @param id
   * @return
   */
  public ExtensionDescriptor getApplicationDescriptor(String id) {
    for (Iterator i = iterator(); i.hasNext();) {
      ExtensionDescriptor app = (ExtensionDescriptor) i.next();
      if (app.getId().equals(id)) {
        return app;
      }
    }
    return null;
  }

  public int compareTo(Object arg0) {
    int c = getType() - ((ExtensionBundle) arg0).getType();
    return c != 0 ? c : name.compareTo(((ExtensionBundle) arg0).name);
  }

  public File getLicenseFile() {
    File baseDir = getBaseDir();
    return baseDir == null || licenseFilePath == null ? null : new File(baseDir, licenseFilePath);
  }

  public VersionInfo.Version getRequiredHostVersion() {
    return requiredHostVersion;
  }

  public void setRequiredHostVersion(VersionInfo.Version requiredHostVersion) {
    this.requiredHostVersion = requiredHostVersion;
  }

  public void setCategory(String category) {
    this.category = category;
  }

  public boolean isMandatoryUpdate() {
    return mandatoryUpdate;
  }

  public Throwable getError() {
    return error;
  }

  public boolean canStop() {
    boolean canStop = status.isStartedOrActivated();
    if (!canStop) {
      return false;
    }
    for (Iterator i = iterator(); i.hasNext();) {
      ExtensionDescriptor d = (ExtensionDescriptor) i.next();
      if (!d.canStop()) {
        return false;
      }
    }
    return true;

  }

  public boolean canStart() {
    return ExtensionBundleStatus.ENABLED.equals(status) && getType() != ExtensionBundle.TYPE_PENDING_INSTALLATION
      && getType() != ExtensionBundle.TYPE_PENDING_REMOVAL
      && getType() != ExtensionBundle.TYPE_PENDING_UPDATE
      && getType() != ExtensionBundle.TYPE_PENDING_STATE_CHANGE;
  }

  public boolean canDisable() {
    return !ExtensionBundleStatus.DISABLED.equals(status) && type != TYPE_CONFIGUREABLE && type != TYPE_INSTALLABLE && type != TYPE_PENDING_STATE_CHANGE;
  }

  public boolean canEnable() {
    return ExtensionBundleStatus.DISABLED.equals(status) && type != TYPE_PENDING_STATE_CHANGE;
  }

  public ExtensionBundleStatus getStatus() {
    return status;
  }

  public void setStatus(ExtensionBundleStatus status) {
    this.status = status;
  }

  private void processInstall(Element installElement) throws ExtensionException {
    String when = installElement.getAttributeValue("when");
    when = when == null ? ExtensionInstaller.ON_ACTIVATE : when;
    for (Iterator i = installElement.getChildren().iterator(); i.hasNext();) {
      Element e = (Element) i.next();
      if (e.getName().equalsIgnoreCase("mkdir")) {
        String dir = Util.trimmedBothOrBlank(e.getText());
        if (dir == null || dir.equals("")) {
          throw new ExtensionException(ExtensionException.FAILED_TO_PROCESS_DESCRIPTOR,
                  "<mkdir> contents must be the name of a directory to create.");
        }
        installer.addOp(new ExtensionInstaller.MkdirInstallOp(when, dir));
      } else if (e.getName().equalsIgnoreCase("cp")) {
        String from = Util.trimmedBothOrBlank(e.getText());
        String to = e.getAttributeValue("to");
        String toDir = e.getAttributeValue("toDir");
        boolean overwrite = "true".equalsIgnoreCase(e.getAttributeValue("overwrite"));
        if (from == null || from.equals("") || ((to == null || to.equals("")) && (toDir == null || toDir.equals("")))) {
          throw new ExtensionException(ExtensionException.FAILED_TO_PROCESS_DESCRIPTOR,
                  "<cp> content must be the source path and the tag must have either a to or toDir attribute.");
        }
        installer.addOp(new ExtensionInstaller.CpInstallOp(when, from, to, toDir, overwrite));
      } else if (e.getName().equalsIgnoreCase("rm")) {
        String path = Util.trimmedBothOrBlank(e.getText());
        if (path == null || path.equals("")) {
          throw new ExtensionException(ExtensionException.FAILED_TO_PROCESS_DESCRIPTOR,
                  "<rm> must a path as its content.");
        }
        installer.addOp(new ExtensionInstaller.RmInstallOp(when, path));
      } else if (e.getName().equalsIgnoreCase("custom")) {
        String clazz = Util.trimmedBothOrBlank(e.getText());
        if (clazz == null || clazz.equals("")) {
          throw new ExtensionException(ExtensionException.FAILED_TO_PROCESS_DESCRIPTOR,
                  "<custom> must provide a class name that implements ExtensionInstaller.ExtensionInstallOp as its content.");
        }
        try {
          installer.addOp(new ExtensionInstaller.CustomInstallOpWrapper(when, clazz));
        } catch (Exception ex) {
          throw new ExtensionException(ExtensionException.FAILED_TO_PROCESS_DESCRIPTOR,
                  ex, "Failed to create <custom> install op.");

        }
      }
    }
  }

  public String getChanges() {
    return changes==null ? "" : changes.trim();
  }
 
  public String toString() {
    return id + " " + version;
  }

  public VersionInfo.Version getUpdateVersion() {
    return updateVersion;
  }

  public void setUpdateVersion(VersionInfo.Version updateVersion) {
    this.updateVersion = updateVersion;
  }

  public void setChanges(String changes) {
    this.changes = changes;
  }

    public boolean isStartOnSetupMode() {
        return startOnSetupMode;
    }

  public String getPlatform() {
    return platform;
  }

  public String getArch() {
    return arch;
  }
 
}
TOP

Related Classes of com.adito.extensions.ExtensionBundle

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.