Package org.drools.repository

Source Code of org.drools.repository.AssetItem

/**
* Copyright 2010 JBoss Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.drools.repository;

import java.io.*;
import java.util.Calendar;
import java.util.Iterator;

import javax.jcr.Binary;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
import javax.jcr.RepositoryException;

import org.drools.repository.events.StorageEventManager;
import org.drools.repository.utils.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* The RuleItem class is used to abstract away the details of the underlying JCR
* repository. It is used to pass information about rules stored in the
* repository.
*
* @author btruitt
*/
public class AssetItem extends CategorisableItem {
  private Logger log = LoggerFactory.getLogger(AssetItem.class);
  /**
   * The name of the rule node type
   */
  public static final String RULE_NODE_TYPE_NAME = "drools:assetNodeType";

  public static final String CONTENT_PROPERTY_NAME = "drools:content";
  public static final String CONTENT_PROPERTY_BINARY_NAME = "drools:binaryContent";
  public static final String CONTENT_PROPERTY_ATTACHMENT_FILENAME = "drools:attachmentFileName";

  /**
   * The name of the date effective property on the rule node type
   */
  public static final String DATE_EFFECTIVE_PROPERTY_NAME = "drools:dateEffective";

  public static final String DISABLED_PROPERTY_NAME = "drools:disabled";

  /**
   * The name of the date expired property on the rule node type
   */
  public static final String DATE_EXPIRED_PROPERTY_NAME = "drools:dateExpired";

  public static final String PACKAGE_NAME_PROPERTY = "drools:packageName";

  /**
   * Constructs a RuleItem object, setting its node attribute to the specified
   * node.
   *
   * @param rulesRepository
   *            the rulesRepository that instantiated this object
   * @param node
   *            the node in the repository that this RuleItem corresponds to
   * @throws RulesRepositoryException
   */
  public AssetItem(RulesRepository rulesRepository, Node node)
      throws RulesRepositoryException {
    super(rulesRepository, node);
    try {
      // make sure this node is a rule node
      if (!(this.node.getPrimaryNodeType().getName().equals(
          RULE_NODE_TYPE_NAME) || isHistoricalVersion())) {
        String message = this.node.getName()
            + " is not a node of type " + RULE_NODE_TYPE_NAME
            + " nor nt:version. It is a node of type: "
            + this.node.getPrimaryNodeType().getName();
        log.error(message);
        throw new RulesRepositoryException(message);
      }
    } catch (Exception e) {
      log.error("Caught exception", e);
      throw new RulesRepositoryException(e);
    }
  }

  public AssetItem() {
    super(null, null);
  }

  /**
   * returns the string contents of the rule node. If this is a binary asset,
   * this will return null (use getBinaryContent instead).
   */
  public String getContent() throws RulesRepositoryException {
    return getContent(false);
  }

  /**
   * Only for use in the StorageEventManager, for passing the fromRepo
   * parameter
   *
   * returns the string contents of the rule node. If this is a binary asset,
   * this will return null (use getBinaryContent instead).
   */
  public String getContent(Boolean fromRepo) throws RulesRepositoryException {
    try {

      if (StorageEventManager.hasLoadEvent() && !fromRepo) {
        return IOUtils.toString(StorageEventManager.getLoadEvent()
            .loadContent(this));
      }

      if (isBinary()) {
        return new String(this.getBinaryContentAsBytes());
      }
      Node ruleNode = getVersionContentNode();
      if (ruleNode.hasProperty(CONTENT_PROPERTY_NAME)) {
        Property data = ruleNode.getProperty(CONTENT_PROPERTY_NAME);
        return data.getValue().getString();

      } else {
        return "";
      }
    } catch (Exception e) {
      log.error("Caught Exception", e);
      throw new RulesRepositoryException(e);
    }
  }

  /**
   * returns the number of bytes of the content.
   */
  public long getContentLength() {
    try {
      Node ruleNode = getVersionContentNode();
      if (ruleNode.hasProperty(CONTENT_PROPERTY_BINARY_NAME)) {
        Property data = ruleNode
            .getProperty(CONTENT_PROPERTY_BINARY_NAME);
        return data.getLength();
      } else {
        if (ruleNode.hasProperty(CONTENT_PROPERTY_NAME)) {
          Property data = ruleNode.getProperty(CONTENT_PROPERTY_NAME);
          return data.getLength();
        } else {
          return 0;
        }
      }
    } catch (RepositoryException e) {
      log.error(e.getMessage(), e);
      throw new RulesRepositoryException(e);
    }
  }

