This is an automated email from the ASF dual-hosted git repository. lburgazzoli pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel.git
commit 3e65db32ae35eeb8748d381bba27594863edc9a3 Author: Luca Burgazzoli <lburgazz...@gmail.com> AuthorDate: Wed Mar 3 18:43:55 2021 +0100 CAMEL-16285: Extensible ResourceHelper --- .../org/apache/camel/resource-resolver/bean | 2 + .../apache/camel/language/bean/BeanLanguage.java | 1 + .../camel/language/bean/BeanResourceResolver.java | 96 +++++++ .../camel/spi/annotations/ResourceResolver.java} | 35 +-- .../org/apache/camel/ExtendedCamelContext.java | 11 + .../main/java/org/apache/camel/spi/Resource.java | 67 ++--- .../java/org/apache/camel/spi/ResourceLoader.java} | 39 ++- .../org/apache/camel/spi/ResourceResolver.java | 45 ++++ .../org/apache/camel/resource-resolver/classpath | 2 + .../org/apache/camel/resource-resolver/file | 2 + .../org/apache/camel/resource-resolver/http | 2 + .../org/apache/camel/resource-resolver/ref | 2 + .../camel/impl/engine/AbstractCamelContext.java | 22 ++ .../engine/DefaultPackageScanResourceResolver.java | 53 ++-- .../apache/camel/impl/engine/DefaultResource.java | 69 ----- .../camel/impl/engine/DefaultResourceLoader.java | 133 ++++++++++ .../impl/engine/DefaultResourceResolvers.java | 281 +++++++++++++++++++++ .../camel/impl/engine/SimpleCamelContext.java | 12 + .../camel/impl/ExtendedCamelContextConfigurer.java | 6 + .../camel/impl/lw/LightweightCamelContext.java | 11 + .../impl/lw/LightweightRuntimeCamelContext.java | 11 + .../ValidatorEndpointClearCachedSchemaTest.java | 10 +- .../ValidatorWithResourceResolverRouteTest.java | 2 +- .../apache/camel/urlhandler/custom/Handler.java | 29 ++- .../org/apache/camel/urlhandler/pd/Handler.java | 117 ++++----- .../org/apache/camel/util/ResourceHelperTest.java | 87 +------ .../org/apache/camel/util/ResourceLoaderTest.java | 207 +++++++++++++++ .../org/apache/camel/support/ResourceHelper.java | 200 +++++---------- .../camel/support/ResourceResolverSupport.java | 83 ++++++ .../dsl/java/joor/JavaRoutesBuilderLoaderTest.java | 8 +- .../apache/camel/dsl/xml/io/XmlLoadRestTest.java | 7 +- .../org/apache/camel/dsl/xml/io/XmlLoadTest.java | 4 +- .../dsl/xml/io/XmlRoutesBuilderLoaderTest.java | 7 +- .../camel/dsl/xml/jaxb/JaxbXmlLoadRestTest.java | 7 +- .../apache/camel/dsl/xml/jaxb/JaxbXmlLoadTest.java | 4 +- .../xml/jaxb/JaxbXmlRoutesBuilderLoaderTest.java | 7 +- .../camel/dsl/yaml/support/YamlTestSupport.groovy | 5 +- .../camel/maven/packaging/SpiGeneratorMojo.java | 7 +- .../camel/spi/annotations/ResourceResolver.java | 35 +-- 39 files changed, 1188 insertions(+), 540 deletions(-) diff --git a/components/camel-bean/src/generated/resources/META-INF/services/org/apache/camel/resource-resolver/bean b/components/camel-bean/src/generated/resources/META-INF/services/org/apache/camel/resource-resolver/bean new file mode 100644 index 0000000..65ea78f --- /dev/null +++ b/components/camel-bean/src/generated/resources/META-INF/services/org/apache/camel/resource-resolver/bean @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.language.bean.BeanResourceResolver diff --git a/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanLanguage.java b/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanLanguage.java index 6c7b515..3a5745d 100644 --- a/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanLanguage.java +++ b/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanLanguage.java @@ -49,6 +49,7 @@ import org.apache.camel.util.URISupport; */ @org.apache.camel.spi.annotations.Language("bean") public class BeanLanguage extends LanguageSupport implements PropertyConfigurer, StaticService { + public static final String LANGUAGE = "bean"; private volatile BeanComponent beanComponent; private volatile ParameterMappingStrategy parameterMappingStrategy; diff --git a/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanResourceResolver.java b/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanResourceResolver.java new file mode 100644 index 0000000..11c4955 --- /dev/null +++ b/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanResourceResolver.java @@ -0,0 +1,96 @@ +/* + * 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.language.bean; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.camel.CamelContext; +import org.apache.camel.Exchange; +import org.apache.camel.spi.Resource; +import org.apache.camel.spi.annotations.ResourceResolver; +import org.apache.camel.support.DefaultExchange; +import org.apache.camel.support.ResourceResolverSupport; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@ResourceResolver(BeanResourceResolver.SCHEME) +public class BeanResourceResolver extends ResourceResolverSupport { + public static final String SCHEME = "bean"; + private static final Logger LOGGER = LoggerFactory.getLogger(BeanResourceResolver.class); + + public BeanResourceResolver() { + super(SCHEME); + } + + @Override + public Resource createResource(String location) { + final String expression = getRemaining(location); + + LOGGER.trace("Creating resource from expression {}", expression); + + return new Resource() { + @Override + public String getLocation() { + return location; + } + + @Override + public boolean exists() { + return false; + } + + @Override + public InputStream getInputStream() throws IOException { + final CamelContext context = getCamelContext(); + final Exchange dummy = new DefaultExchange(context); + + InputStream answer = null; + Object out = evaluate(dummy, expression); + + if (dummy.getException() != null) { + throw new IOException( + "Cannot find resource: " + location + " from calling the bean", dummy.getException()); + } + + if (out != null) { + answer = context.getTypeConverter().tryConvertTo(InputStream.class, dummy, out); + if (answer == null) { + String text = context.getTypeConverter().tryConvertTo(String.class, dummy, out); + if (text != null) { + answer = new ByteArrayInputStream(text.getBytes()); + } + } + } + + if (answer == null) { + throw new IOException("Cannot find resource: " + location + " from calling the bean"); + } + + return answer; + } + }; + } + + private Object evaluate(Exchange dummy, String expression) { + return getCamelContext() + .resolveLanguage(BeanLanguage.LANGUAGE) + .createExpression(expression) + .evaluate(dummy, Object.class); + } +} diff --git a/core/camel-core/src/test/java/org/apache/camel/urlhandler/custom/Handler.java b/core/camel-api/src/generated/java/org/apache/camel/spi/annotations/ResourceResolver.java similarity index 51% copy from core/camel-core/src/test/java/org/apache/camel/urlhandler/custom/Handler.java copy to core/camel-api/src/generated/java/org/apache/camel/spi/annotations/ResourceResolver.java index 9207b0b..0ea471c 100644 --- a/core/camel-core/src/test/java/org/apache/camel/urlhandler/custom/Handler.java +++ b/core/camel-api/src/generated/java/org/apache/camel/spi/annotations/ResourceResolver.java @@ -14,29 +14,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.urlhandler.custom; +package org.apache.camel.spi.annotations; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLStreamHandler; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; -public class Handler extends URLStreamHandler { - @Override - protected URLConnection openConnection(URL u) throws IOException { - final String echo = u.getHost(); - return new URLConnection(u) { - @Override - public void connect() throws IOException { - connected = true; - } +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Target({ ElementType.TYPE }) +@ServiceFactory("resource-resolver") +public @interface ResourceResolver { + + String value(); - @Override - public InputStream getInputStream() throws IOException { - return new ByteArrayInputStream(echo.getBytes()); - } - }; - } } diff --git a/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java b/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java index c68403e..114eeab 100644 --- a/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java +++ b/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java @@ -57,6 +57,7 @@ import org.apache.camel.spi.PackageScanResourceResolver; import org.apache.camel.spi.ProcessorFactory; import org.apache.camel.spi.ReactiveExecutor; import org.apache.camel.spi.Registry; +import org.apache.camel.spi.ResourceLoader; import org.apache.camel.spi.RestBindingJaxbDataFormatFactory; import org.apache.camel.spi.RouteController; import org.apache.camel.spi.RouteFactory; @@ -649,6 +650,16 @@ public interface ExtendedCamelContext extends CamelContext { void setRoutesLoader(RoutesLoader routesLoader); /** + * Gets the {@link ResourceLoader} to be used. + */ + ResourceLoader getResourceLoader(); + + /** + * Sets a custom {@link ResourceLoader} to be used. + */ + void setResourceLoader(ResourceLoader resourceLoader); + + /** * Gets the {@link ModelToXMLDumper} to be used. */ ModelToXMLDumper getModelToXMLDumper(); diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/Resource.java b/core/camel-api/src/main/java/org/apache/camel/spi/Resource.java index 7e4c324..fb336c7 100644 --- a/core/camel-api/src/main/java/org/apache/camel/spi/Resource.java +++ b/core/camel-api/src/main/java/org/apache/camel/spi/Resource.java @@ -16,10 +16,11 @@ */ package org.apache.camel.spi; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; -import java.nio.charset.StandardCharsets; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; /** * Describe a resource, such as a file or class path resource. @@ -31,61 +32,33 @@ public interface Resource { String getLocation(); /** - * Returns an input stream that reads from the underlying resource. - * </p> - * Each invocation must return a new {@link InputStream} instance. + * Whether this resource exists.. */ - InputStream getInputStream() throws IOException; + boolean exists(); /** - * Finds a resource with a given name. - * - * @see Class#getResourceAsStream(String) + * The {@link URI} of the resource. + * </p> + * The default implementation creates a {@code URI} object from resource location. */ - static Resource fromClasspath(String location) { - return fromClasspath(Resource.class, location); + default URI getURI() { + return URI.create(getLocation()); } /** - * Finds a resource with a given name. - * - * @see Class#getResourceAsStream(String) - */ - static Resource fromClasspath(Class<?> type, String location) { - return new Resource() { - @Override - public String getLocation() { - return location; - } - - @Override - public InputStream getInputStream() throws IOException { - return type.getResourceAsStream(location); - } - }; - } - - /** - * Create a resource from bytes. + * The {@link URL} for the resource or <code>null</code> if the URL can not be computed. + * </p> + * The default implementation creates a {@code URI} object from resource location. */ - static Resource fromBytes(String location, byte[] content) { - return new Resource() { - @Override - public String getLocation() { - return location; - } - - @Override - public InputStream getInputStream() throws IOException { - return new ByteArrayInputStream(content); - } - }; + default URL getURL() throws MalformedURLException { + URI uri = getURI(); + return uri != null ? uri.toURL() : null; } /** - * Create a resource from a string. + * Returns an input stream that reads from the underlying resource. + * </p> + * Each invocation must return a new {@link InputStream} instance. */ - static Resource fromString(String location, String content) { - return fromBytes(location, content.getBytes(StandardCharsets.UTF_8)); - } + InputStream getInputStream() throws IOException; } diff --git a/core/camel-core/src/test/java/org/apache/camel/urlhandler/custom/Handler.java b/core/camel-api/src/main/java/org/apache/camel/spi/ResourceLoader.java similarity index 51% copy from core/camel-core/src/test/java/org/apache/camel/urlhandler/custom/Handler.java copy to core/camel-api/src/main/java/org/apache/camel/spi/ResourceLoader.java index 9207b0b..5f96beb1 100644 --- a/core/camel-core/src/test/java/org/apache/camel/urlhandler/custom/Handler.java +++ b/core/camel-api/src/main/java/org/apache/camel/spi/ResourceLoader.java @@ -14,29 +14,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.urlhandler.custom; +package org.apache.camel.spi; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLStreamHandler; +import org.apache.camel.CamelContextAware; -public class Handler extends URLStreamHandler { - @Override - protected URLConnection openConnection(URL u) throws IOException { - final String echo = u.getHost(); - return new URLConnection(u) { - @Override - public void connect() throws IOException { - connected = true; - } +/** + * SPI for loading resources. + */ +public interface ResourceLoader extends CamelContextAware { + /** + * Service factory key. + */ + String FACTORY = "resource-loader"; - @Override - public InputStream getInputStream() throws IOException { - return new ByteArrayInputStream(echo.getBytes()); - } - }; - } + /** + * Loads {@link Resource} from uri. + * + * @param uri the location of the resource to resolve. + * @return an optional {@link Resource} + */ + Resource resolveResource(String uri); } diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/ResourceResolver.java b/core/camel-api/src/main/java/org/apache/camel/spi/ResourceResolver.java new file mode 100644 index 0000000..1330a11 --- /dev/null +++ b/core/camel-api/src/main/java/org/apache/camel/spi/ResourceResolver.java @@ -0,0 +1,45 @@ +/* + * 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.spi; + +import org.apache.camel.CamelContextAware; +import org.apache.camel.StaticService; + +/** + * SPI for loading resources. + */ +public interface ResourceResolver extends StaticService, CamelContextAware { + /** + * Service factory base path for scheme specific resolver. + */ + String FACTORY_PATH = "META-INF/services/org/apache/camel/resource-resolver/"; + + /** + * The supported resource scheme. + * <p/> + * Implementations should support a single scheme only. + */ + String getSupportedScheme(); + + /** + * Resolve a {@link Resource} from a give uri. + * + * @param location the location of the resource to resolve. + * @return an {@link Resource}, null if was not possible to resolve the resource. + */ + Resource resolve(String location); +} diff --git a/core/camel-base-engine/src/generated/resources/META-INF/services/org/apache/camel/resource-resolver/classpath b/core/camel-base-engine/src/generated/resources/META-INF/services/org/apache/camel/resource-resolver/classpath new file mode 100644 index 0000000..b5aa541 --- /dev/null +++ b/core/camel-base-engine/src/generated/resources/META-INF/services/org/apache/camel/resource-resolver/classpath @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.impl.engine.DefaultResourceResolvers$ClasspathResolver diff --git a/core/camel-base-engine/src/generated/resources/META-INF/services/org/apache/camel/resource-resolver/file b/core/camel-base-engine/src/generated/resources/META-INF/services/org/apache/camel/resource-resolver/file new file mode 100644 index 0000000..aa1520e --- /dev/null +++ b/core/camel-base-engine/src/generated/resources/META-INF/services/org/apache/camel/resource-resolver/file @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.impl.engine.DefaultResourceResolvers$FileResolver diff --git a/core/camel-base-engine/src/generated/resources/META-INF/services/org/apache/camel/resource-resolver/http b/core/camel-base-engine/src/generated/resources/META-INF/services/org/apache/camel/resource-resolver/http new file mode 100644 index 0000000..633e677 --- /dev/null +++ b/core/camel-base-engine/src/generated/resources/META-INF/services/org/apache/camel/resource-resolver/http @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.impl.engine.DefaultResourceResolvers$HttpResolver diff --git a/core/camel-base-engine/src/generated/resources/META-INF/services/org/apache/camel/resource-resolver/ref b/core/camel-base-engine/src/generated/resources/META-INF/services/org/apache/camel/resource-resolver/ref new file mode 100644 index 0000000..e2ca4d4 --- /dev/null +++ b/core/camel-base-engine/src/generated/resources/META-INF/services/org/apache/camel/resource-resolver/ref @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.impl.engine.DefaultResourceResolvers$RefResolver diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java index eab4f12..45a1a92 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java @@ -133,6 +133,7 @@ import org.apache.camel.spi.PropertiesComponent; import org.apache.camel.spi.ReactiveExecutor; import org.apache.camel.spi.Registry; import org.apache.camel.spi.ReifierStrategy; +import org.apache.camel.spi.ResourceLoader; import org.apache.camel.spi.RestBindingJaxbDataFormatFactory; import org.apache.camel.spi.RestConfiguration; import org.apache.camel.spi.RestRegistry; @@ -290,6 +291,7 @@ public abstract class AbstractCamelContext extends BaseService private volatile BeanProcessorFactory beanProcessorFactory; private volatile XMLRoutesDefinitionLoader xmlRoutesDefinitionLoader; private volatile RoutesLoader routesLoader; + private volatile ResourceLoader resourceLoader; private volatile ModelToXMLDumper modelToXMLDumper; private volatile RestBindingJaxbDataFormatFactory restBindingJaxbDataFormatFactory; private volatile RuntimeCamelCatalog runtimeCamelCatalog; @@ -3653,6 +3655,7 @@ public abstract class AbstractCamelContext extends BaseService getUnitOfWorkFactory(); getRouteController(); getRoutesLoader(); + getResourceLoader(); try { getRestRegistryFactory(); @@ -4601,6 +4604,23 @@ public abstract class AbstractCamelContext extends BaseService this.routesLoader = doAddService(routesLoader); } + @Override + public ResourceLoader getResourceLoader() { + if (resourceLoader == null) { + synchronized (lock) { + if (resourceLoader == null) { + setResourceLoader(createResourceLoader()); + } + } + } + return resourceLoader; + } + + @Override + public void setResourceLoader(ResourceLoader resourceLoader) { + this.resourceLoader = doAddService(resourceLoader); + } + public ModelToXMLDumper getModelToXMLDumper() { if (modelToXMLDumper == null) { synchronized (lock) { @@ -4860,6 +4880,8 @@ public abstract class AbstractCamelContext extends BaseService protected abstract RoutesLoader createRoutesLoader(); + protected abstract ResourceLoader createResourceLoader(); + protected abstract ModelToXMLDumper createModelToXMLDumper(); protected abstract RestBindingJaxbDataFormatFactory createRestBindingJaxbDataFormatFactory(); diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultPackageScanResourceResolver.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultPackageScanResourceResolver.java index aacd075..ea775c0 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultPackageScanResourceResolver.java +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultPackageScanResourceResolver.java @@ -26,7 +26,6 @@ import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; import java.net.URLDecoder; -import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; @@ -38,14 +37,15 @@ import java.util.jar.JarEntry; import java.util.jar.JarInputStream; import org.apache.camel.CamelContextAware; +import org.apache.camel.ExtendedCamelContext; import org.apache.camel.NonManagedService; import org.apache.camel.spi.PackageScanResourceResolver; import org.apache.camel.spi.Resource; +import org.apache.camel.spi.ResourceLoader; import org.apache.camel.support.ResourceHelper; import org.apache.camel.util.AntPathMatcher; import org.apache.camel.util.IOHelper; import org.apache.camel.util.ObjectHelper; -import org.apache.camel.util.function.ThrowingSupplier; /** * Default implement of {@link org.apache.camel.spi.PackageScanResourceResolver} @@ -84,15 +84,11 @@ public class DefaultPackageScanResourceResolver extends BasePackageScanResolver findInClasspath(root, resources, subPattern); } } else { + final ExtendedCamelContext ecc = getCamelContext().adapt(ExtendedCamelContext.class); + final ResourceLoader loader = ecc.getResourceLoader(); + // its a single resource so load it directly - resources.add(new DefaultResource( - location, - new ThrowingSupplier<InputStream, IOException>() { - @Override - public InputStream get() throws IOException { - return ResourceHelper.resolveMandatoryResourceAsInputStream(getCamelContext(), location); - } - })); + resources.add(loader.resolveResource(location)); } } @@ -102,16 +98,11 @@ public class DefaultPackageScanResourceResolver extends BasePackageScanResolver String subPattern) throws Exception { - for (Path path : ResourceHelper.findInFileSystem(dir.toPath(), subPattern)) { + final ExtendedCamelContext ecc = getCamelContext().adapt(ExtendedCamelContext.class); + final ResourceLoader loader = ecc.getResourceLoader(); - resources.add(new DefaultResource( - path.toString(), - new ThrowingSupplier<InputStream, IOException>() { - @Override - public InputStream get() throws IOException { - return Files.newInputStream(path); - } - })); + for (Path path : ResourceHelper.findInFileSystem(dir.toPath(), subPattern)) { + resources.add(loader.resolveResource("file:" + path.toString())); } } @@ -276,14 +267,10 @@ public class DefaultPackageScanResourceResolver extends BasePackageScanResolver boolean match = PATH_MATCHER.match(subPattern, shortName); log.debug("Found resource: {} matching pattern: {} -> {}", shortName, subPattern, match); if (match) { - resources.add(new DefaultResource( - name, - new ThrowingSupplier<InputStream, IOException>() { - @Override - public InputStream get() throws IOException { - return getCamelContext().getClassResolver().loadResourceAsStream(name); - } - })); + final ExtendedCamelContext ecc = getCamelContext().adapt(ExtendedCamelContext.class); + final ResourceLoader loader = ecc.getResourceLoader(); + + resources.add(loader.resolveResource(name)); } } } @@ -324,14 +311,10 @@ public class DefaultPackageScanResourceResolver extends BasePackageScanResolver boolean match = PATH_MATCHER.match(subPattern, name); log.debug("Found resource: {} matching pattern: {} -> {}", name, subPattern, match); if (match) { - resources.add(new DefaultResource( - name, - new ThrowingSupplier<InputStream, IOException>() { - @Override - public InputStream get() throws IOException { - return new FileInputStream(file); - } - })); + final ExtendedCamelContext ecc = getCamelContext().adapt(ExtendedCamelContext.class); + final ResourceLoader loader = ecc.getResourceLoader(); + + resources.add(loader.resolveResource("file:" + file.getPath())); } } } diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultResource.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultResource.java deleted file mode 100644 index 437a303..0000000 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultResource.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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.impl.engine; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Objects; - -import org.apache.camel.spi.Resource; -import org.apache.camel.util.ObjectHelper; -import org.apache.camel.util.function.ThrowingSupplier; - -public class DefaultResource implements Resource { - private final String location; - private final ThrowingSupplier<InputStream, IOException> inputStreamSupplier; - - public DefaultResource(String location, ThrowingSupplier<InputStream, IOException> inputStreamSupplier) { - this.location = ObjectHelper.notNull(location, "location"); - this.inputStreamSupplier = ObjectHelper.notNull(inputStreamSupplier, "inputStreamSupplier"); - } - - @Override - public String getLocation() { - return location; - } - - @Override - public InputStream getInputStream() throws IOException { - return inputStreamSupplier.get(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof Resource)) { - return false; - } - Resource resource = (Resource) o; - return getLocation().equals(resource.getLocation()); - } - - @Override - public int hashCode() { - return Objects.hash(getLocation()); - } - - @Override - public String toString() { - return "DefaultResource{" + - "location='" + location + '\'' + - '}'; - } -} diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultResourceLoader.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultResourceLoader.java new file mode 100644 index 0000000..4af5f3f --- /dev/null +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultResourceLoader.java @@ -0,0 +1,133 @@ +/* + * 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.impl.engine; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.camel.CamelContext; +import org.apache.camel.CamelContextAware; +import org.apache.camel.ExtendedCamelContext; +import org.apache.camel.spi.FactoryFinder; +import org.apache.camel.spi.Resource; +import org.apache.camel.spi.ResourceLoader; +import org.apache.camel.spi.ResourceResolver; +import org.apache.camel.spi.RoutesBuilderLoader; +import org.apache.camel.support.ResolverHelper; +import org.apache.camel.support.service.ServiceHelper; +import org.apache.camel.support.service.ServiceSupport; +import org.apache.camel.util.ObjectHelper; +import org.apache.camel.util.StringHelper; + +/** + * Default {@link ResourceLoader}. + */ +public class DefaultResourceLoader extends ServiceSupport implements ResourceLoader { + /** + * Prefix to use for looking up existing {@link ResourceLoader} from the {@link org.apache.camel.spi.Registry}. + */ + public static final String RESOURCE_LOADER_KEY_PREFIX = "resource-loader-"; + + private final Map<String, ResourceResolver> resolvers; + private CamelContext camelContext; + + public DefaultResourceLoader() { + this(null); + } + + public DefaultResourceLoader(CamelContext camelContext) { + this.camelContext = camelContext; + this.resolvers = new ConcurrentHashMap<>(); + } + + @Override + public void doStop() throws Exception { + super.doStop(); + + ServiceHelper.stopService(resolvers.values()); + + resolvers.clear(); + } + + @Override + public CamelContext getCamelContext() { + return camelContext; + } + + @Override + public void setCamelContext(CamelContext camelContext) { + this.camelContext = camelContext; + } + + @Override + public Resource resolveResource(final String uri) { + ObjectHelper.notNull(uri, "Resource uri must not be null"); + + String location = uri; + String scheme = StringHelper.before(location, ":"); + if (scheme == null) { + scheme = DefaultResourceResolvers.ClasspathResolver.SCHEME; + location = DefaultResourceResolvers.ClasspathResolver.SCHEME + ":" + location; + } + + ResourceResolver rr = getResourceResolver(scheme); + if (rr == null) { + throw new IllegalArgumentException( + "Cannot find a ResourceResolver in classpath supporting the scheme: " + scheme); + } + + return rr.resolve(location); + } + + /** + * Looks up a {@link ResourceResolver} for the given scheme in the registry or fallback to a factory finder + * mechanism if none found. + * + * @param scheme the file extension for which a loader should be find. + * @return a {@link RoutesBuilderLoader} or <code>null</code> if none found. + */ + private ResourceResolver getResourceResolver(final String scheme) { + ResourceResolver answer = getCamelContext().getRegistry().lookupByNameAndType( + RESOURCE_LOADER_KEY_PREFIX + scheme, + ResourceResolver.class); + + if (answer == null) { + answer = resolvers.computeIfAbsent(scheme, this::resolveService); + } + + return answer; + } + + /** + * Looks up a {@link ResourceResolver} for the given scheme with factory finder. + * + * @param scheme the file extension for which a loader should be find. + * @return a {@link RoutesBuilderLoader} or <code>null</code> if none found. + */ + private ResourceResolver resolveService(String scheme) { + final ExtendedCamelContext ecc = getCamelContext().adapt(ExtendedCamelContext.class); + final FactoryFinder finder = ecc.getBootstrapFactoryFinder(ResourceResolver.FACTORY_PATH); + + ResourceResolver rr = ResolverHelper.resolveService(ecc, finder, scheme, ResourceResolver.class).orElse(null); + if (rr != null) { + CamelContextAware.trySetCamelContext(rr, getCamelContext()); + ServiceHelper.startService(rr); + } + + return rr; + } +} diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultResourceResolvers.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultResourceResolvers.java new file mode 100644 index 0000000..e4d298b --- /dev/null +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultResourceResolvers.java @@ -0,0 +1,281 @@ +/* + * 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.impl.engine; + +import java.io.ByteArrayInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLConnection; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.apache.camel.ExtendedCamelContext; +import org.apache.camel.spi.Resource; +import org.apache.camel.spi.annotations.ResourceResolver; +import org.apache.camel.support.CamelContextHelper; +import org.apache.camel.support.ResourceResolverSupport; +import org.apache.camel.util.FileUtil; +import org.apache.camel.util.StringHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class DefaultResourceResolvers { + private DefaultResourceResolvers() { + } + + @ResourceResolver(FileResolver.SCHEME) + public static final class FileResolver extends ResourceResolverSupport { + public static final String SCHEME = "file"; + private static final Logger LOGGER = LoggerFactory.getLogger(FileResolver.class); + + public FileResolver() { + super(SCHEME); + } + + @Override + public Resource createResource(String location) { + final String remaining = getRemaining(location); + final Path path = Paths.get(tryDecodeUri(remaining)); + + LOGGER.trace("Creating resource: {} from file system", path); + + return new Resource() { + @Override + public String getLocation() { + return location; + } + + @Override + public boolean exists() { + return Files.exists(path); + } + + @Override + public URI getURI() { + return path.toUri(); + } + + @Override + public InputStream getInputStream() throws IOException { + if (!exists()) { + throw new FileNotFoundException(path.toString() + " does not exists"); + } + if (Files.isDirectory(path)) { + throw new FileNotFoundException(path.toString() + " is a directory"); + } + + return Files.newInputStream(path); + } + + @Override + public String toString() { + return "Resource{" + + "location=" + getLocation() + + '}'; + } + }; + } + } + + @ResourceResolver(HttpResolver.SCHEME) + public static final class HttpResolver extends ResourceResolverSupport { + public static final String SCHEME = "http"; + private static final Logger LOGGER = LoggerFactory.getLogger(HttpResolver.class); + + public HttpResolver() { + super(SCHEME); + } + + @Override + public Resource createResource(String location) { + LOGGER.trace("Creating resource: {} from HTTP", location); + + return new Resource() { + @Override + public String getLocation() { + return location; + } + + @Override + public boolean exists() { + URLConnection connection = null; + + try { + connection = new URL(location).openConnection(); + + if (connection instanceof HttpURLConnection) { + return ((HttpURLConnection) connection).getResponseCode() == HttpURLConnection.HTTP_OK; + } + + return connection.getContentLengthLong() > 0; + } catch (IOException e) { + throw new IllegalArgumentException(e); + } finally { + // close the http connection to avoid + // leaking gaps in case of an exception + if (connection instanceof HttpURLConnection) { + ((HttpURLConnection) connection).disconnect(); + } + } + } + + @Override + public InputStream getInputStream() throws IOException { + URLConnection con = new URL(location).openConnection(); + con.setUseCaches(false); + + try { + return con.getInputStream(); + } catch (IOException e) { + // close the http connection to avoid + // leaking gaps in case of an exception + if (con instanceof HttpURLConnection) { + ((HttpURLConnection) con).disconnect(); + } + throw e; + } + } + + @Override + public String toString() { + return "Resource{" + + "location=" + getLocation() + + '}'; + } + }; + } + } + + @ResourceResolver(ClasspathResolver.SCHEME) + public static final class ClasspathResolver extends ResourceResolverSupport { + public static final String SCHEME = "classpath"; + private static final Logger LOGGER = LoggerFactory.getLogger(ClasspathResolver.class); + + public ClasspathResolver() { + super(SCHEME); + } + + @Override + public Resource createResource(String location) { + final String path = getPath(location); + + LOGGER.trace("Creating resource: {} from classpath", path); + + return new Resource() { + @Override + public String getLocation() { + return location; + } + + @Override + public boolean exists() { + return getURI() != null; + } + + @Override + public URI getURI() { + URL url = getCamelContext() + .adapt(ExtendedCamelContext.class) + .getClassResolver() + .loadResourceAsURL(path); + + try { + return url != null ? url.toURI() : null; + } catch (URISyntaxException e) { + throw new IllegalArgumentException(e); + } + + } + + @Override + public InputStream getInputStream() throws IOException { + return getCamelContext() + .adapt(ExtendedCamelContext.class) + .getClassResolver() + .loadResourceAsStream(path); + } + + @Override + public String toString() { + return "Resource{" + + "location=" + getLocation() + + '}'; + } + }; + } + + private String getPath(String location) { + String uri = StringHelper.after(location, "classpath:"); + uri = tryDecodeUri(uri); + uri = FileUtil.compactPath(uri, '/'); + + return uri; + } + } + + @ResourceResolver(RefResolver.SCHEME) + public static final class RefResolver extends ResourceResolverSupport { + public static final String SCHEME = "ref"; + private static final Logger LOGGER = LoggerFactory.getLogger(RefResolver.class); + + public RefResolver() { + super(SCHEME); + } + + @Override + public Resource createResource(String location) { + final String key = getRemaining(location); + final String val = CamelContextHelper.lookup(getCamelContext(), key, String.class); + + LOGGER.trace("Creating resource: {} from registry", key); + + return new Resource() { + @Override + public String getLocation() { + return location; + } + + @Override + public boolean exists() { + return val != null; + } + + @Override + public InputStream getInputStream() throws IOException { + if (!exists()) { + throw new IOException("There is no bean in the registry with name " + key + "and type String"); + } + + return new ByteArrayInputStream(val.getBytes()); + } + + @Override + public String toString() { + return "Resource{" + + "location=" + getLocation() + + '}'; + } + }; + } + } +} diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java index 2cae07b..057cd5a 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java @@ -63,6 +63,7 @@ import org.apache.camel.spi.ProcessorFactory; import org.apache.camel.spi.PropertiesComponent; import org.apache.camel.spi.ReactiveExecutor; import org.apache.camel.spi.Registry; +import org.apache.camel.spi.ResourceLoader; import org.apache.camel.spi.RestBindingJaxbDataFormatFactory; import org.apache.camel.spi.RestRegistryFactory; import org.apache.camel.spi.RouteController; @@ -454,6 +455,17 @@ public class SimpleCamelContext extends AbstractCamelContext { } @Override + protected ResourceLoader createResourceLoader() { + Optional<ResourceLoader> result = ResolverHelper.resolveService( + getCamelContextReference(), + getBootstrapFactoryFinder(), + ResourceLoader.FACTORY, + ResourceLoader.class); + + return result.orElseGet(DefaultResourceLoader::new); + } + + @Override protected ModelToXMLDumper createModelToXMLDumper() { Optional<ModelToXMLDumper> result = ResolverHelper.resolveService( getCamelContextReference(), diff --git a/core/camel-core-engine/src/generated/java/org/apache/camel/impl/ExtendedCamelContextConfigurer.java b/core/camel-core-engine/src/generated/java/org/apache/camel/impl/ExtendedCamelContextConfigurer.java index fc3b1b3..d06c43d 100644 --- a/core/camel-core-engine/src/generated/java/org/apache/camel/impl/ExtendedCamelContextConfigurer.java +++ b/core/camel-core-engine/src/generated/java/org/apache/camel/impl/ExtendedCamelContextConfigurer.java @@ -129,6 +129,8 @@ public class ExtendedCamelContextConfigurer extends org.apache.camel.support.com case "ReactiveExecutor": target.setReactiveExecutor(property(camelContext, org.apache.camel.spi.ReactiveExecutor.class, value)); return true; case "registry": case "Registry": target.setRegistry(property(camelContext, org.apache.camel.spi.Registry.class, value)); return true; + case "resourceloader": + case "ResourceLoader": target.setResourceLoader(property(camelContext, org.apache.camel.spi.ResourceLoader.class, value)); return true; case "restbindingjaxbdataformatfactory": case "RestBindingJaxbDataFormatFactory": target.setRestBindingJaxbDataFormatFactory(property(camelContext, org.apache.camel.spi.RestBindingJaxbDataFormatFactory.class, value)); return true; case "restconfiguration": @@ -300,6 +302,8 @@ public class ExtendedCamelContextConfigurer extends org.apache.camel.support.com case "ReactiveExecutor": return org.apache.camel.spi.ReactiveExecutor.class; case "registry": case "Registry": return org.apache.camel.spi.Registry.class; + case "resourceloader": + case "ResourceLoader": return org.apache.camel.spi.ResourceLoader.class; case "restbindingjaxbdataformatfactory": case "RestBindingJaxbDataFormatFactory": return org.apache.camel.spi.RestBindingJaxbDataFormatFactory.class; case "restconfiguration": @@ -472,6 +476,8 @@ public class ExtendedCamelContextConfigurer extends org.apache.camel.support.com case "ReactiveExecutor": return target.getReactiveExecutor(); case "registry": case "Registry": return target.getRegistry(); + case "resourceloader": + case "ResourceLoader": return target.getResourceLoader(); case "restbindingjaxbdataformatfactory": case "RestBindingJaxbDataFormatFactory": return target.getRestBindingJaxbDataFormatFactory(); case "restconfiguration": diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java index 5b122bd..16f4521 100644 --- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java +++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java @@ -118,6 +118,7 @@ import org.apache.camel.spi.ProcessorFactory; import org.apache.camel.spi.PropertiesComponent; import org.apache.camel.spi.ReactiveExecutor; import org.apache.camel.spi.Registry; +import org.apache.camel.spi.ResourceLoader; import org.apache.camel.spi.RestBindingJaxbDataFormatFactory; import org.apache.camel.spi.RestConfiguration; import org.apache.camel.spi.RestRegistry; @@ -1503,6 +1504,16 @@ public class LightweightCamelContext implements ExtendedCamelContext, CatalogCam } @Override + public ResourceLoader getResourceLoader() { + return getExtendedCamelContext().getResourceLoader(); + } + + @Override + public void setResourceLoader(ResourceLoader resourceLoader) { + getExtendedCamelContext().setResourceLoader(resourceLoader); + } + + @Override public void setModelToXMLDumper(ModelToXMLDumper modelToXMLDumper) { getExtendedCamelContext().setModelToXMLDumper(modelToXMLDumper); } diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java index 97dba59..afed430 100644 --- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java +++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java @@ -115,6 +115,7 @@ import org.apache.camel.spi.ProcessorFactory; import org.apache.camel.spi.PropertiesComponent; import org.apache.camel.spi.ReactiveExecutor; import org.apache.camel.spi.Registry; +import org.apache.camel.spi.ResourceLoader; import org.apache.camel.spi.RestBindingJaxbDataFormatFactory; import org.apache.camel.spi.RestConfiguration; import org.apache.camel.spi.RestRegistry; @@ -1793,6 +1794,16 @@ public class LightweightRuntimeCamelContext implements ExtendedCamelContext, Cat } @Override + public ResourceLoader getResourceLoader() { + throw new UnsupportedOperationException(); + } + + @Override + public void setResourceLoader(ResourceLoader resourceLoader) { + throw new UnsupportedOperationException(); + } + + @Override public void registerEndpointCallback(EndpointStrategy strategy) { throw new UnsupportedOperationException(); } diff --git a/core/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorEndpointClearCachedSchemaTest.java b/core/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorEndpointClearCachedSchemaTest.java index 22ee228..7739270 100644 --- a/core/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorEndpointClearCachedSchemaTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorEndpointClearCachedSchemaTest.java @@ -27,7 +27,8 @@ import org.apache.camel.ContextTestSupport; import org.apache.camel.Endpoint; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; -import org.apache.camel.impl.DefaultCamelContext; +import org.apache.camel.impl.engine.DefaultResourceLoader; +import org.apache.camel.urlhandler.pd.Handler; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -72,10 +73,9 @@ public class ValidatorEndpointClearCachedSchemaTest extends ContextTestSupport { @Override protected CamelContext createCamelContext() throws Exception { - String handlerPackageSystemProp = "java.protocol.handler.pkgs"; - String customUrlHandlerPackage = "org.apache.camel.urlhandler"; - registerSystemProperty(handlerPackageSystemProp, customUrlHandlerPackage, "|"); - return new DefaultCamelContext(); + CamelContext context = super.createCamelContext(); + context.getRegistry().bind(DefaultResourceLoader.RESOURCE_LOADER_KEY_PREFIX + "pd", new Handler()); + return context; } @Override diff --git a/core/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorWithResourceResolverRouteTest.java b/core/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorWithResourceResolverRouteTest.java index ed89826..bc52554 100644 --- a/core/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorWithResourceResolverRouteTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorWithResourceResolverRouteTest.java @@ -77,7 +77,7 @@ public class ValidatorWithResourceResolverRouteTest extends ContextTestSupport { // we have to do it here, because we need the context created first CatalogManager.getStaticManager().setIgnoreMissingProperties(true); CatalogResolver catalogResolver = new CatalogResolver(true); - URL catalogUrl = ResourceHelper.resolveMandatoryResourceAsUrl(context.getClassResolver(), + URL catalogUrl = ResourceHelper.resolveMandatoryResourceAsUrl(context, "org/apache/camel/component/validator/catalog.cat"); catalogResolver.getCatalog().parseCatalog(catalogUrl); LSResourceResolver resourceResolver = new CatalogLSResourceResolver(catalogResolver); diff --git a/core/camel-core/src/test/java/org/apache/camel/urlhandler/custom/Handler.java b/core/camel-core/src/test/java/org/apache/camel/urlhandler/custom/Handler.java index 9207b0b..4d9469f 100644 --- a/core/camel-core/src/test/java/org/apache/camel/urlhandler/custom/Handler.java +++ b/core/camel-core/src/test/java/org/apache/camel/urlhandler/custom/Handler.java @@ -19,23 +19,32 @@ package org.apache.camel.urlhandler.custom; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLStreamHandler; +import java.nio.charset.StandardCharsets; + +import org.apache.camel.spi.Resource; +import org.apache.camel.support.ResourceResolverSupport; + +public class Handler extends ResourceResolverSupport { + public Handler() { + super("custom"); + } -public class Handler extends URLStreamHandler { @Override - protected URLConnection openConnection(URL u) throws IOException { - final String echo = u.getHost(); - return new URLConnection(u) { + protected Resource createResource(String location) { + return new Resource() { + @Override + public String getLocation() { + return location; + } + @Override - public void connect() throws IOException { - connected = true; + public boolean exists() { + return true; } @Override public InputStream getInputStream() throws IOException { - return new ByteArrayInputStream(echo.getBytes()); + return new ByteArrayInputStream(getRemaining(location).getBytes(StandardCharsets.UTF_8)); } }; } diff --git a/core/camel-core/src/test/java/org/apache/camel/urlhandler/pd/Handler.java b/core/camel-core/src/test/java/org/apache/camel/urlhandler/pd/Handler.java index 573496b..f753c92 100644 --- a/core/camel-core/src/test/java/org/apache/camel/urlhandler/pd/Handler.java +++ b/core/camel-core/src/test/java/org/apache/camel/urlhandler/pd/Handler.java @@ -19,11 +19,11 @@ package org.apache.camel.urlhandler.pd; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLStreamHandler; import java.nio.charset.StandardCharsets; +import java.util.concurrent.atomic.AtomicInteger; +import org.apache.camel.spi.Resource; +import org.apache.camel.support.ResourceResolverSupport; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,81 +32,58 @@ import org.slf4j.LoggerFactory; * not fit to the XML document. In the second call a XSD fitting to the XML document is returned. Used in * org.apache.camel.component.validator.ValidatorEndpointClearCachedSchemaTest */ -public class Handler extends URLStreamHandler { - private static int counter; +public class Handler extends ResourceResolverSupport { private static final Logger LOG = LoggerFactory.getLogger(Handler.class); - private final String xsdtemplate1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + // - "<xsd:schema targetNamespace=\"http://apache.camel.org/test\" xmlns=\"http://apache.camel.org/test\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" - + // - " <xsd:complexType name=\"TestMessage\">" + // - " <xsd:sequence>" + // - " <xsd:element name=\"Content\" type=\"xsd:string\" />" + // // - // wrong - // element - // name - // will - // cause - // the - // validation - // to - // fail - " </xsd:sequence>" + // - " <xsd:attribute name=\"attr\" type=\"xsd:string\" default=\"xsd1\"/>" + // - " </xsd:complexType>" + // - " <xsd:element name=\"TestMessage\" type=\"TestMessage\" />" + // - "</xsd:schema>"; // + // wrong element name will cause the validation to fail + private static final String XSD_TEMPLATE_1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + + "<xsd:schema targetNamespace=\"http://apache.camel.org/test\" " + + " xmlns=\"http://apache.camel.org/test\" " + + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" + + " <xsd:complexType name=\"TestMessage\">" + + " <xsd:sequence>" + + " <xsd:element name=\"Content\" type=\"xsd:string\" />" + + " </xsd:sequence>" + + " <xsd:attribute name=\"attr\" type=\"xsd:string\" default=\"xsd1\"/>" + + " </xsd:complexType>" + + " <xsd:element name=\"TestMessage\" type=\"TestMessage\" />" + + "</xsd:schema>"; - private final String xsdtemplate2 = xsdtemplate1.replace("\"Content\"", "\"MessageContent\""); // correct - // element - // name - // --> - // validation - // will - // be - // correct + // correct element name, the validation will be corerct + private static final String XSD_TEMPLATE_2 = XSD_TEMPLATE_1.replace("\"Content\"", "\"MessageContent\""); - private byte[] xsd1 = xsdtemplate1.getBytes(StandardCharsets.UTF_8); - private byte[] xsd2 = xsdtemplate2.getBytes(StandardCharsets.UTF_8); + private final AtomicInteger counter; - @Override - protected URLConnection openConnection(URL u) throws IOException { - if (getCounter() == 0) { - LOG.info("resolved XSD1"); - incrementCounter(); - return new URLConnection(u) { - @Override - public void connect() throws IOException { - connected = true; - } - - @Override - public InputStream getInputStream() throws IOException { - return new ByteArrayInputStream(xsd1); - } - }; - } else { - LOG.info("resolved XSD2"); - incrementCounter(); - return new URLConnection(u) { - @Override - public void connect() throws IOException { - connected = true; - } + public Handler() { + super("pd"); - @Override - public InputStream getInputStream() throws IOException { - return new ByteArrayInputStream(xsd2); - } - }; - } + this.counter = new AtomicInteger(); } - public static synchronized void incrementCounter() { - counter++; - } + @Override + protected Resource createResource(String location) { + return new Resource() { + @Override + public String getLocation() { + return location; + } + + @Override + public boolean exists() { + return true; + } - public static synchronized int getCounter() { - return counter; + @Override + public InputStream getInputStream() throws IOException { + if (counter.getAndIncrement() == 0) { + LOG.info("resolved XSD1"); + return new ByteArrayInputStream(XSD_TEMPLATE_1.getBytes(StandardCharsets.UTF_8)); + } else { + LOG.info("resolved XSD2"); + + return new ByteArrayInputStream(XSD_TEMPLATE_2.getBytes(StandardCharsets.UTF_8)); + } + } + }; } } diff --git a/core/camel-core/src/test/java/org/apache/camel/util/ResourceHelperTest.java b/core/camel-core/src/test/java/org/apache/camel/util/ResourceHelperTest.java index 9b7351e..7668d3a 100644 --- a/core/camel-core/src/test/java/org/apache/camel/util/ResourceHelperTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/util/ResourceHelperTest.java @@ -20,7 +20,6 @@ import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.InputStream; -import java.io.InputStreamReader; import java.net.URL; import java.util.LinkedHashMap; import java.util.Map; @@ -28,14 +27,18 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.camel.CamelContext; import org.apache.camel.TestSupport; -import org.apache.camel.converter.IOConverter; import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.spi.Registry; import org.apache.camel.support.DefaultRegistry; import org.apache.camel.support.ResourceHelper; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; /** * @@ -211,7 +214,8 @@ public class ResourceHelperTest extends TestSupport { ResourceHelper.resolveMandatoryResourceAsInputStream(context, "classpath:notfound.txt"); fail("Should not find file"); } catch (FileNotFoundException e) { - assertEquals("Cannot find resource: classpath:notfound.txt in classpath for URI: classpath:notfound.txt", + assertEquals( + "Cannot find resource: classpath:notfound.txt for URI: classpath:notfound.txt", e.getMessage()); } @@ -223,8 +227,7 @@ public class ResourceHelperTest extends TestSupport { CamelContext context = new DefaultCamelContext(); context.start(); - URL url = ResourceHelper.resolveMandatoryResourceAsUrl(context.getClassResolver(), - "file:src/test/resources/log4j2.properties"); + URL url = ResourceHelper.resolveMandatoryResourceAsUrl(context, "file:src/test/resources/log4j2.properties"); assertNotNull(url); String text = context.getTypeConverter().convertTo(String.class, url); @@ -239,7 +242,7 @@ public class ResourceHelperTest extends TestSupport { CamelContext context = new DefaultCamelContext(); context.start(); - URL url = ResourceHelper.resolveMandatoryResourceAsUrl(context.getClassResolver(), "classpath:log4j2.properties"); + URL url = ResourceHelper.resolveMandatoryResourceAsUrl(context, "classpath:log4j2.properties"); assertNotNull(url); String text = context.getTypeConverter().convertTo(String.class, url); @@ -250,72 +253,6 @@ public class ResourceHelperTest extends TestSupport { } @Test - public void testLoadCustomUrlasInputStream() throws Exception { - CamelContext context = new DefaultCamelContext(); - context.start(); - - String handlerPackageSystemProp = "java.protocol.handler.pkgs"; - String customUrlHandlerPackage = "org.apache.camel.urlhandler"; - - registerSystemProperty(handlerPackageSystemProp, customUrlHandlerPackage, "|"); - - InputStream is = ResourceHelper.resolveMandatoryResourceAsInputStream(context, "custom://hello"); - assertNotNull(is); - - assertEquals("hello", IOConverter.toString(IOHelper.buffered(new InputStreamReader(is, "UTF-8")))); - - context.stop(); - } - - @Test - public void testLoadCustomUrlasInputStreamFail() throws Exception { - CamelContext context = new DefaultCamelContext(); - context.start(); - - try { - InputStream is = ResourceHelper.resolveMandatoryResourceAsInputStream(context, "custom://hello"); - assertNotNull(is); - } catch (Exception e) { - assertEquals("unknown protocol: custom", e.getMessage()); - } - - context.stop(); - } - - @Test - public void testLoadCustomUrl() throws Exception { - CamelContext context = new DefaultCamelContext(); - context.start(); - - String handlerPackageSystemProp = "java.protocol.handler.pkgs"; - String customUrlHandlerPackage = "org.apache.camel.urlhandler"; - registerSystemProperty(handlerPackageSystemProp, customUrlHandlerPackage, "|"); - - URL url = ResourceHelper.resolveResourceAsUrl(context.getClassResolver(), "custom://hello"); - assertNotNull(url); - - String text = context.getTypeConverter().convertTo(String.class, url); - assertNotNull(text); - assertTrue(text.contains("hello")); - - context.stop(); - } - - @Test - public void testLoadCustomUrlFail() throws Exception { - CamelContext context = new DefaultCamelContext(); - context.start(); - - try { - ResourceHelper.resolveResourceAsUrl(context.getClassResolver(), "custom://hello"); - } catch (Exception e) { - assertEquals("unknown protocol: custom", e.getMessage()); - } - - context.stop(); - } - - @Test public void testIsHttp() throws Exception { assertFalse(ResourceHelper.isHttpUri("direct:foo")); assertFalse(ResourceHelper.isHttpUri("")); @@ -342,8 +279,8 @@ public class ResourceHelperTest extends TestSupport { assertEquals("file:", ResourceHelper.getScheme("file:myfile.txt")); assertEquals("classpath:", ResourceHelper.getScheme("classpath:myfile.txt")); assertEquals("http:", ResourceHelper.getScheme("http:www.foo.com")); - assertEquals(null, ResourceHelper.getScheme("www.foo.com")); - assertEquals(null, ResourceHelper.getScheme("myfile.txt")); + assertNull(ResourceHelper.getScheme("www.foo.com")); + assertNull(ResourceHelper.getScheme("myfile.txt")); } @Test diff --git a/core/camel-core/src/test/java/org/apache/camel/util/ResourceLoaderTest.java b/core/camel-core/src/test/java/org/apache/camel/util/ResourceLoaderTest.java new file mode 100644 index 0000000..89c084e --- /dev/null +++ b/core/camel-core/src/test/java/org/apache/camel/util/ResourceLoaderTest.java @@ -0,0 +1,207 @@ +/* + * 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.util; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.InputStream; +import java.net.URL; +import java.util.concurrent.atomic.AtomicReference; + +import org.apache.camel.TestSupport; +import org.apache.camel.impl.DefaultCamelContext; +import org.apache.camel.spi.Resource; +import org.junit.jupiter.api.Test; + +import static org.apache.camel.util.FileUtil.copyFile; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class ResourceLoaderTest extends TestSupport { + + @Test + public void testLoadFile() throws Exception { + DefaultCamelContext context = new DefaultCamelContext(); + Resource resource = context.getResourceLoader().resolveResource("file:src/test/resources/log4j2.properties"); + + try (InputStream is = resource.getInputStream()) { + assertNotNull(is); + + String text = context.getTypeConverter().convertTo(String.class, is); + assertNotNull(text); + assertTrue(text.contains("rootLogger")); + } + } + + @Test + public void testLoadFileWithSpace() throws Exception { + createDirectory("target/data/my space"); + copyFile(new File("src/test/resources/log4j2.properties"), new File("target/data/my space/log4j2.properties")); + + DefaultCamelContext context = new DefaultCamelContext(); + Resource resource = context.getResourceLoader().resolveResource("file:target/data/my%20space/log4j2.properties"); + + try (InputStream is = resource.getInputStream()) { + assertNotNull(is); + + String text = context.getTypeConverter().convertTo(String.class, is); + assertNotNull(text); + assertTrue(text.contains("rootLogger")); + } + } + + @Test + public void testLoadClasspath() throws Exception { + DefaultCamelContext context = new DefaultCamelContext(); + Resource resource = context.getResourceLoader().resolveResource("classpath:log4j2.properties"); + + try (InputStream is = resource.getInputStream()) { + assertNotNull(is); + + String text = context.getTypeConverter().convertTo(String.class, is); + assertNotNull(text); + assertTrue(text.contains("rootLogger")); + } + } + + @Test + public void testLoadClasspathDefault() throws Exception { + DefaultCamelContext context = new DefaultCamelContext(); + Resource resource = context.getResourceLoader().resolveResource("log4j2.properties"); + + try (InputStream is = resource.getInputStream()) { + assertNotNull(is); + + String text = context.getTypeConverter().convertTo(String.class, is); + assertNotNull(text); + assertTrue(text.contains("rootLogger")); + } + } + + @Test + public void testLoadRegistry() throws Exception { + DefaultCamelContext context = new DefaultCamelContext(); + context.getRegistry().bind("myBean", "This is a log4j logging configuration file"); + + Resource resource = context.getResourceLoader().resolveResource("ref:myBean"); + + try (InputStream is = resource.getInputStream()) { + assertNotNull(is); + + String text = context.getTypeConverter().convertTo(String.class, is); + assertNotNull(text); + assertTrue(text.contains("log4j")); + } + } + + @Test + public void testLoadBeanDoubleColon() throws Exception { + DefaultCamelContext context = new DefaultCamelContext(); + context.getRegistry().bind("myBean", new AtomicReference<InputStream>(new ByteArrayInputStream("a".getBytes()))); + + Resource resource = context.getResourceLoader().resolveResource("bean:myBean::get"); + + try (InputStream is = resource.getInputStream()) { + assertNotNull(is); + + String text = context.getTypeConverter().convertTo(String.class, is); + assertNotNull(text); + assertEquals("a", text); + } + } + + @Test + public void testLoadBeanDoubleColonLong() throws Exception { + DefaultCamelContext context = new DefaultCamelContext(); + context.getRegistry().bind("my.company.MyClass", + new AtomicReference<InputStream>(new ByteArrayInputStream("a".getBytes()))); + + Resource resource = context.getResourceLoader().resolveResource("bean:my.company.MyClass::get"); + + try (InputStream is = resource.getInputStream()) { + assertNotNull(is); + + String text = context.getTypeConverter().convertTo(String.class, is); + assertNotNull(text); + assertEquals("a", text); + } + } + + @Test + public void testLoadBeanDot() throws Exception { + DefaultCamelContext context = new DefaultCamelContext(); + context.getRegistry().bind("myBean", new AtomicReference<InputStream>(new ByteArrayInputStream("a".getBytes()))); + + Resource resource = context.getResourceLoader().resolveResource("bean:myBean.get"); + + try (InputStream is = resource.getInputStream()) { + assertNotNull(is); + + String text = context.getTypeConverter().convertTo(String.class, is); + assertNotNull(text); + assertEquals("a", text); + } + } + + @Test + public void testLoadFileNotFound() throws Exception { + DefaultCamelContext context = new DefaultCamelContext(); + Resource resource = context.getResourceLoader().resolveResource("file:src/test/resources/notfound.txt"); + + assertFalse(resource.exists()); + } + + @Test + public void testLoadClasspathNotFound() throws Exception { + DefaultCamelContext context = new DefaultCamelContext(); + Resource resource = context.getResourceLoader().resolveResource("classpath:notfound.txt"); + + assertFalse(resource.exists()); + } + + @Test + public void testLoadFileAsUrl() throws Exception { + DefaultCamelContext context = new DefaultCamelContext(); + Resource resource = context.getResourceLoader().resolveResource("file:src/test/resources/log4j2.properties"); + + URL url = resource.getURI().toURL(); + assertNotNull(url); + + String text = context.getTypeConverter().convertTo(String.class, url); + assertNotNull(text); + assertTrue(text.contains("rootLogger")); + + context.stop(); + } + + @Test + public void testLoadClasspathAsUrl() throws Exception { + DefaultCamelContext context = new DefaultCamelContext(); + Resource resource = context.getResourceLoader().resolveResource("classpath:log4j2.properties"); + + URL url = resource.getURI().toURL(); + assertNotNull(url); + + String text = context.getTypeConverter().convertTo(String.class, url); + assertNotNull(text); + assertTrue(text.contains("rootLogger")); + + context.stop(); + } +} diff --git a/core/camel-support/src/main/java/org/apache/camel/support/ResourceHelper.java b/core/camel-support/src/main/java/org/apache/camel/support/ResourceHelper.java index 76a4aaa..11d549d 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/ResourceHelper.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/ResourceHelper.java @@ -18,17 +18,16 @@ package org.apache.camel.support; import java.io.ByteArrayInputStream; import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; -import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; -import java.net.URLConnection; import java.net.URLDecoder; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.LinkedHashSet; @@ -39,12 +38,12 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.camel.CamelContext; -import org.apache.camel.Exchange; -import org.apache.camel.spi.ClassResolver; +import org.apache.camel.ExtendedCamelContext; +import org.apache.camel.spi.Resource; +import org.apache.camel.spi.ResourceLoader; import org.apache.camel.util.AntPathMatcher; import org.apache.camel.util.FileUtil; import org.apache.camel.util.ObjectHelper; -import org.apache.camel.util.StringHelper; import org.apache.camel.util.URISupport; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -110,38 +109,10 @@ public final class ResourceHelper { * @throws java.io.IOException is thrown if the resource file could not be found or loaded as {@link InputStream} */ public static InputStream resolveMandatoryResourceAsInputStream(CamelContext camelContext, String uri) throws IOException { - if (uri.startsWith("ref:")) { - String ref = uri.substring(4); - String value = CamelContextHelper.mandatoryLookup(camelContext, ref, String.class); - return new ByteArrayInputStream(value.getBytes()); - } else if (uri.startsWith("bean:")) { - String bean = uri.substring(5); - Exchange dummy = new DefaultExchange(camelContext); - Object out = camelContext.resolveLanguage("bean").createExpression(bean).evaluate(dummy, Object.class); - if (dummy.getException() != null) { - IOException io = new IOException("Cannot find resource: " + uri + " from calling the bean"); - io.initCause(dummy.getException()); - throw io; - } - if (out != null) { - InputStream is = camelContext.getTypeConverter().tryConvertTo(InputStream.class, dummy, out); - if (is == null) { - String text = camelContext.getTypeConverter().tryConvertTo(String.class, dummy, out); - if (text != null) { - return new ByteArrayInputStream(text.getBytes()); - } - } else { - return is; - } - } else { - throw new IOException("Cannot find resource: " + uri + " from calling the bean"); - } - } - - InputStream is = resolveResourceAsInputStream(camelContext.getClassResolver(), uri); + InputStream is = resolveResourceAsInputStream(camelContext, uri); if (is == null) { String resolvedName = resolveUriPath(uri); - throw new FileNotFoundException("Cannot find resource: " + resolvedName + " in classpath for URI: " + uri); + throw new FileNotFoundException("Cannot find resource: " + resolvedName + " for URI: " + uri); } else { return is; } @@ -159,96 +130,25 @@ public final class ResourceHelper { * @throws java.io.IOException is thrown if error loading the resource */ public static InputStream resolveResourceAsInputStream(CamelContext camelContext, String uri) throws IOException { - if (uri.startsWith("ref:")) { - String ref = uri.substring(4); - String value = CamelContextHelper.mandatoryLookup(camelContext, ref, String.class); - return new ByteArrayInputStream(value.getBytes()); - } else if (uri.startsWith("bean:")) { - String bean = uri.substring(5); - Exchange dummy = new DefaultExchange(camelContext); - Object out = camelContext.resolveLanguage("bean").createExpression(bean).evaluate(dummy, Object.class); - if (dummy.getException() != null) { - IOException io = new IOException("Cannot find resource: " + uri + " from calling the bean"); - io.initCause(dummy.getException()); - throw io; - } - if (out != null) { - InputStream is = camelContext.getTypeConverter().tryConvertTo(InputStream.class, dummy, out); - if (is == null) { - String text = camelContext.getTypeConverter().tryConvertTo(String.class, dummy, out); - if (text != null) { - return new ByteArrayInputStream(text.getBytes()); - } - } else { - return is; - } - } else { - throw new IOException("Cannot find resource: " + uri + " from calling the bean"); - } - } - return resolveResourceAsInputStream(camelContext.getClassResolver(), uri); - } + final ExtendedCamelContext ecc = camelContext.adapt(ExtendedCamelContext.class); + final ResourceLoader loader = ecc.getResourceLoader(); + final Resource resource = loader.resolveResource(uri); - /** - * Resolves the resource. - * <p/> - * If possible recommended to use {@link #resolveMandatoryResourceAsUrl(org.apache.camel.spi.ClassResolver, String)} - * - * @param classResolver the class resolver to load the resource from the classpath - * @param uri URI of the resource - * @return the resource as an {@link InputStream}. Remember to close this stream after usage. Or - * <tt>null</tt> if not found. - * @throws java.io.IOException is thrown if error loading the resource - */ - public static InputStream resolveResourceAsInputStream(ClassResolver classResolver, String uri) throws IOException { - if (uri.startsWith("file:")) { - uri = StringHelper.after(uri, "file:"); - uri = tryDecodeUri(uri); - LOG.trace("Loading resource: {} from file system", uri); - return new FileInputStream(uri); - } else if (uri.startsWith("http:")) { - URL url = new URL(uri); - LOG.trace("Loading resource: {} from HTTP", uri); - URLConnection con = url.openConnection(); - con.setUseCaches(false); - try { - return con.getInputStream(); - } catch (IOException e) { - // close the http connection to avoid - // leaking gaps in case of an exception - if (con instanceof HttpURLConnection) { - ((HttpURLConnection) con).disconnect(); - } - throw e; - } - } else if (uri.startsWith("classpath:")) { - uri = StringHelper.after(uri, "classpath:"); - uri = tryDecodeUri(uri); - } else if (uri.contains(":")) { - LOG.trace("Loading resource: {} with UrlHandler for protocol {}", uri, uri.split(":")[0]); - URL url = new URL(uri); - URLConnection con = url.openConnection(); - return con.getInputStream(); - } - - // load from classpath by default - String resolvedName = resolveUriPath(uri); - LOG.trace("Loading resource: {} from classpath", resolvedName); - return classResolver.loadResourceAsStream(resolvedName); + return resource.getInputStream(); } /** * Resolves the mandatory resource. * - * @param classResolver the class resolver to load the resource from the classpath + * @param camelContext the camel context * @param uri uri of the resource * @return the resource as an {@link java.net.URL}. * @throws java.io.FileNotFoundException is thrown if the resource file could not be found * @throws java.net.MalformedURLException if the URI is malformed */ - public static URL resolveMandatoryResourceAsUrl(ClassResolver classResolver, String uri) + public static URL resolveMandatoryResourceAsUrl(CamelContext camelContext, String uri) throws FileNotFoundException, MalformedURLException { - URL url = resolveResourceAsUrl(classResolver, uri); + URL url = resolveResourceAsUrl(camelContext, uri); if (url == null) { String resolvedName = resolveUriPath(uri); throw new FileNotFoundException("Cannot find resource: " + resolvedName + " in classpath for URI: " + uri); @@ -260,37 +160,17 @@ public final class ResourceHelper { /** * Resolves the resource. * - * @param classResolver the class resolver to load the resource from the classpath + * @param camelContext the camel context * @param uri uri of the resource * @return the resource as an {@link java.net.URL}. Or <tt>null</tt> if not found. * @throws java.net.MalformedURLException if the URI is malformed */ - public static URL resolveResourceAsUrl(ClassResolver classResolver, String uri) throws MalformedURLException { - if (uri.startsWith("file:")) { - // check if file exists first - String name = StringHelper.after(uri, "file:"); - uri = tryDecodeUri(uri); - LOG.trace("Loading resource: {} from file system", uri); - File file = new File(name); - if (!file.exists()) { - return null; - } - return new URL(uri); - } else if (uri.startsWith("http:")) { - LOG.trace("Loading resource: {} from HTTP", uri); - return new URL(uri); - } else if (uri.startsWith("classpath:")) { - uri = StringHelper.after(uri, "classpath:"); - uri = tryDecodeUri(uri); - } else if (uri.contains(":")) { - LOG.trace("Loading resource: {} with UrlHandler for protocol {}", uri, uri.split(":")[0]); - return new URL(uri); - } + public static URL resolveResourceAsUrl(CamelContext camelContext, String uri) throws MalformedURLException { + final ExtendedCamelContext ecc = camelContext.adapt(ExtendedCamelContext.class); + final ResourceLoader loader = ecc.getResourceLoader(); + final Resource resource = loader.resolveResource(uri); - // load from classpath by default - String resolvedName = resolveUriPath(uri); - LOG.trace("Loading resource: {} from classpath", resolvedName); - return classResolver.loadResourceAsURL(resolvedName); + return resource.getURL(); } /** @@ -393,4 +273,44 @@ public final class ResourceHelper { .collect(Collectors.toCollection(LinkedHashSet::new)); } } + + /** + * Create a {@link Resource} from bytes. + * + * @param location a virtual location + * @param content the resource content + * @return a resource wrapping the given byte array + */ + public static Resource fromBytes(String location, byte[] content) { + return new Resource() { + @Override + public String getLocation() { + return location; + } + + @Override + public boolean exists() { + return true; + } + + @Override + public InputStream getInputStream() throws IOException { + return new ByteArrayInputStream(content); + } + }; + } + + /** + * Create a {@link Resource} from a {@link String}. + * </p> + * The implementation delegates to {@link #fromBytes(String, byte[])} by encoding the string as bytes with + * {@link String#getBytes(Charset)} and {@link StandardCharsets#UTF_8} as charset. + * + * @param location a virtual location + * @param content the resource content + * @return a resource wrapping the given {@link String} + */ + public static Resource fromString(String location, String content) { + return fromBytes(location, content.getBytes(StandardCharsets.UTF_8)); + } } diff --git a/core/camel-support/src/main/java/org/apache/camel/support/ResourceResolverSupport.java b/core/camel-support/src/main/java/org/apache/camel/support/ResourceResolverSupport.java new file mode 100644 index 0000000..9968641 --- /dev/null +++ b/core/camel-support/src/main/java/org/apache/camel/support/ResourceResolverSupport.java @@ -0,0 +1,83 @@ +/* + * 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.support; + +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; + +import org.apache.camel.CamelContext; +import org.apache.camel.spi.Resource; +import org.apache.camel.spi.ResourceResolver; +import org.apache.camel.support.service.ServiceSupport; +import org.apache.camel.util.StringHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Base class for {@link ResourceResolver} implementations. + */ +public abstract class ResourceResolverSupport extends ServiceSupport implements ResourceResolver { + private static final Logger LOGGER = LoggerFactory.getLogger(ResourceResolverSupport.class); + + private final String scheme; + private CamelContext camelContext; + + protected ResourceResolverSupport(String scheme) { + this.scheme = scheme; + } + + public String getSupportedScheme() { + return scheme; + } + + @Override + public CamelContext getCamelContext() { + return camelContext; + } + + @Override + public void setCamelContext(CamelContext camelContext) { + this.camelContext = camelContext; + } + + @Override + public Resource resolve(String location) { + if (!location.startsWith(getSupportedScheme() + ":")) { + throw new IllegalArgumentException("Unsupported scheme: " + location); + } + + return createResource(location); + } + + protected abstract Resource createResource(String location); + + protected String tryDecodeUri(String uri) { + try { + // try to decode as the uri may contain %20 for spaces etc + uri = URLDecoder.decode(uri, StandardCharsets.UTF_8.name()); + } catch (Exception e) { + LOGGER.trace("Error URL decoding uri using UTF-8 encoding: {}. This exception is ignored.", uri); + // ignore + } + + return uri; + } + + protected String getRemaining(String location) { + return StringHelper.after(location, getSupportedScheme() + ":"); + } +} diff --git a/dsl/camel-java-joor-dsl/src/test/java/org/apache/camel/dsl/java/joor/JavaRoutesBuilderLoaderTest.java b/dsl/camel-java-joor-dsl/src/test/java/org/apache/camel/dsl/java/joor/JavaRoutesBuilderLoaderTest.java index f14d635..20803af 100644 --- a/dsl/camel-java-joor-dsl/src/test/java/org/apache/camel/dsl/java/joor/JavaRoutesBuilderLoaderTest.java +++ b/dsl/camel-java-joor-dsl/src/test/java/org/apache/camel/dsl/java/joor/JavaRoutesBuilderLoaderTest.java @@ -44,7 +44,7 @@ public class JavaRoutesBuilderLoaderTest { }) void testLoadRoutes(String location) throws Exception { try (DefaultCamelContext context = new DefaultCamelContext()) { - Resource resource = Resource.fromClasspath(JavaRoutesBuilderLoaderTest.class, location); + Resource resource = context.getResourceLoader().resolveResource(location); Collection<RoutesBuilder> builders = context.getRoutesLoader().findRoutesBuilders(resource); assertThat(builders).hasSize(1); @@ -68,7 +68,7 @@ public class JavaRoutesBuilderLoaderTest { final String location = "/routes/MyRoutesWithNestedClass.java"; try (DefaultCamelContext context = new DefaultCamelContext()) { - Resource resource = Resource.fromClasspath(JavaRoutesBuilderLoaderTest.class, location); + Resource resource = context.getResourceLoader().resolveResource(location); Collection<RoutesBuilder> builders = context.getRoutesLoader().findRoutesBuilders(resource); assertThat(builders).hasSize(1); @@ -94,7 +94,7 @@ public class JavaRoutesBuilderLoaderTest { final String location = "/routes/MyRoutesWithRestConfiguration.java"; try (DefaultCamelContext context = new DefaultCamelContext()) { - Resource resource = Resource.fromClasspath(JavaRoutesBuilderLoaderTest.class, location); + Resource resource = context.getResourceLoader().resolveResource(location); Collection<RoutesBuilder> builders = context.getRoutesLoader().findRoutesBuilders(resource); assertThat(builders).hasSize(1); @@ -113,7 +113,7 @@ public class JavaRoutesBuilderLoaderTest { final String location = "/routes/MyRoutesWithModel.java"; try (DefaultCamelContext context = new DefaultCamelContext()) { - Resource resource = Resource.fromClasspath(JavaRoutesBuilderLoaderTest.class, location); + Resource resource = context.getResourceLoader().resolveResource(location); Collection<RoutesBuilder> builders = context.getRoutesLoader().findRoutesBuilders(resource); assertThat(builders).hasSize(1); diff --git a/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/XmlLoadRestTest.java b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/XmlLoadRestTest.java index 3d14a68..76a20c4 100644 --- a/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/XmlLoadRestTest.java +++ b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/XmlLoadRestTest.java @@ -16,11 +16,11 @@ */ package org.apache.camel.dsl.xml.io; +import org.apache.camel.ExtendedCamelContext; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.component.rest.DummyRestConsumerFactory; import org.apache.camel.impl.DefaultCamelContext; -import org.apache.camel.model.LoadRouteFromXmlTest; import org.apache.camel.spi.Resource; import org.junit.jupiter.api.Test; @@ -57,7 +57,10 @@ public class XmlLoadRestTest { foo.assertIsSatisfied(); // load rest from XML and add them to the existing camel context - Resource resource = Resource.fromClasspath(LoadRouteFromXmlTest.class, "barRest.xml"); + ExtendedCamelContext ecc = context.adapt(ExtendedCamelContext.class); + Resource resource = ecc.getResourceLoader().resolveResource( + "/org/apache/camel/dsl/xml/io/barRest.xml"); + context.getRoutesLoader().loadRoutes(resource); assertEquals(2, context.getRoutes().size()); diff --git a/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/XmlLoadTest.java b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/XmlLoadTest.java index 2819445..a147e47 100644 --- a/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/XmlLoadTest.java +++ b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/XmlLoadTest.java @@ -20,7 +20,6 @@ import org.apache.camel.ExtendedCamelContext; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.impl.DefaultCamelContext; -import org.apache.camel.model.LoadRouteFromXmlTest; import org.apache.camel.spi.Resource; import org.junit.jupiter.api.Test; @@ -54,7 +53,8 @@ public class XmlLoadTest { // START SNIPPET: e1 // load route from XML and add them to the existing camel context ExtendedCamelContext ecc = context.adapt(ExtendedCamelContext.class); - Resource resource = Resource.fromClasspath(LoadRouteFromXmlTest.class, "barRoute.xml"); + Resource resource = ecc.getResourceLoader().resolveResource( + "/org/apache/camel/dsl/xml/io/barRoute.xml"); ecc.getRoutesLoader().loadRoutes(resource); diff --git a/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoaderTest.java b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoaderTest.java index c1fe3e7..ef73bee 100644 --- a/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoaderTest.java +++ b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoaderTest.java @@ -19,6 +19,7 @@ package org.apache.camel.dsl.xml.io; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.spi.Resource; +import org.apache.camel.support.ResourceHelper; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -38,7 +39,7 @@ public class XmlRoutesBuilderLoaderTest { + " </route>" + "</routes>"; - Resource resource = Resource.fromString("in-memory.xml", content); + Resource resource = ResourceHelper.fromString("in-memory.xml", content); RouteBuilder builder = (RouteBuilder) new XmlRoutesBuilderLoader().loadRoutesBuilder(resource); builder.setContext(new DefaultCamelContext()); builder.configure(); @@ -57,7 +58,7 @@ public class XmlRoutesBuilderLoaderTest { + " </rest>" + "</rests>"; - Resource resource = Resource.fromString("in-memory.xml", content); + Resource resource = ResourceHelper.fromString("in-memory.xml", content); RouteBuilder builder = (RouteBuilder) new XmlRoutesBuilderLoader().loadRoutesBuilder(resource); builder.setContext(new DefaultCamelContext()); builder.configure(); @@ -79,7 +80,7 @@ public class XmlRoutesBuilderLoaderTest { + " </routeTemplate>" + "</routeTemplates>"; - Resource resource = Resource.fromString("in-memory.xml", content); + Resource resource = ResourceHelper.fromString("in-memory.xml", content); RouteBuilder builder = (RouteBuilder) new XmlRoutesBuilderLoader().loadRoutesBuilder(resource); builder.setContext(new DefaultCamelContext()); builder.configure(); diff --git a/dsl/camel-xml-jaxb-dsl/src/test/java/org/apache/camel/dsl/xml/jaxb/JaxbXmlLoadRestTest.java b/dsl/camel-xml-jaxb-dsl/src/test/java/org/apache/camel/dsl/xml/jaxb/JaxbXmlLoadRestTest.java index c4476e9..1d00d22 100644 --- a/dsl/camel-xml-jaxb-dsl/src/test/java/org/apache/camel/dsl/xml/jaxb/JaxbXmlLoadRestTest.java +++ b/dsl/camel-xml-jaxb-dsl/src/test/java/org/apache/camel/dsl/xml/jaxb/JaxbXmlLoadRestTest.java @@ -16,11 +16,11 @@ */ package org.apache.camel.dsl.xml.jaxb; +import org.apache.camel.ExtendedCamelContext; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.component.rest.DummyRestConsumerFactory; import org.apache.camel.impl.DefaultCamelContext; -import org.apache.camel.model.LoadRouteFromXmlTest; import org.apache.camel.spi.Resource; import org.junit.jupiter.api.Test; @@ -57,7 +57,10 @@ public class JaxbXmlLoadRestTest { foo.assertIsSatisfied(); // load rest from XML and add them to the existing camel context - Resource resource = Resource.fromClasspath(LoadRouteFromXmlTest.class, "barRest.xml"); + ExtendedCamelContext ecc = context.adapt(ExtendedCamelContext.class); + Resource resource = ecc.getResourceLoader().resolveResource( + "/org/apache/camel/dsl/xml/jaxb/barRest.xml"); + context.getRoutesLoader().loadRoutes(resource); assertEquals(2, context.getRoutes().size()); diff --git a/dsl/camel-xml-jaxb-dsl/src/test/java/org/apache/camel/dsl/xml/jaxb/JaxbXmlLoadTest.java b/dsl/camel-xml-jaxb-dsl/src/test/java/org/apache/camel/dsl/xml/jaxb/JaxbXmlLoadTest.java index bc02eee..dbe7210 100644 --- a/dsl/camel-xml-jaxb-dsl/src/test/java/org/apache/camel/dsl/xml/jaxb/JaxbXmlLoadTest.java +++ b/dsl/camel-xml-jaxb-dsl/src/test/java/org/apache/camel/dsl/xml/jaxb/JaxbXmlLoadTest.java @@ -20,7 +20,6 @@ import org.apache.camel.ExtendedCamelContext; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.impl.DefaultCamelContext; -import org.apache.camel.model.LoadRouteFromXmlTest; import org.apache.camel.spi.Resource; import org.junit.jupiter.api.Test; @@ -54,7 +53,8 @@ public class JaxbXmlLoadTest { // START SNIPPET: e1 // load route from XML and add them to the existing camel context ExtendedCamelContext ecc = context.adapt(ExtendedCamelContext.class); - Resource resource = Resource.fromClasspath(LoadRouteFromXmlTest.class, "barRoute.xml"); + Resource resource = ecc.getResourceLoader().resolveResource( + "/org/apache/camel/dsl/xml/jaxb/barRoute.xml"); ecc.getRoutesLoader().loadRoutes(resource); diff --git a/dsl/camel-xml-jaxb-dsl/src/test/java/org/apache/camel/dsl/xml/jaxb/JaxbXmlRoutesBuilderLoaderTest.java b/dsl/camel-xml-jaxb-dsl/src/test/java/org/apache/camel/dsl/xml/jaxb/JaxbXmlRoutesBuilderLoaderTest.java index 6804f53..7b7b4c4 100644 --- a/dsl/camel-xml-jaxb-dsl/src/test/java/org/apache/camel/dsl/xml/jaxb/JaxbXmlRoutesBuilderLoaderTest.java +++ b/dsl/camel-xml-jaxb-dsl/src/test/java/org/apache/camel/dsl/xml/jaxb/JaxbXmlRoutesBuilderLoaderTest.java @@ -19,6 +19,7 @@ package org.apache.camel.dsl.xml.jaxb; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.spi.Resource; +import org.apache.camel.support.ResourceHelper; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -38,7 +39,7 @@ public class JaxbXmlRoutesBuilderLoaderTest { + " </route>" + "</routes>"; - Resource resource = Resource.fromString("in-memory.xml", content); + Resource resource = ResourceHelper.fromString("in-memory.xml", content); JaxbXmlRoutesBuilderLoader loader = new JaxbXmlRoutesBuilderLoader(); loader.setCamelContext(new DefaultCamelContext()); @@ -61,7 +62,7 @@ public class JaxbXmlRoutesBuilderLoaderTest { + " </rest>" + "</rests>"; - Resource resource = Resource.fromString("in-memory.xml", content); + Resource resource = ResourceHelper.fromString("in-memory.xml", content); JaxbXmlRoutesBuilderLoader loader = new JaxbXmlRoutesBuilderLoader(); loader.setCamelContext(new DefaultCamelContext()); @@ -87,7 +88,7 @@ public class JaxbXmlRoutesBuilderLoaderTest { + " </routeTemplate>" + "</routeTemplates>"; - Resource resource = Resource.fromString("in-memory.xml", content); + Resource resource = ResourceHelper.fromString("in-memory.xml", content); JaxbXmlRoutesBuilderLoader loader = new JaxbXmlRoutesBuilderLoader(); loader.setCamelContext(new DefaultCamelContext()); diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/support/YamlTestSupport.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/support/YamlTestSupport.groovy index f982c17..5427bc7 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/support/YamlTestSupport.groovy +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/support/YamlTestSupport.groovy @@ -27,6 +27,7 @@ import org.apache.camel.component.mock.MockEndpoint import org.apache.camel.impl.DefaultCamelContext import org.apache.camel.spi.HasCamelContext import org.apache.camel.spi.Resource +import org.apache.camel.support.ResourceHelper import spock.lang.AutoCleanup import spock.lang.Specification @@ -62,7 +63,7 @@ class YamlTestSupport extends Specification implements HasCamelContext { loadRoutes( resources.collect { - it -> Resource.fromString("route-${index++}.yaml", it.stripIndent()) + it -> ResourceHelper.fromString("route-${index++}.yaml", it.stripIndent()) } ) } @@ -89,7 +90,7 @@ class YamlTestSupport extends Specification implements HasCamelContext { } static Resource asResource(String location, String content) { - return Resource.fromString( + return ResourceHelper.fromString( location.endsWith('.yaml') ? location : location + '.yaml', content.stripIndent() ) diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/SpiGeneratorMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/SpiGeneratorMojo.java index db785ca..3e23588 100644 --- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/SpiGeneratorMojo.java +++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/SpiGeneratorMojo.java @@ -127,8 +127,11 @@ public class SpiGeneratorMojo extends AbstractGeneratorMojo { } DotName sfaName = sfa.target().asClass().name(); for (AnnotationInstance annotation : index.getAnnotations(sfaName)) { - if (annotation.target().kind() != Kind.CLASS - || annotation.target().asClass().nestingType() != NestingType.TOP_LEVEL) { + if (annotation.target().kind() != Kind.CLASS) { + continue; + } + if (annotation.target().asClass().nestingType() != NestingType.TOP_LEVEL + && annotation.target().asClass().nestingType() != NestingType.INNER) { continue; } String className = annotation.target().asClass().name().toString(); diff --git a/core/camel-core/src/test/java/org/apache/camel/urlhandler/custom/Handler.java b/tooling/spi-annotations/src/main/java/org/apache/camel/spi/annotations/ResourceResolver.java similarity index 51% copy from core/camel-core/src/test/java/org/apache/camel/urlhandler/custom/Handler.java copy to tooling/spi-annotations/src/main/java/org/apache/camel/spi/annotations/ResourceResolver.java index 9207b0b..0ea471c 100644 --- a/core/camel-core/src/test/java/org/apache/camel/urlhandler/custom/Handler.java +++ b/tooling/spi-annotations/src/main/java/org/apache/camel/spi/annotations/ResourceResolver.java @@ -14,29 +14,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.urlhandler.custom; +package org.apache.camel.spi.annotations; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLStreamHandler; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; -public class Handler extends URLStreamHandler { - @Override - protected URLConnection openConnection(URL u) throws IOException { - final String echo = u.getHost(); - return new URLConnection(u) { - @Override - public void connect() throws IOException { - connected = true; - } +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Target({ ElementType.TYPE }) +@ServiceFactory("resource-resolver") +public @interface ResourceResolver { + + String value(); - @Override - public InputStream getInputStream() throws IOException { - return new ByteArrayInputStream(echo.getBytes()); - } - }; - } }