org.drools.repository.AssetItem Maven / Gradle / Ivy
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