All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.drools.repository.AssetItem Maven / Gradle / Ivy

There is a newer version: 5.1.1
Show newest version
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;

	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy