CAMEL-7647: Added logic to detect quartz2/spring schedulers on route inputs in camel-blueprint. CAMEL-7648: Fixed osgi to be able to load classes using the camel context classloader, so it can load quartz2 scheduler etc.
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/edf9014f Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/edf9014f Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/edf9014f Branch: refs/heads/camel-2.13.x Commit: edf9014fe6b01d3874ac2eee535bc1c50318d90b Parents: 3c7bfcc Author: Claus Ibsen <davscl...@apache.org> Authored: Tue Jul 29 12:02:58 2014 +0200 Committer: Claus Ibsen <davscl...@apache.org> Committed: Tue Jul 29 13:12:07 2014 +0200 ---------------------------------------------------------------------- .../handler/CamelNamespaceHandler.java | 43 ++++++++-- .../camel/core/osgi/OsgiCamelContextHelper.java | 2 +- .../camel/core/osgi/OsgiClassResolver.java | 20 ++++- .../camel/core/osgi/CamelOsgiTestSupport.java | 2 +- tests/camel-itest-osgi/pom.xml | 5 ++ .../OSGiBlueprintQuarz2SchedulerTest.java | 86 ++++++++++++++++++++ .../camel/itest/osgi/blueprint/blueprint-28.xml | 28 +++++++ 7 files changed, 173 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/edf9014f/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/handler/CamelNamespaceHandler.java ---------------------------------------------------------------------- diff --git a/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/handler/CamelNamespaceHandler.java b/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/handler/CamelNamespaceHandler.java index e25621d..9b982e0 100644 --- a/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/handler/CamelNamespaceHandler.java +++ b/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/handler/CamelNamespaceHandler.java @@ -19,22 +19,19 @@ package org.apache.camel.blueprint.handler; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.concurrent.Callable; - import javax.xml.bind.Binder; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - import org.apache.aries.blueprint.BeanProcessor; import org.apache.aries.blueprint.ComponentDefinitionRegistry; import org.apache.aries.blueprint.ComponentDefinitionRegistryProcessor; @@ -80,13 +77,13 @@ import org.apache.camel.spi.DataFormatResolver; import org.apache.camel.spi.LanguageResolver; import org.apache.camel.spi.NamespaceAware; import org.apache.camel.util.ObjectHelper; +import org.apache.camel.util.URISupport; import org.apache.camel.util.blueprint.KeyStoreParametersFactoryBean; import org.apache.camel.util.blueprint.SSLContextParametersFactoryBean; import org.apache.camel.util.blueprint.SecureRandomParametersFactoryBean; import org.apache.camel.util.jsse.KeyStoreParameters; import org.apache.camel.util.jsse.SSLContextParameters; import org.apache.camel.util.jsse.SecureRandomParameters; - import org.osgi.framework.Bundle; import org.osgi.service.blueprint.container.BlueprintContainer; import org.osgi.service.blueprint.container.ComponentDefinitionException; @@ -96,6 +93,10 @@ import org.osgi.service.blueprint.reflect.Metadata; import org.osgi.service.blueprint.reflect.RefMetadata; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; import static org.osgi.service.blueprint.reflect.ComponentMetadata.ACTIVATION_LAZY; import static org.osgi.service.blueprint.reflect.ServiceReferenceMetadata.AVAILABILITY_MANDATORY; @@ -896,6 +897,7 @@ public class CamelNamespaceHandler implements NamespaceHandler { if (defs != null) { for (FromDefinition def : defs) { findUriComponent(def.getUri(), components); + findSchedulerUriComponent(def.getUri(), components); } } } @@ -976,6 +978,33 @@ public class CamelNamespaceHandler implements NamespaceHandler { } } + private void findSchedulerUriComponent(String uri, Set<String> components) { + + // the input may use a scheduler which can be quartz or spring + if (uri != null) { + try { + URI u = new URI(uri); + Map<String, Object> parameters = URISupport.parseParameters(u); + Object value = parameters.get("scheduler"); + if (value == null) { + value = parameters.get("consumer.scheduler"); + } + if (value != null) { + // the scheduler can be quartz2 or spring based, so add reference to camel component + // from these components os blueprint knows about the requirement + String name = value.toString(); + if ("quartz2".equals(name)) { + components.add("quartz2"); + } else if ("spring".equals(name)) { + components.add("spring-event"); + } + } + } catch (URISyntaxException e) { + // ignore + } + } + } + } } http://git-wip-us.apache.org/repos/asf/camel/blob/edf9014f/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiCamelContextHelper.java ---------------------------------------------------------------------- diff --git a/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiCamelContextHelper.java b/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiCamelContextHelper.java index 1df4a3b..08ff669 100644 --- a/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiCamelContextHelper.java +++ b/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiCamelContextHelper.java @@ -40,7 +40,7 @@ public final class OsgiCamelContextHelper { LOG.debug("Using OsgiManagementNameStrategy"); camelContext.setManagementNameStrategy(new OsgiManagementNameStrategy(camelContext, bundleContext)); LOG.debug("Using OsgiClassResolver"); - camelContext.setClassResolver(new OsgiClassResolver(bundleContext)); + camelContext.setClassResolver(new OsgiClassResolver(camelContext, bundleContext)); LOG.debug("Using OsgiFactoryFinderResolver"); camelContext.setFactoryFinderResolver(new OsgiFactoryFinderResolver(bundleContext)); LOG.debug("Using OsgiPackageScanClassResolver"); http://git-wip-us.apache.org/repos/asf/camel/blob/edf9014f/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiClassResolver.java ---------------------------------------------------------------------- diff --git a/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiClassResolver.java b/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiClassResolver.java index 66c4008..481caff 100644 --- a/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiClassResolver.java +++ b/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiClassResolver.java @@ -22,6 +22,7 @@ import java.net.URL; import java.util.Enumeration; import java.util.Vector; +import org.apache.camel.CamelContext; import org.apache.camel.impl.DefaultClassResolver; import org.apache.camel.util.CastUtils; import org.apache.camel.util.FileUtil; @@ -35,9 +36,11 @@ import org.slf4j.LoggerFactory; public class OsgiClassResolver extends DefaultClassResolver { private static final Logger LOG = LoggerFactory.getLogger(OsgiClassResolver.class); - public BundleContext bundleContext; - - public OsgiClassResolver(BundleContext context) { + private final CamelContext camelContext; + private final BundleContext bundleContext; + + public OsgiClassResolver(CamelContext camelContext, BundleContext context) { + this.camelContext = camelContext; this.bundleContext = context; } @@ -52,7 +55,16 @@ public class OsgiClassResolver extends DefaultClassResolver { Class<?> clazz = ObjectHelper.loadSimpleType(name); if (clazz == null) { clazz = doLoadClass(name, bundleContext.getBundle()); - LOG.trace("Loading class {} using BundleContext {} -> {}", new Object[]{name, bundleContext.getBundle(), clazz}); + if (LOG.isTraceEnabled()) { + LOG.trace("Loading class {} using BundleContext {} -> {}", new Object[]{name, bundleContext.getBundle(), clazz}); + } + } + if (clazz == null && camelContext != null) { + // fallback and load class using the application context classloader + clazz = super.loadClass(name, camelContext.getApplicationContextClassLoader()); + if (LOG.isTraceEnabled()) { + LOG.trace("Loading class {} using CamelContext {} -> {}", new Object[]{name, camelContext, clazz}); + } } return clazz; } http://git-wip-us.apache.org/repos/asf/camel/blob/edf9014f/components/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/CamelOsgiTestSupport.java ---------------------------------------------------------------------- diff --git a/components/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/CamelOsgiTestSupport.java b/components/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/CamelOsgiTestSupport.java index 6adbe1c..eb92465 100644 --- a/components/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/CamelOsgiTestSupport.java +++ b/components/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/CamelOsgiTestSupport.java @@ -28,7 +28,7 @@ public class CamelOsgiTestSupport extends Assert { private MockBundle bundle = new CamelMockBundle(); private MockBundleContext bundleContext = new CamelMockBundleContext(bundle); private OsgiPackageScanClassResolver packageScanClassResolver = new OsgiPackageScanClassResolver(bundleContext); - private ClassResolver classResolver = new OsgiClassResolver(bundleContext); + private ClassResolver classResolver = new OsgiClassResolver(null, bundleContext); @Before public void setUp() throws Exception { http://git-wip-us.apache.org/repos/asf/camel/blob/edf9014f/tests/camel-itest-osgi/pom.xml ---------------------------------------------------------------------- diff --git a/tests/camel-itest-osgi/pom.xml b/tests/camel-itest-osgi/pom.xml index c6fe417..9501e61 100644 --- a/tests/camel-itest-osgi/pom.xml +++ b/tests/camel-itest-osgi/pom.xml @@ -221,6 +221,11 @@ <scope>test</scope> </dependency> <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-quartz2</artifactId> + <scope>test</scope> + </dependency> + <dependency> <groupId>ca.uhn.hapi</groupId> <artifactId>hapi-structures-v24</artifactId> <version>${hapi-version}</version> http://git-wip-us.apache.org/repos/asf/camel/blob/edf9014f/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/blueprint/OSGiBlueprintQuarz2SchedulerTest.java ---------------------------------------------------------------------- diff --git a/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/blueprint/OSGiBlueprintQuarz2SchedulerTest.java b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/blueprint/OSGiBlueprintQuarz2SchedulerTest.java new file mode 100644 index 0000000..fae4496 --- /dev/null +++ b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/blueprint/OSGiBlueprintQuarz2SchedulerTest.java @@ -0,0 +1,86 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.camel.itest.osgi.blueprint; + +import org.apache.camel.CamelContext; +import org.apache.camel.Exchange; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.component.mock.MockEndpoint; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.junit.Configuration; +import org.ops4j.pax.exam.junit.JUnit4TestRunner; +import org.osgi.framework.Constants; + +import static org.ops4j.pax.exam.OptionUtils.combine; +import static org.ops4j.pax.swissbox.tinybundles.core.TinyBundles.newBundle; + +/** + * @version + */ +@RunWith(JUnit4TestRunner.class) +public class OSGiBlueprintQuarz2SchedulerTest extends OSGiBlueprintTestSupport { + + private static final String NAME = OSGiBlueprintQuarz2SchedulerTest.class.getName(); + + @Override + public void setUp() throws Exception { + deleteDirectory("target/paxrunner/target/foo"); + super.setUp(); + } + + @Test + public void testQuartz2Scheduler() throws Exception { + // start bundle + getInstalledBundle(NAME).start(); + + // must use the camel context from osgi + CamelContext ctx = getOsgiService(CamelContext.class, "(camel.context.symbolicname=" + NAME + ")", 10000); + + MockEndpoint mock = ctx.getEndpoint("mock:result", MockEndpoint.class); + mock.expectedMessageCount(2); + + ProducerTemplate myTemplate = ctx.createProducerTemplate(); + myTemplate.start(); + + myTemplate.sendBodyAndHeader("file:target/foo", "Hello World", Exchange.FILE_NAME, "hello.txt"); + myTemplate.sendBodyAndHeader("file:target/foo", "Bye World", Exchange.FILE_NAME, "bye.txt"); + + mock.assertIsSatisfied(); + + myTemplate.stop(); + } + + @Configuration + public static Option[] configure() throws Exception { + + Option[] options = combine( + getDefaultCamelKarafOptions(), + + bundle(newBundle() + .add("OSGI-INF/blueprint/test.xml", OSGiBlueprintTestSupport.class.getResource("blueprint-28.xml")) + .set(Constants.BUNDLE_SYMBOLICNAME, NAME) + .build()).noStart(), + + // using the features to install the camel components + loadCamelFeatures("camel-blueprint", "camel-quartz2")); + + return options; + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/edf9014f/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/blueprint/blueprint-28.xml ---------------------------------------------------------------------- diff --git a/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/blueprint/blueprint-28.xml b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/blueprint/blueprint-28.xml new file mode 100644 index 0000000..7aace2c --- /dev/null +++ b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/blueprint/blueprint-28.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You 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. +--> +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" + xmlns:camel="http://camel.apache.org/schema/blueprint"> + + <camel:camelContext id="camel1"> + <camel:route> + <camel:from uri="file:target/foo?scheduler=quartz2&scheduler.cron=0/2+*+*+*+*+?"/> + <camel:to uri="mock:result"/> + </camel:route> + </camel:camelContext> + +</blueprint>