Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
Milyn - Copyright (C) 2006 - 2010
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License (version 2.1) as published by the Free Software
Foundation.
This library 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 Lesser General Public License for more details:
http://www.gnu.org/licenses/lgpl.txt
*/
package org.milyn.cdr;
import org.apache.commons.logging.*;
import org.milyn.classpath.*;
import org.milyn.container.*;
import org.milyn.delivery.Filter;
import org.milyn.delivery.Visitor;
import org.milyn.delivery.sax.*;
import org.milyn.expression.*;
import org.milyn.io.*;
import org.milyn.profile.*;
import org.milyn.resource.*;
import org.milyn.util.*;
import org.milyn.xml.*;
import org.milyn.cdr.xpath.SelectorStepBuilder;
import org.milyn.cdr.xpath.SelectorStep;
import org.milyn.cdr.xpath.evaluators.XPathExpressionEvaluator;
import org.milyn.cdr.xpath.evaluators.PassThruEvaluator;
import org.w3c.dom.*;
import org.jaxen.saxpath.SAXPathException;
import java.io.*;
import java.net.*;
import java.util.*;
import javassist.NotFoundException;
import javassist.CannotCompileException;
import javax.xml.namespace.QName;
/**
* Smooks Resource Targeting Configuration.
*
* A Smooks Resource is anything that can be used by Smooks in the process of analysing or
* transforming a data stream. They could be pieces
* of Java logic (SAX or DOM element {@link Visitor} implementations), some text or script resource, or perhaps
* simply a configuration parameter (see {@link org.milyn.cdr.ParameterAccessor}).
*
*
What is Resource Targeting?
* Smooks works by "targeting" {@link Visitor} resources at message fragments.
* This typically means targeting a piece of tranformation logic (XSLT, Java, Groovy etc)
* at a specific fragment of that message. The fragment may
* include as much or as little of the document as required. Smooks also allows you to target multilpe
* resources at the same fragment.
*
*
Resource Targeting Configurations
* Smooks can be manually/programmatically configured (through code), but the easiest way of working is through XML. The follwoing
* are a few sample configurations. Explanations follow the samples.
*
* A basic sample. Note that it is not using any profiling. The resource-config element maps directly to an instance of this class.
*
*
* A more complex sample, using profiling. So resource 1 is targeted at both "message-exchange-1" and "message-exchange-2",
* whereas resource 2 is only targeted at "message-exchange-1" and resource 3 at "message-exchange-2" (see {@link org.milyn.Smooks#createExecutionContext(String)}).
*
target-profile: A list of 1 or more {@link ProfileTargetingExpression profile targeting expressions}.
* (supports wildcards "*").
*
*
*
selector: Selector string. Used by Smooks to "lookup" a resource configuration.
* This is typically the message fragment name (partial XPath support), but as mentioned above, not all resources are
* transformation/analysis resources targeted at a message fragment - this is why we didn't call this attribute
* "target-fragment". This attribute supports a list of comma separated selectors, allowing you to target a
* single resource at multiple selector (e.g. fragments). Where the resource is a {@link Visitor} implementation, the selector
* is treated as an XPath expression (full XPath spec not supported), otherwise the selector value is treated as an opaque value.
*
*
* Example selectors:
*
*
For a {@link Visitor} implementation, use the target fragment name e.g. "order", "address", "address/name", "item[2]/price[text() = 99.99]" etc.
* Also supports wildcard based fragment selection ("*"). See the User Guide for more details on setting selectors for {@link Visitor} type
* resources.
*
*
"#document" is a special selector that targets a resource at the "document" fragment i.e. the whole document,
* or document root node fragment.
*
Targeting a specific {@link org.milyn.xml.SmooksXMLReader} at a specific profile.
*
*
*
*
selector-namespace: The XML namespace of the selector target for this resource. This is used
* to target {@link Visitor} implementations at fragments from a
* specific XML namespace e.g. "http://www.w3.org/2002/xforms". If not defined, the resource
* is targeted at all namespces.
*
* Note that since Smooks v1.3, namespace URI-to-prefix mappings can be configured through the "smooks-core" configuration namespace. Then,
* selectors can be configured with namespace prefixes, removing the need to use the "selector-namespace" configuration.
*
*
*
*
Resource Targeting Configurations
*
* @author [email protected]
* @see SmooksResourceConfigurationSortComparator
*/
public class SmooksResourceConfiguration {
/**
* Logger.
*/
private static Log logger = LogFactory.getLog(SmooksResourceConfiguration.class);
/**
* The resource type can be specified as a resource parameter. This constant defines
* that parameter name.
*
* @deprecated Resource type now specified on "type" attribute of <resource> element.
* Since Configuration DTD v2.0.
*/
public static final String PARAM_RESTYPE = "restype";
/**
* The resource data can be specified as a resource parameter. This constant defines
* that parameter name.
*
* @deprecated Resource now specified on <resource> element.
* Since Configuration DTD v2.0.
*/
public static final String PARAM_RESDATA = "resdata";
/**
* XML selector type definition prefix
*/
public static final String XML_DEF_PREFIX = "xmldef:".toLowerCase();
/**
*
*/
public static final String SELECTOR_NONE = "none";
/**
* URI resource locator.
*/
private static URIResourceLocator uriResourceLocator = new URIResourceLocator();
/**
* A special selector for resource targeted at the document as a whole (the roor element).
*/
public static final String DOCUMENT_FRAGMENT_SELECTOR = "#document";
public static final String LEGACY_DOCUMENT_FRAGMENT_SELECTOR = "$document";
/**
* A special selector for resource targeted at the document as a whole (the roor element).
*/
public static final String DOCUMENT_VOID_SELECTOR = "$void";
/**
* Document target on which the resource is to be applied.
*/
private String selector;
/**
* The name of the target element specified on the selector.
*/
private QName targetElement;
/**
* The name of an attribute, if one is specified on the selector.
*/
private QName targetAttribute;
/**
* Selector step. Is the last step in the selectorSteps array.
* We maintsain it as a stanalone variable as a small optimization i.e to save
* indexing into the selectorSteps array.
*/
private SelectorStep selectorStep;
/**
* Selector steps.
*/
private SelectorStep[] selectorSteps;
/**
* Is the selector contextual i.e. does it have multiple steps.
*/
private boolean isContextualSelector;
/**
* Target profile.
*/
private String targetProfile;
/**
* List of device/profile names on which the Content Delivery Resource is to be applied
* for instances of selector.
*/
private String[] profileTargetingExpressionStrings;
/**
* Targeting expressions built from the target-profile list.
*/
private ProfileTargetingExpression[] profileTargetingExpressions;
/**
* The resource.
*/
private String resource;
/**
* Java resource object instance.
*/
private Object javaResourceObject;
/**
* Is this resource defined inline in the configuration, or is it
* referenced through a URI.
*/
private boolean isInline = false;
/**
* Condition evaluator used in resource targeting.
*/
private ExpressionEvaluator expressionEvaluator;
/**
* The type of the resource. "class", "groovy", "xsl" etc....
*/
private String resourceType;
/**
* Is this selector defininition an XML based definition.
*/
private boolean isXmlDef;
/**
* SmooksResourceConfiguration parameters - String name and String value.
*/
private LinkedHashMap parameters = new LinkedHashMap();
private int parameterCount;
/**
* Global Parameters object.
*/
private SmooksResourceConfiguration globalParams;
/**
* The XML namespace of the tag to which this config
* should only be applied.
*/
private String namespaceURI;
/**
* Flag indicating whether or not the resource is a default applied resource
* e.g. {@link org.milyn.delivery.dom.serialize.DefaultSerializationUnit} or
* {@link org.milyn.delivery.sax.DefaultSAXElementSerializer}.
*/
private boolean defaultResource = false;
/**
* The extended config namespace from which the resource was created.
*/
private String extendedConfigNS;
/**
* Change listeners.
*/
private Set changeListeners = new HashSet();
/**
* Public default constructor.
*
* @see #setSelector(String)
* @see #setSelectorNamespaceURI(String)
* @see #setTargetProfile(String)
* @see #setResource(String)
* @see #setResourceType(String)
* @see #setParameter(String, String)
*/
public SmooksResourceConfiguration() {
setSelector(SELECTOR_NONE);
setTargetProfile(Profile.DEFAULT_PROFILE);
}
/**
* Public constructor.
*
* @param selector The selector definition.
* @see #setSelectorNamespaceURI(String)
* @see #setTargetProfile(String)
* @see #setResource(String)
* @see #setResourceType(String)
* @see #setParameter(String, String)
*/
public SmooksResourceConfiguration(String selector) {
setSelector(selector);
setTargetProfile(Profile.DEFAULT_PROFILE);
}
/**
* Public constructor.
*
* @param selector The selector definition.
* @param resource The resource.
* @see #setSelectorNamespaceURI(String)
* @see #setTargetProfile(String)
* @see #setResourceType(String)
* @see #setParameter(String, String)
*/
public SmooksResourceConfiguration(String selector, String resource) {
this(selector, Profile.DEFAULT_PROFILE, resource);
}
/**
* Public constructor.
*
* @param selector The selector definition.
* @param targetProfile Target Profile(s). Comma separated list of
* {@link ProfileTargetingExpression ProfileTargetingExpressions}.
* @param resource The resource.
* @see #setSelectorNamespaceURI(String)
* @see #setResourceType(String)
* @see #setParameter(String, String)
*/
public SmooksResourceConfiguration(String selector, String targetProfile, String resource) {
this(selector);
setTargetProfile(targetProfile);
setResource(resource);
}
/**
* Perform a shallow clone of this configuration.
*
* @return Configuration clone.
*/
public Object clone() {
SmooksResourceConfiguration clone = new SmooksResourceConfiguration();
clone.extendedConfigNS = extendedConfigNS;
clone.selector = selector;
clone.selectorSteps = selectorSteps;
clone.targetElement = targetElement;
clone.targetAttribute = targetAttribute;
clone.isContextualSelector = isContextualSelector;
clone.targetProfile = targetProfile;
clone.defaultResource = defaultResource;
clone.profileTargetingExpressionStrings = profileTargetingExpressionStrings;
clone.profileTargetingExpressions = profileTargetingExpressions;
clone.resource = resource;
clone.isInline = isInline;
clone.resourceType = resourceType;
clone.isXmlDef = isXmlDef;
if (parameters != null) {
clone.parameters = (LinkedHashMap) parameters.clone();
}
clone.parameterCount = parameterCount;
clone.namespaceURI = namespaceURI;
clone.expressionEvaluator = expressionEvaluator;
return clone;
}
/**
* Get the extended config namespace from which this configuration was created.
* @return The extended config namespace from which this configuration was created.
*/
public String getExtendedConfigNS() {
return extendedConfigNS;
}
/**
* Set the extended config namespace from which this configuration was created.
* @param extendedConfigNS The extended config namespace from which this configuration was created.
*/
public void setExtendedConfigNS(String extendedConfigNS) {
this.extendedConfigNS = extendedConfigNS;
}
public void attachGlobalParameters(ApplicationContext appContext) {
if(globalParams == null) {
globalParams = appContext.getStore().getGlobalParams();
}
}
public SmooksResourceConfiguration merge(SmooksResourceConfiguration config) {
SmooksResourceConfiguration clone = (SmooksResourceConfiguration) clone();
clone.parameters.clear();
clone.parameters.putAll(config.parameters);
clone.parameters.putAll(this.parameters);
return clone;
}
public void addParmeters(SmooksResourceConfiguration config) {
parameters.putAll(config.parameters);
}
/**
* Public constructor.
*
* @param selector The selector definition.
* @param selectorNamespaceURI The selector namespace URI.
* @param targetProfile Target Profile(s). Comma separated list of
* {@link ProfileTargetingExpression ProfileTargetingExpressions}.
* @param resource The resource.
* @see #setResourceType(String)
* @see #setParameter(String, String)
*/
public SmooksResourceConfiguration(String selector, String selectorNamespaceURI, String targetProfile, String resource) {
this(selector, targetProfile, resource);
setSelectorNamespaceURI(selectorNamespaceURI);
}
/**
* Set the config selector.
*
* @param selector The selector definition.
*/
public void setSelector(final String selector) {
if (selector == null || selector.trim().equals("")) {
throw new IllegalArgumentException("null or empty 'selector' arg in constructor call.");
}
if(selector.equals(LEGACY_DOCUMENT_FRAGMENT_SELECTOR)) {
this.selector = DOCUMENT_FRAGMENT_SELECTOR;
} else {
this.selector = selector;
}
// If there's a "#document" token in the selector, but it's not at the very start,
// then we have an invalid selector...
int docSelectorIndex = selector.trim().indexOf(DOCUMENT_FRAGMENT_SELECTOR);
if(docSelectorIndex != -1 && docSelectorIndex > 0) {
throw new SmooksConfigurationException("Invalid selector '" + selector + "'. '" + DOCUMENT_FRAGMENT_SELECTOR + "' token can only exist at the start of the selector.");
}
isXmlDef = selector.startsWith(XML_DEF_PREFIX);
try {
selectorSteps = SelectorStepBuilder.buildSteps(selector);
} catch (SAXPathException e) {
selectorSteps = constructSelectorStepsFromLegacySelector(selector);
}
initTarget();
fireChangedEvent();
}
private void initTarget() {
selectorStep = selectorSteps[selectorSteps.length - 1];
targetElement = selectorStep.getTargetElement();
targetAttribute = selectorStep.getTargetAttribute();
isContextualSelector = (selectorSteps.length > 1);
}
private SelectorStep[] constructSelectorStepsFromLegacySelector(String selector) {
// In case it's a legacy selector that we don't support...
if(selector.startsWith("/")) {
selector = DOCUMENT_FRAGMENT_SELECTOR + selector;
}
String[] contextualSelector = parseSelector(selector);
List selectorStepList = new ArrayList();
for(int i = 0; i < contextualSelector.length; i++) {
String targetElementName = contextualSelector[i];
if(i == contextualSelector.length - 2 && contextualSelector[contextualSelector.length - 1].startsWith("@")) {
selectorStepList.add(new LegacySelectorStep(selector, targetElementName, contextualSelector[contextualSelector.length - 1]));
break;
} else {
selectorStepList.add(new LegacySelectorStep(selector, targetElementName));
}
}
logger.debug("Unable to parse selector '" + selector + "' as an XPath selector (even after normalization). Parsing as a legacy style selector.");
return selectorStepList.toArray(new SelectorStep[selectorStepList.size()]);
}
public static String[] parseSelector(String selector) {
String[] splitTokens;
if(selector.startsWith("/")) {
selector = selector.substring(1);
}
// Parse the selector in case it's a contextual selector...
if (selector.indexOf('/') != -1) {
// Parse it as e.g. "a/b/c" ...
splitTokens = selector.split("/");
} else {
// Parse it as a CSS form selector e.g. "TD UL LI" ...
splitTokens = selector.split(" +");
}
for (int i = 0; i < splitTokens.length; i++) {
String splitToken = splitTokens[i];
if (!splitToken.startsWith("@")) {
splitTokens[i] = splitToken;
}
if (splitToken.equals(LEGACY_DOCUMENT_FRAGMENT_SELECTOR)) {
splitTokens[i] = DOCUMENT_FRAGMENT_SELECTOR;
}
}
return splitTokens;
}
/**
* Set the namespace URI to which the selector is associated.
*
* @param namespaceURI Selector namespace.
*/
public void setSelectorNamespaceURI(String namespaceURI) {
if (namespaceURI != null) {
if (namespaceURI.equals("*")) {
this.namespaceURI = null;
} else {
this.namespaceURI = namespaceURI.intern();
}
fireChangedEvent();
}
}
/**
* Set the configs "resource".
*
* @param resource The resource.
*/
public void setResource(String resource) {
this.resource = resource;
if (resource != null) {
try {
// If the resource resolves as a valid URI, then it's not an inline resource.
new URI(resource);
isInline = false;
} catch (Exception e) {
isInline = true;
}
}
fireChangedEvent();
}
/**
* Get the Java resource object instance associated with this resource, if one exists and
* it has been create.
* @return The Java resource object instance associated with this resource, if one exists and
* it has been create, otherwise null.
*/
public Object getJavaResourceObject() {
return javaResourceObject;
}
/**
* Set the Java resource object instance associated with this resource.
* @param javaResourceObject The Java resource object instance associated with this resource.
*/
public void setJavaResourceObject(Object javaResourceObject) {
this.javaResourceObject = javaResourceObject;
}
/**
* Is this resource defined inline in the configuration, or is it
* referenced through a URI.
*
* Note that this method also returns false if the resource is undefined (null).
*
* @return True if the resource is defined inline, otherwise false.
*/
public boolean isInline() {
return isInline;
}
/**
* Get the target profile string as set in the configuration.
*
* @return The target profile.
*/
public String getTargetProfile() {
return targetProfile;
}
/**
* Set the configs "target profile".
*
* @param targetProfile Target Profile(s). Comma separated list of
* {@link ProfileTargetingExpression ProfileTargetingExpressions}.
*/
public void setTargetProfile(String targetProfile) {
if (targetProfile == null || targetProfile.trim().equals("")) {
// Default the target profile to everything if not specified.
targetProfile = Profile.DEFAULT_PROFILE;
}
this.targetProfile = targetProfile;
parseTargetingExpressions(targetProfile);
}
/**
* Explicitly set the resource type.
*
* E.g. "class", "xsl", "groovy" etc.
*
* @param resourceType The resource type.
*/
public void setResourceType(String resourceType) {
this.resourceType = resourceType;
}
/**
* Get the selector definition for this SmooksResourceConfiguration.
*
* @return The selector definition.
*/
public String getSelector() {
return selector;
}
/**
* Get the contextual selector definition for this SmooksResourceConfiguration.
*
* See details about the "selector" attribute in the
* Attribute Definitions section.
*
* @return The contxtual selector definition.
* @deprecated Use {#link #getSelectorSteps}.
*/
public String[] getContextualSelector() {
return SelectorStepBuilder.toContextualSelector(selectorSteps);
}
/**
* Set the selector steps.
* @param selectorSteps The selector steps.
*/
public void setSelectorSteps(SelectorStep[] selectorSteps) {
this.selectorSteps = selectorSteps;
initTarget();
fireChangedEvent();
}
/**
* Get the selector steps.
* @return The selector steps.
*/
public SelectorStep[] getSelectorSteps() {
return selectorSteps;
}
/**
* Get the targeting selector step.
* @return The targeting selector step.
*/
public SelectorStep getSelectorStep() {
return selectorStep;
}
/**
* Get the name of the target element where the {@link #getSelector() selector}
* is targeting the resource at an XML element.
*
* Accomodates the fact that element based selectors can be contextual. This method
* is not relevant where the selector is not targeting an XML element.
*
* See details about the "selector" attribute in the
* Attribute Definitions section.
*
* @return The target XML element name.
*/
public String getTargetElement() {
return targetElement.getLocalPart();
}
/**
* Get the {@link QName} of the target element where the {@link #getSelector() selector}
* is targeting the resource at an XML element.
*
* Accomodates the fact that element based selectors can be contextual. This method
* is not relevant where the selector is not targeting an XML element.
*
* See details about the "selector" attribute in the
* Attribute Definitions section.
*
* @return The target XML element {@link QName}.
*/
public QName getTargetElementQName() {
return targetElement;
}
/**
* Get the name of the attribute specified on the selector, if one was
* specified.
* @return An attribute name, if one was specified on the selector, otherwise null.
*/
public String getTargetAttribute() {
if(targetAttribute == null) {
return null;
}
return targetAttribute.getLocalPart();
}
/**
* Get the name of the attribute specified on the selector, if one was
* specified.
* @return An attribute name, if one was specified on the selector, otherwise null.
*/
public QName getTargetAttributeQName() {
return targetAttribute;
}
/**
* The the selector namespace URI.
*
* @return The XML namespace URI of the element to which this configuration
* applies, or null if not namespaced.
*/
public String getSelectorNamespaceURI() {
return namespaceURI;
}
/**
* Get the profile targeting expressions for this SmooksResourceConfiguration.
*
* @return The profile targeting expressions.
*/
public ProfileTargetingExpression[] getProfileTargetingExpressions() {
return profileTargetingExpressions;
}
/**
* Get the resource for this SmooksResourceConfiguration.
*
* @return The cdrar path.
*/
public String getResource() {
return resource;
}
/**
* Set the condition evaluator to be used in targeting of this resource.
*
* @param expressionEvaluator The {@link org.milyn.expression.ExpressionEvaluator}, or null if no condition is to be used.
*/
public void setConditionEvaluator(ExpressionEvaluator expressionEvaluator) {
if (expressionEvaluator != null && !(expressionEvaluator instanceof ExecutionContextExpressionEvaluator)) {
throw new UnsupportedOperationException("Unsupported ExpressionEvaluator type '" + expressionEvaluator.getClass().getName() + "'. Currently only support '" + ExecutionContextExpressionEvaluator.class.getName() + "' implementations.");
}
this.expressionEvaluator = expressionEvaluator;
}
/**
* Get the condition evaluator used in targeting of this resource.
*
* @return The {@link org.milyn.expression.ExpressionEvaluator}, or null if no condition is specified.
*/
public ExpressionEvaluator getConditionEvaluator() {
return expressionEvaluator;
}
/**
* Is this resource config a default applied resource.
*
* Some resources (e.g. {@link org.milyn.delivery.dom.serialize.DefaultSerializationUnit} or
* {@link org.milyn.delivery.sax.DefaultSAXElementSerializer}) are applied by default when no other
* resources are targeted at an element.
*
* @return True if this is a default applied resource, otherwise false.
*/
public boolean isDefaultResource() {
return defaultResource;
}
/**
* Set this resource config as a default applied resource.
*
* Some resources (e.g. {@link org.milyn.delivery.dom.serialize.DefaultSerializationUnit} or
* {@link org.milyn.delivery.sax.DefaultSAXElementSerializer}) are applied by default when no other
* resources are targeted at an element.
*
* @param defaultResource True if this is a default applied resource, otherwise false.
*/
public void setDefaultResource(boolean defaultResource) {
this.defaultResource = defaultResource;
}
/**
* Get the resource "type" for this resource.
*
* Determines the type through the following checks (in order):
*
*