  /**
   * True if this is a binary asset (or has binary content).
   */
  public boolean isBinary() {
    try {
      Node ruleNode = getVersionContentNode();
      return ruleNode.hasProperty(CONTENT_PROPERTY_BINARY_NAME);
    } catch (RepositoryException e) {
      log.error(e.getMessage(), e);
      throw new RulesRepositoryException(e);
    }
  }

  /**
   * If this asset contains binary data, this is how you return it. Otherwise
   * it will return null.
   */
  public InputStream getBinaryContentAttachment() {
    try {
      if (StorageEventManager.hasLoadEvent()) {
        return StorageEventManager.getLoadEvent().loadContent(this);
      }
      Node ruleNode = getVersionContentNode();
      if (ruleNode.hasProperty(CONTENT_PROPERTY_BINARY_NAME)) {
        Property data = ruleNode
            .getProperty(CONTENT_PROPERTY_BINARY_NAME);
        return data.getBinary().getStream();
      } else {
        if (ruleNode.hasProperty(CONTENT_PROPERTY_NAME)) {
          Property data = ruleNode.getProperty(CONTENT_PROPERTY_NAME);
          return data.getBinary().getStream();
        }
        return null;
      }
    } catch (Exception e) {
      log.error("Caught Exception", e);
      throw new RulesRepositoryException(e);
    }
  }

  /** Get the name of the "file" attachment, if one is set. Null otherwise */
  public String getBinaryContentAttachmentFileName() {
    return getStringProperty(CONTENT_PROPERTY_ATTACHMENT_FILENAME);
  }

  /**
   * This is a convenience method for returning the binary data as a byte
   * array.
   */
  public byte[] getBinaryContentAsBytes() {
    try {
      Node ruleNode = getVersionContentNode();
      if (StorageEventManager.hasLoadEvent()) {
        return IOUtils.toByteArray(StorageEventManager.getLoadEvent()
            .loadContent(this));
      }
      if (isBinary()) {
        Property data = ruleNode
            .getProperty(CONTENT_PROPERTY_BINARY_NAME);
        InputStream in = data.getBinary().getStream();

        // Create the byte array to hold the data
        byte[] bytes = new byte[(int) data.getLength()];

        // Read in the bytes
        int offset = 0;
        int numRead = 0;
        while (offset < bytes.length
            && (numRead = in.read(bytes, offset, bytes.length
                - offset)) >= 0) {
          offset += numRead;
        }

        // Ensure all the bytes have been read in
        if (offset < bytes.length) {
          throw new RulesRepositoryException(
              "Could not completely read asset " + getName());
        }

        // Close the input stream and return bytes
        in.close();
        return bytes;
      } else {
        return getContent().getBytes();
      }
    } catch (Exception e) {
      log.error(e.getMessage(), e);
      if (e instanceof RuntimeException)
        throw (RuntimeException) e;
      throw new RulesRepositoryException(e);
    }
  }

  /**
   * @return the date the rule becomes effective
   * @throws RulesRepositoryException
   */
  public Calendar getDateEffective() throws RulesRepositoryException {
    try {
      Node ruleNode = getVersionContentNode();

      Property dateEffectiveProperty = ruleNode
          .getProperty(DATE_EFFECTIVE_PROPERTY_NAME);
      return dateEffectiveProperty.getDate();
    } catch (PathNotFoundException e) {
      // doesn't have this property
      return null;
    } catch (Exception e) {
      log.error("Caught Exception", e);
      throw new RulesRepositoryException(e);
    }
  }

  /**
   * @return if this rule is disabled
   * @throws RulesRepositoryException
   */
  public boolean getDisabled() throws RulesRepositoryException {
    try {
      Node ruleNode = getVersionContentNode();

      Property disabled = ruleNode.getProperty(DISABLED_PROPERTY_NAME);
      return disabled.getBoolean();
    } catch (PathNotFoundException e) {
      // doesn't have this property
      return false;
    } catch (Exception e) {
      log.error("Caught Exception", e);
      throw new RulesRepositoryException(e);
    }
  }

