You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2018/12/19 11:46:14 UTC

[camel] branch camel-2.x updated: CAMEL-13016: camel-jetty - If multiple bundles uses the same context-path (pathspec) then Jetty should fail

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch camel-2.x
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/camel-2.x by this push:
     new 78730b9  CAMEL-13016: camel-jetty - If multiple bundles uses the same context-path (pathspec) then Jetty should fail
78730b9 is described below

commit 78730b9f22b21e066538c448e7fdfa5bee4835f9
Author: Claus Ibsen <cl...@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 834cb63..87682df 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
@@ -183,6 +183,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 ac57892..dfe3071 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
@@ -148,12 +148,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;
@@ -316,6 +318,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.
      */
@@ -339,16 +369,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 3eb9595..ac2a460 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 fe63e28..a10623b 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
@@ -35,6 +35,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");
 
@@ -42,7 +43,6 @@ public class MultiPartFormTest extends BaseJettyTest {
                         new FilePart(file.getName(), file)};
 
         return new MultipartRequestEntity(parts, new HttpMethodParams());
-
     }
 
     @Test