This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch camel-2.21.x in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-2.21.x by this push: new ad1200f CAMEL-13016: camel-jetty - If multiple bundles uses the same context-path (pathspec) then Jetty should fail ad1200f is described below commit ad1200fcc8f6e2c16309f870450a574b5d1c4517 Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Wed Dec 19 12:42:06 2018 +0100 CAMEL-13016: camel-jetty - If multiple bundles uses the same context-path (pathspec) then Jetty should fail --- .../camel/http/common/HttpCommonComponent.java | 10 ++++++ .../camel/http/common/HttpCommonEndpoint.java | 4 +++ .../org/apache/camel/http/common/HttpConsumer.java | 14 ++++++-- .../camel/component/jetty/JettyHttpComponent.java | 37 ++++++++++++++++++-- .../camel/component/jetty/JettyHttpConsumer.java | 39 ++++++++++++++++++++++ .../camel/component/jetty/JettyHttpEndpoint.java | 2 +- .../component/jetty/JettySessionSupportTest.java | 2 ++ .../camel/component/jetty/MultiPartFormTest.java | 2 +- 8 files changed, 103 insertions(+), 7 deletions(-) diff --git a/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpCommonComponent.java b/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpCommonComponent.java index c5036ee..5f875a6 100644 --- a/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpCommonComponent.java +++ b/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpCommonComponent.java @@ -88,6 +88,16 @@ public abstract class HttpCommonComponent extends HeaderFilterStrategyComponent public void disconnect(HttpConsumer consumer) throws Exception { } + /** + * Checks whether the consumer is possible to connect to the endoint. + * + * @param consumer the consumer + * @throws Exception can be thrown + */ + public boolean canConnect(HttpConsumer consumer) throws Exception { + return true; + } + @Override protected boolean useIntrospectionOnEndpoint() { return false; diff --git a/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpCommonEndpoint.java b/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpCommonEndpoint.java index 58deced..ca1dae9 100644 --- a/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpCommonEndpoint.java +++ b/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpCommonEndpoint.java @@ -179,6 +179,10 @@ public abstract class HttpCommonEndpoint extends DefaultEndpoint implements Head component.disconnect(consumer); } + public boolean canConnect(HttpConsumer consumer) throws Exception { + return component.canConnect(consumer); + } + @Override public HttpCommonComponent getComponent() { return (HttpCommonComponent) super.getComponent(); diff --git a/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpConsumer.java b/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpConsumer.java index 60907e1..744a25f 100644 --- a/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpConsumer.java +++ b/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpConsumer.java @@ -21,7 +21,9 @@ import org.apache.camel.Suspendable; import org.apache.camel.impl.DefaultConsumer; public class HttpConsumer extends DefaultConsumer implements Suspendable { + protected volatile boolean canConnected; private volatile boolean suspended; + private boolean traceEnabled; private boolean optionsEnabled; @@ -51,14 +53,20 @@ public class HttpConsumer extends DefaultConsumer implements Suspendable { @Override protected void doStart() throws Exception { super.doStart(); - getEndpoint().connect(this); - suspended = false; + if (getEndpoint().canConnect(this)) { + canConnected = true; + getEndpoint().connect(this); + suspended = false; + } } @Override protected void doStop() throws Exception { suspended = false; - getEndpoint().disconnect(this); + if (canConnected) { + canConnected = false; + getEndpoint().disconnect(this); + } super.doStop(); } diff --git a/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java b/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java index 4ae6252..ef1917f 100644 --- a/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java +++ b/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java @@ -146,12 +146,14 @@ public abstract class JettyHttpComponent extends HttpCommonComponent implements } class ConnectorRef { + CamelContext camelContext; Server server; Connector connector; CamelServlet servlet; int refCount; - ConnectorRef(Server server, Connector connector, CamelServlet servlet) { + ConnectorRef(CamelContext camelContext, Server server, Connector connector, CamelServlet servlet) { + this.camelContext = camelContext; this.server = server; this.connector = connector; this.servlet = servlet; @@ -314,6 +316,34 @@ public abstract class JettyHttpComponent extends HttpCommonComponent implements protected abstract JettyHttpEndpoint createEndpoint(URI endpointUri, URI httpUri) throws URISyntaxException; + @Override + public boolean canConnect(HttpConsumer consumer) throws Exception { + // Make sure that there is a connector for the requested endpoint. + JettyHttpEndpoint endpoint = (JettyHttpEndpoint)consumer.getEndpoint(); + String connectorKey = getConnectorKey(endpoint); + + synchronized (CONNECTORS) { + ConnectorRef connectorRef = CONNECTORS.get(connectorKey); + + // check if there are already another consumer on the same context-path and if so fail + if (connectorRef != null) { + for (Map.Entry<String, HttpConsumer> entry : connectorRef.servlet.getConsumers().entrySet()) { + String path = entry.getValue().getPath(); + CamelContext camelContext = entry.getValue().getEndpoint().getCamelContext(); + if (consumer.getPath().equals(path)) { + // its allowed if they are from the same camel context + boolean sameContext = consumer.getEndpoint().getCamelContext() == camelContext; + if (!sameContext) { + return false; + } + } + } + } + } + + return true; + } + /** * Connects the URL specified on the endpoint to the specified processor. */ @@ -337,16 +367,19 @@ public abstract class JettyHttpComponent extends HttpCommonComponent implements } server.addConnector(connector); - connectorRef = new ConnectorRef(server, connector, createServletForConnector(server, connector, endpoint.getHandlers(), endpoint)); + connectorRef = new ConnectorRef(getCamelContext(), server, connector, createServletForConnector(server, connector, endpoint.getHandlers(), endpoint)); // must enable session before we start if (endpoint.isSessionSupport()) { enableSessionSupport(connectorRef.server, connectorKey); } connectorRef.server.start(); + LOG.debug("Adding connector key: {} -> {}", connectorKey, connectorRef); CONNECTORS.put(connectorKey, connectorRef); } else { + LOG.debug("Using existing connector key: {} -> {}", connectorKey, connectorRef); + // check if there are any new handlers, and if so then we need to re-start the server if (endpoint.getHandlers() != null && !endpoint.getHandlers().isEmpty()) { List<Handler> existingHandlers = new ArrayList<>(); diff --git a/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpConsumer.java b/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpConsumer.java new file mode 100644 index 0000000..b104de4 --- /dev/null +++ b/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpConsumer.java @@ -0,0 +1,39 @@ +/** + * 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.component.jetty; + +import org.apache.camel.Processor; +import org.apache.camel.http.common.HttpCommonEndpoint; +import org.apache.camel.http.common.HttpConsumer; + +public class JettyHttpConsumer extends HttpConsumer { + + public JettyHttpConsumer(HttpCommonEndpoint endpoint, Processor processor) { + super(endpoint, processor); + } + + @Override + protected void doStart() throws Exception { + super.doStart(); + if (!canConnected) { + // if we cannot connect then its due to clash on context-path when using Jetty + String msg = "Cannot bind this Camel Jetty consumer to the JettyServer connector as there is already an existing Camel Jetty consumer using the same context-path: " + getPath(); + throw new IllegalStateException(msg); + } + } + +} diff --git a/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpEndpoint.java b/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpEndpoint.java index dc7ea51..c0f8bd7 100644 --- a/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpEndpoint.java +++ b/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpEndpoint.java @@ -186,7 +186,7 @@ public abstract class JettyHttpEndpoint extends HttpCommonEndpoint { @Override public Consumer createConsumer(Processor processor) throws Exception { - HttpConsumer answer = new HttpConsumer(this, processor); + JettyHttpConsumer answer = new JettyHttpConsumer(this, processor); configureConsumer(answer); return answer; } diff --git a/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/JettySessionSupportTest.java b/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/JettySessionSupportTest.java index 0af49a0..59d7036 100644 --- a/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/JettySessionSupportTest.java +++ b/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/JettySessionSupportTest.java @@ -44,6 +44,8 @@ public class JettySessionSupportTest extends BaseJettyTest { fail("Should have thrown an exception"); } catch (IllegalStateException e) { assertEquals("Server has already been started. Cannot enabled sessionSupport on http:localhost:" + getPort(), e.getMessage()); + } finally { + context.stop(); } } diff --git a/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/MultiPartFormTest.java b/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/MultiPartFormTest.java index 715207d..ffc2dc9 100644 --- a/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/MultiPartFormTest.java +++ b/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/MultiPartFormTest.java @@ -34,6 +34,7 @@ import org.apache.commons.httpclient.params.HttpMethodParams; import org.junit.Test; public class MultiPartFormTest extends BaseJettyTest { + private RequestEntity createMultipartRequestEntity() throws Exception { File file = new File("src/main/resources/META-INF/NOTICE.txt"); @@ -41,7 +42,6 @@ public class MultiPartFormTest extends BaseJettyTest { new FilePart(file.getName(), file)}; return new MultipartRequestEntity(parts, new HttpMethodParams()); - } @Test