  /**
   * Creates a new version of this object's rule node, updating the effective
   * date for the rule node.
   *
   * @param newDateEffective
   *            the new effective date for the rule
   * @throws RulesRepositoryException
   */
  public void updateDateEffective(Calendar newDateEffective)
      throws RulesRepositoryException {
    checkIsUpdateable();
    checkout();
    try {
      this.node.setProperty(DATE_EFFECTIVE_PROPERTY_NAME,
          newDateEffective);
    } catch (RepositoryException e) {
      log.error("Caught Exception", e);
      throw new RulesRepositoryException(e);
    }
  }

  /**
   * Creates a new version of this object's rule node, updating the disable
   * value for the rule node.
   *
   * @param disabled
   *            is this rule disabled
   * @throws RulesRepositoryException
   */
  public void updateDisabled(boolean disabled)
      throws RulesRepositoryException {
    checkIsUpdateable();
    checkout();
    try {
      this.node.setProperty(DISABLED_PROPERTY_NAME, disabled);
    } catch (RepositoryException e) {
      log.error("Caught Exception", e);
      throw new RulesRepositoryException(e);
    }
  }

  /**
   * @return the date the rule becomes expired
   * @throws RulesRepositoryException
   */
  public Calendar getDateExpired() throws RulesRepositoryException {
    try {
      Node ruleNode = getVersionContentNode();

      Property dateExpiredProperty = ruleNode
          .getProperty(DATE_EXPIRED_PROPERTY_NAME);
      return dateExpiredProperty.getDate();
    } catch (PathNotFoundException e) {
      // doesn't have this property
      return null;
    } catch (Exception e) {
      log.error("Caught Exception", e);
      throw new RulesRepositoryException(e);
    }
  }

  /**
   * Creates a new version of this object's rule node, updating the expired
   * date for the rule node.
   *
   * @param newDateExpired
   *            the new expired date for the rule
   * @throws RulesRepositoryException
   */
  public void updateDateExpired(Calendar newDateExpired)
      throws RulesRepositoryException {
    checkout();

    try {
      this.node.setProperty(DATE_EXPIRED_PROPERTY_NAME, newDateExpired);
    } catch (Exception e) {
      log.error("Caught Exception", e);
      throw new RulesRepositoryException(e);
    }
  }

  /**
   * This will update the asset's content (checking it out if it is not
   * already). This will not save the session or create a new version of the
   * node (this has to be done seperately, as several properties may change as
   * part of one edit). This is only used if the asset is a textual asset. For
   * binary, use the updateBinaryContent method instead.
   */
  public AssetItem updateContent(String newRuleContent)
      throws RulesRepositoryException {
    checkout();
    try {
      if (this.isBinary()) {
        this.updateBinaryContentAttachment(new ByteArrayInputStream(
            newRuleContent.getBytes()));
      }
      this.node.setProperty(CONTENT_PROPERTY_NAME, newRuleContent);
      return this;
    } catch (RepositoryException e) {
      log.error("Unable to update the asset content", e);
      throw new RulesRepositoryException(e);
    }
  }

  /**
   * If the asset is a binary asset, then use this to update the content (do
   * NOT use text).
   */
  public AssetItem updateBinaryContentAttachment(InputStream data) {
    checkout();
    try {
      Binary is = this.node.getSession().getValueFactory().createBinary(data);
      this.node.setProperty(CONTENT_PROPERTY_BINARY_NAME, is);
      return this;
    } catch (RepositoryException e) {
      log.error("Unable to update the assets binary content", e);
      throw new RulesRepositoryException(e);
    }
  }

  /**
   * Optionally set the filename to be associated with the binary content.
   */
  public void updateBinaryContentAttachmentFileName(String name) {
    updateStringProperty(name, CONTENT_PROPERTY_ATTACHMENT_FILENAME);
  }

  /**
   * This updates a user defined property (not one of the intrinsic ones).
   */
  public void updateUserProperty(String propertyName, String value) {
    if (propertyName.startsWith("drools:")) {
      throw new IllegalArgumentException(
          "Can only set the pre defined fields using the appropriate methods.");
    }
    updateStringProperty(value, propertyName);

  }

