Author: dvaleri Date: Thu Oct 6 21:07:28 2011 New Revision: 1179853 URL: http://svn.apache.org/viewvc?rev=1179853&view=rev Log: [CAMEL-4520] [CAMEL-3775] Added support for custom prefix/suffix tokens and custom property name prefix and suffix strings to XML based configuration and fixed disabled OSGI itests for property placeholders.
Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/CamelContext.java camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java camel/trunk/camel-core/src/main/java/org/apache/camel/impl/PropertyPlaceholderDelegateRegistry.java camel/trunk/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/CamelPropertyPlaceholderDefinition.java camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/SpringPropertiesComponent2Test.xml camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/blueprint/BlueprintExplicitPropertiesRouteTest.java camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/blueprint/BlueprintPropertiesRouteTest.java camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/blueprint/blueprint-16.xml Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/CamelContext.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/CamelContext.java?rev=1179853&r1=1179852&r2=1179853&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/CamelContext.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/CamelContext.java Thu Oct 6 21:07:28 2011 @@ -619,6 +619,22 @@ public interface CamelContext extends Su * @throws Exception is thrown if property placeholders was used and there was an error resolving them */ String resolvePropertyPlaceholders(String text) throws Exception; + + /** + * Returns the configured property placeholder prefix token if and only if the context has + * property placeholder abilities, otherwise returns {@code null}. + * + * @return the prefix token or {@code null} + */ + String getPropertyPrefixToken(); + + /** + * Returns the configured property placeholder suffix token if and only if the context has + * property placeholder abilities, otherwise returns {@code null}. + * + * @return the suffix token or {@code null} + */ + String getPropertySuffixToken(); /** * Gets a readonly list with the names of the languages currently registered. @@ -1037,5 +1053,4 @@ public interface CamelContext extends Su * @param useBreadcrumb <tt>true</tt> to enable breadcrumb, <tt>false</tt> to disable */ void setUseBreadcrumb(Boolean useBreadcrumb); - } Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java?rev=1179853&r1=1179852&r2=1179853&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java Thu Oct 6 21:07:28 2011 @@ -1512,7 +1512,7 @@ public final class ExpressionBuilder { .mandatoryConvertTo(PropertiesComponent.class, component); // enclose key with {{ }} to force parsing String[] paths = locations.split(","); - return pc.parseUri(PropertiesComponent.PREFIX_TOKEN + key + PropertiesComponent.SUFFIX_TOKEN, paths); + return pc.parseUri(pc.getPrefixToken() + key + pc.getSuffixToken(), paths); } else { // the properties component is mandatory if no locations provided Component component = exchange.getContext().hasComponent("properties"); @@ -1523,7 +1523,7 @@ public final class ExpressionBuilder { PropertiesComponent pc = exchange.getContext().getTypeConverter() .mandatoryConvertTo(PropertiesComponent.class, component); // enclose key with {{ }} to force parsing - return pc.parseUri(PropertiesComponent.PREFIX_TOKEN + key + PropertiesComponent.SUFFIX_TOKEN); + return pc.parseUri(pc.getPrefixToken() + key + pc.getSuffixToken()); } } catch (Exception e) { throw ObjectHelper.wrapRuntimeCamelException(e); Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java?rev=1179853&r1=1179852&r2=1179853&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java Thu Oct 6 21:07:28 2011 @@ -958,32 +958,53 @@ public class DefaultCamelContext extends // no language resolved return answer; } + + public String getPropertyPrefixToken() { + PropertiesComponent pc = getPropertiesComponent(); + + if (pc != null) { + return pc.getPrefixToken(); + } else { + return null; + } + } + + public String getPropertySuffixToken() { + PropertiesComponent pc = getPropertiesComponent(); + + if (pc != null) { + return pc.getSuffixToken(); + } else { + return null; + } + } public String resolvePropertyPlaceholders(String text) throws Exception { - // do not parse uris that are designated for the properties component as it will handle that itself - if (text != null && !text.startsWith("properties:") && text.contains(PropertiesComponent.PREFIX_TOKEN)) { - // the uri contains property placeholders so lookup mandatory properties component and let it parse it - Component component = hasComponent("properties"); - if (component == null) { - // then fallback to lookup the component - component = getRegistry().lookup("properties", Component.class); - } - if (component == null) { + // While it is more efficient to only do the lookup if we are sure we need the component, + // with custom tokens, we cannot know if the URI contains a property or not without having + // the component. We also lose fail-fast behavior for the missing component with this change. + PropertiesComponent pc = getPropertiesComponent(); + + // Do not parse uris that are designated for the properties component as it will handle that itself + if (text != null && !text.startsWith("properties:")) { + // No component, assume default tokens. + if (pc == null && text.contains(PropertiesComponent.DEFAULT_PREFIX_TOKEN)) { throw new IllegalArgumentException("PropertiesComponent with name properties must be defined" + " in CamelContext to support property placeholders."); + + // Component available, use actual tokens + } else if (pc != null && text.contains(pc.getPrefixToken())) { + // the parser will throw exception if property key was not found + String answer = pc.parseUri(text); + log.debug("Resolved text: {} -> {}", text, answer); + return answer; } - // force component to be created and registered as a component - PropertiesComponent pc = getComponent("properties", PropertiesComponent.class); - // the parser will throw exception if property key was not found - String answer = pc.parseUri(text); - log.debug("Resolved text: {} -> {}", text, answer); - return answer; } // return original text as is return text; } - + // Properties // ----------------------------------------------------------------------- @@ -2066,6 +2087,27 @@ public class DefaultCamelContext extends protected boolean shouldStartRoutes() { return isStarted() && !isStarting(); } + + /** + * Looks up the properties component if one may be resolved or has already been created. + * Returns {@code null} if one was not created or is not in the registry. + */ + protected PropertiesComponent getPropertiesComponent() { + Component component = hasComponent("properties"); + if (component == null) { + // then fallback to lookup the component + component = getRegistry().lookup("properties", Component.class); + } + + PropertiesComponent pc = null; + // Ensure that we don't create one if one is not really available. + if (component != null) { + // force component to be created and registered as a component + pc = getComponent("properties", PropertiesComponent.class); + } + + return pc; + } public void setDataFormats(Map<String, DataFormatDefinition> dataFormats) { this.dataFormats = dataFormats; Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/PropertyPlaceholderDelegateRegistry.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/PropertyPlaceholderDelegateRegistry.java?rev=1179853&r1=1179852&r2=1179853&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/impl/PropertyPlaceholderDelegateRegistry.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/impl/PropertyPlaceholderDelegateRegistry.java Thu Oct 6 21:07:28 2011 @@ -41,7 +41,11 @@ public class PropertyPlaceholderDelegate public Object lookup(String name) { try { - name = context.resolvePropertyPlaceholders(name); + // Must avoid attempting placeholder resolution when looking up + // the properties component or else we end up in an infinite loop. + if (!name.equals("properties")) { + name = context.resolvePropertyPlaceholders(name); + } return delegate.lookup(name); } catch (Exception e) { throw ObjectHelper.wrapRuntimeCamelException(e); @@ -50,7 +54,11 @@ public class PropertyPlaceholderDelegate public <T> T lookup(String name, Class<T> type) { try { - name = context.resolvePropertyPlaceholders(name); + // Must avoid attempting placeholder resolution when looking up + // the properties component or else we end up in an infinite loop. + if (!name.equals("properties")) { + name = context.resolvePropertyPlaceholders(name); + } return delegate.lookup(name, type); } catch (Exception e) { throw ObjectHelper.wrapRuntimeCamelException(e); Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java?rev=1179853&r1=1179852&r2=1179853&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java Thu Oct 6 21:07:28 2011 @@ -471,11 +471,17 @@ public abstract class ProcessorDefinitio if (value != null && value instanceof String) { // value must be enclosed with placeholder tokens String s = (String) value; - if (!s.startsWith(PropertiesComponent.PREFIX_TOKEN)) { - s = PropertiesComponent.PREFIX_TOKEN + s; + String prefixToken = routeContext.getCamelContext().getPropertyPrefixToken(); + String suffixToken = routeContext.getCamelContext().getPropertySuffixToken(); + if (prefixToken == null) { + throw new IllegalArgumentException("Property with name [" + local + "] uses property placeholders; however, no properties component is configured."); } - if (!s.endsWith(PropertiesComponent.SUFFIX_TOKEN)) { - s = s + PropertiesComponent.SUFFIX_TOKEN; + + if (!s.startsWith(prefixToken)) { + s = prefixToken + s; + } + if (!s.endsWith(suffixToken)) { + s = s + suffixToken; } value = s; } Modified: camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java?rev=1179853&r1=1179852&r2=1179853&view=diff ============================================================================== --- camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java (original) +++ camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java Thu Oct 6 21:07:28 2011 @@ -411,6 +411,16 @@ public abstract class AbstractCamelConte PropertiesParser.class); pc.setPropertiesParser(parser); } + + pc.setPropertyPrefix(def.getPropertyPrefix()); + pc.setPropertySuffix(def.getPropertySuffix()); + + if (def.isFallbackToUnaugmentedProperty() != null) { + pc.setFallbackToUnaugmentedProperty(def.isFallbackToUnaugmentedProperty()); + } + + pc.setPrefixToken(def.getPrefixToken()); + pc.setSuffixToken(def.getSuffixToken()); // register the properties component getContext().addComponent("properties", pc); Modified: camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/CamelPropertyPlaceholderDefinition.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/CamelPropertyPlaceholderDefinition.java?rev=1179853&r1=1179852&r2=1179853&view=diff ============================================================================== --- camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/CamelPropertyPlaceholderDefinition.java (original) +++ camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/CamelPropertyPlaceholderDefinition.java Thu Oct 6 21:07:28 2011 @@ -40,6 +40,21 @@ public class CamelPropertyPlaceholderDef @XmlAttribute private String propertiesParserRef; + + @XmlAttribute + private String propertyPrefix; + + @XmlAttribute + private String propertySuffix; + + @XmlAttribute + private Boolean fallbackToUnaugmentedProperty; + + @XmlAttribute + private String prefixToken; + + @XmlAttribute + private String suffixToken; public String getLocation() { return location; @@ -64,4 +79,44 @@ public class CamelPropertyPlaceholderDef public void setPropertiesParserRef(String propertiesParserRef) { this.propertiesParserRef = propertiesParserRef; } + + public String getPropertyPrefix() { + return propertyPrefix; + } + + public void setPropertyPrefix(String propertyPrefix) { + this.propertyPrefix = propertyPrefix; + } + + public String getPropertySuffix() { + return propertySuffix; + } + + public void setPropertySuffix(String propertySuffix) { + this.propertySuffix = propertySuffix; + } + + public Boolean isFallbackToUnaugmentedProperty() { + return fallbackToUnaugmentedProperty; + } + + public void setFallbackToUnaugmentedProperty(Boolean fallbackToUnaugmentedProperty) { + this.fallbackToUnaugmentedProperty = fallbackToUnaugmentedProperty; + } + + public String getPrefixToken() { + return prefixToken; + } + + public void setPrefixToken(String prefixToken) { + this.prefixToken = prefixToken; + } + + public String getSuffixToken() { + return suffixToken; + } + + public void setSuffixToken(String suffixToken) { + this.suffixToken = suffixToken; + } } Modified: camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/SpringPropertiesComponent2Test.xml URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/SpringPropertiesComponent2Test.xml?rev=1179853&r1=1179852&r2=1179853&view=diff ============================================================================== --- camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/SpringPropertiesComponent2Test.xml (original) +++ camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/properties/SpringPropertiesComponent2Test.xml Thu Oct 6 21:07:28 2011 @@ -26,26 +26,29 @@ <propertyPlaceholder id="properties" location="classpath:org/apache/camel/component/properties/cheese.properties" + prefixToken="[[" + suffixToken="]]" + propertyPrefix="cool." xmlns="http://camel.apache.org/schema/spring"/> <route> <from uri="direct:start"/> - <to uri="properties:{{cool.end}}"/> + <to uri="properties:[[end]]"/> </route> <route> <from uri="direct:bar"/> - <to uri="properties:mock:{{cool.bar}}"/> + <to uri="properties:mock:[[bar]]"/> </route> <route> <from uri="direct:start2"/> - <to uri="{{cool.end}}"/> + <to uri="[[end]]"/> </route> <route> <from uri="direct:bar2"/> - <to uri="mock:{{cool.bar}}"/> + <to uri="mock:[[bar]]"/> </route> </camelContext> Modified: camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/blueprint/BlueprintExplicitPropertiesRouteTest.java URL: http://svn.apache.org/viewvc/camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/blueprint/BlueprintExplicitPropertiesRouteTest.java?rev=1179853&r1=1179852&r2=1179853&view=diff ============================================================================== --- camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/blueprint/BlueprintExplicitPropertiesRouteTest.java (original) +++ camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/blueprint/BlueprintExplicitPropertiesRouteTest.java Thu Oct 6 21:07:28 2011 @@ -34,7 +34,6 @@ import static org.ops4j.pax.swissbox.tin /** * */ -@Ignore("Got NPE error when the CmPropertyPlaceholder init is called") @RunWith(JUnit4TestRunner.class) public class BlueprintExplicitPropertiesRouteTest extends OSGiBlueprintTestSupport { @@ -74,6 +73,7 @@ public class BlueprintExplicitProperties bundle(newBundle() .add("OSGI-INF/blueprint/test.xml", BlueprintExplicitPropertiesRouteTest.class.getResource("blueprint-16.xml")) .set(Constants.BUNDLE_SYMBOLICNAME, BlueprintExplicitPropertiesRouteTest.class.getName()) + .set(Constants.BUNDLE_VERSION, "1.0.0") .build()).noStart(), // using the features to install the camel components Modified: camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/blueprint/BlueprintPropertiesRouteTest.java URL: http://svn.apache.org/viewvc/camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/blueprint/BlueprintPropertiesRouteTest.java?rev=1179853&r1=1179852&r2=1179853&view=diff ============================================================================== --- camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/blueprint/BlueprintPropertiesRouteTest.java (original) +++ camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/blueprint/BlueprintPropertiesRouteTest.java Thu Oct 6 21:07:28 2011 @@ -34,7 +34,6 @@ import static org.ops4j.pax.swissbox.tin /** * */ -@Ignore("Got NPE error when the CmPropertyPlaceholder init is called") @RunWith(JUnit4TestRunner.class) public class BlueprintPropertiesRouteTest extends OSGiBlueprintTestSupport { @@ -74,6 +73,7 @@ public class BlueprintPropertiesRouteTes bundle(newBundle() .add("OSGI-INF/blueprint/test.xml", BlueprintPropertiesRouteTest.class.getResource("blueprint-17.xml")) .set(Constants.BUNDLE_SYMBOLICNAME, BlueprintPropertiesRouteTest.class.getName()) + .set(Constants.BUNDLE_VERSION, "1.0.0") .build()).noStart(), // using the features to install the camel components Modified: camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/blueprint/blueprint-16.xml URL: http://svn.apache.org/viewvc/camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/blueprint/blueprint-16.xml?rev=1179853&r1=1179852&r2=1179853&view=diff ============================================================================== --- camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/blueprint/blueprint-16.xml (original) +++ camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/blueprint/blueprint-16.xml Thu Oct 6 21:07:28 2011 @@ -26,20 +26,22 @@ <cm:property-placeholder id="myblueprint.placeholder" persistent-id="camel.blueprint"> <!-- list some properties for this test --> <cm:default-properties> - <cm:property name="result" value="mock:result"/> + <cm:property name="prefix.result" value="mock:result"/> </cm:default-properties> </cm:property-placeholder> <camelContext xmlns="http://camel.apache.org/schema/blueprint"> <!-- using Camel properties component and refer to the blueprint property placeholder by its id --> - <propertyPlaceholder id="properties" location="blueprint:myblueprint.placeholder"/> + <propertyPlaceholder id="properties" location="blueprint:myblueprint.placeholder" + prefixToken="[[" suffixToken="]]" + propertyPrefix="prefix."/> <!-- in the route we can use {{ }} placeholders which will lookup in blueprint --> <route> <from uri="direct:start"/> <to uri="mock:foo"/> - <to uri="{{result}}"/> + <to uri="[[result]]"/> </route> </camelContext>