  /**
   * Nicely formats the information contained by the node that this object
   * encapsulates
   */
  public String toString() {
    try {
      StringBuffer returnString = new StringBuffer();
      returnString.append("Content of rule item named '" + this.getName()
          + "':\n");
      returnString.append("Content: " + this.getContent() + "\n");
      returnString.append("------\n");

      returnString.append("Archived: " + this.isArchived() + "\n");
      returnString.append("------\n");

      returnString.append("Date Effective: " + this.getDateEffective()
          + "\n");
      returnString
          .append("Date Expired: " + this.getDateExpired() + "\n");
      returnString.append("------\n");

      returnString.append("Rule state: ");
      StateItem stateItem = this.getState();
      if (stateItem != null) {
        returnString.append(this.getState().getName() + "\n");
      } else {
        returnString.append("NO STATE SET FOR THIS NODE\n");
      }
      returnString.append("------\n");

      returnString.append("Rule tags:\n");
      for (Iterator it = this.getCategories().iterator(); it.hasNext();) {
        CategoryItem currentTag = (CategoryItem) it.next();
        returnString.append(currentTag.getName() + "\n");
      }
      returnString.append("--------------\n");
      return returnString.toString();
    } catch (Exception e) {
      throw new RulesRepositoryException(e);
    }
  }

  public VersionableItem getPrecedingVersion()
      throws RulesRepositoryException {
    try {
      Node precedingVersionNode = this.getPrecedingVersionNode();
      if (precedingVersionNode != null) {
        return new AssetItem(this.rulesRepository, precedingVersionNode);
      } else {
        return null;
      }
    } catch (Exception e) {
      log.error("Caught exception", e);
      throw new RulesRepositoryException(e);
    }
  }

  public VersionableItem getSucceedingVersion()
      throws RulesRepositoryException {
    try {
      Node succeedingVersionNode = this.getSucceedingVersionNode();
      if (succeedingVersionNode != null) {
        return new AssetItem(this.rulesRepository,
            succeedingVersionNode);
      } else {
        return null;
      }
    } catch (Exception e) {
      log.error("Caught exception", e);
      throw new RulesRepositoryException(e);
    }
  }

  /**
   * Get the name of the enclosing package. As assets are stored in
   * versionable subfolders, this means walking up 2 levels in the hierarchy
   * to get to the enclosing "package" node.
   */
  public String getPackageName() {
    return super.getStringProperty(PACKAGE_NAME_PROPERTY);
  }

  /**
   * @return A property value (for a user defined property).
   */
  public String getUserProperty(String property) {
    return getStringProperty(property);
  }

  /**
   * This will remove the item. The repository will need to be saved for this
   * to take effect. Typically the package that contains this should be
   * versioned before removing this, to make it easy to roll back.
   */
  public void remove() {

    if (StorageEventManager.hasSaveEvent()) {
      StorageEventManager.getSaveEvent().onAssetDelete(this);
    }

    checkIsUpdateable();
    if (this.getDateExpired() != null) {
      if (Calendar.getInstance().before(this.getDateExpired())) {
        throw new RulesRepositoryException(
            "Can't delete an item before its expiry date.");
      }
    }
    try {
      this.node.remove();
    } catch (RepositoryException e) {
      throw new RulesRepositoryException(e);
    }
  }

  /**
   *
   * @return An iterator over the nodes history.
   */
  public AssetHistoryIterator getHistory() {
    return new AssetHistoryIterator(this.rulesRepository, this.node);
  }

  /**
   * This will get the package an asset item belongs to.
   */
  public PackageItem getPackage() {

    try {
      if (this.isHistoricalVersion()) {
        return this.rulesRepository.loadPackage(this.getPackageName());
      }
      return new PackageItem(this.rulesRepository, this.node.getParent()
          .getParent());
    } catch (RepositoryException e) {
      throw new RulesRepositoryException(e);
    }
  }

  /**
   * This converts a "filename" to an asset name.
   *
   * File name is foo.drl -> ["foo", "drl"]
   *
   * @param fileName
   * @return
   */
  public static String[] getAssetNameFromFileName(String fileName) {

    String[] r = new String[] { "", "" };
    if (!fileName.contains(".")) {
      r[0] = fileName;
    } else if (fileName.endsWith(".bpel.jar")) {
      r[0] = fileName.substring(0, fileName.lastIndexOf(".bpel.jar"));
      r[1] = "bpel.jar";
    } else if (fileName.endsWith(".model.drl")) {
      r[0] = fileName.substring(0, fileName.lastIndexOf(".model.drl"));
      r[1] = "model.drl";
    } else {
      r[0] = fileName.substring(0, fileName.lastIndexOf("."));
      r[1] = fileName.substring(fileName.lastIndexOf(".") + 1);

    }
    return r;

  }

}
TOP

Related Classes of org.drools.repository.AssetItem

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.