http://git-wip-us.apache.org/repos/asf/camel/blob/db88eeda/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/RestNettyHttpBinding.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/RestNettyHttpBinding.java
 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/RestNettyHttpBinding.java
new file mode 100644
index 0000000..597b6d5
--- /dev/null
+++ 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/RestNettyHttpBinding.java
@@ -0,0 +1,92 @@
+/**
+ * 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.netty4.http;
+
+import java.net.URI;
+import java.util.Map;
+
+import io.netty.handler.codec.http.FullHttpRequest;
+import org.apache.camel.Exchange;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.spi.HeaderFilterStrategy;
+
+
+/**
+ * A {@link org.apache.camel.component.netty.http.NettyHttpBinding} that 
supports the Rest DSL.
+ */
+public class RestNettyHttpBinding extends DefaultNettyHttpBinding {
+
+    public RestNettyHttpBinding() {
+    }
+
+    public RestNettyHttpBinding(HeaderFilterStrategy headerFilterStrategy) {
+        super(headerFilterStrategy);
+    }
+
+    public RestNettyHttpBinding copy() {
+        try {
+            return (RestNettyHttpBinding)this.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new RuntimeCamelException(e);
+        }
+    }
+
+    @Override
+    public void populateCamelHeaders(FullHttpRequest request, Map<String, 
Object> headers, Exchange exchange, NettyHttpConfiguration configuration) 
throws Exception {
+        super.populateCamelHeaders(request, headers, exchange, configuration);
+
+        String path = request.getUri();
+        if (path == null) {
+            return;
+        }
+
+        // skip the scheme/host/port etc, as we only want the context-path
+        URI uri = new URI(path);
+        path = uri.getPath();
+
+        // in the endpoint the user may have defined rest {} placeholders
+        // so we need to map those placeholders with data from the incoming 
request context path
+
+        String consumerPath = configuration.getPath();
+
+        if (useRestMatching(consumerPath)) {
+
+            // split using single char / is optimized in the jdk
+            String[] paths = path.split("/");
+            String[] consumerPaths = consumerPath.split("/");
+
+            for (int i = 0; i < consumerPaths.length; i++) {
+                if (paths.length < i) {
+                    break;
+                }
+                String p1 = consumerPaths[i];
+                if (p1.startsWith("{") && p1.endsWith("}")) {
+                    String key = p1.substring(1, p1.length() - 1);
+                    String value = paths[i];
+                    if (value != null) {
+                        NettyHttpHelper.appendHeader(headers, key, value);
+                    }
+                }
+            }
+        }
+    }
+
+    private boolean useRestMatching(String path) {
+        // only need to do rest matching if using { } placeholders
+        return path.indexOf('{') > -1;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/db88eeda/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/SecurityAuthenticator.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/SecurityAuthenticator.java
 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/SecurityAuthenticator.java
new file mode 100644
index 0000000..8d99f11
--- /dev/null
+++ 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/SecurityAuthenticator.java
@@ -0,0 +1,76 @@
+/**
+ * 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.netty4.http;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginException;
+
+/**
+ * A {@link SecurityAuthenticator} allows to plugin custom authenticators,
+ * such as JAAS based or custom implementations.
+ */
+public interface SecurityAuthenticator {
+
+    /**
+     * Sets the name of the realm to use.
+     */
+    void setName(String name);
+
+    /**
+     * Gets the name of the realm.
+     */
+    String getName();
+
+    /**
+     * Sets the role class names (separated by comma)
+     * <p/>
+     * By default if no explicit role class names has been configured, then 
this implementation
+     * will assume the {@link Subject} {@link java.security.Principal}s is a 
role if the classname
+     * contains the word <tt>role</tt> (lower cased).
+     *
+     * @param names a list of FQN class names for role {@link 
java.security.Principal} implementations.
+     */
+    void setRoleClassNames(String names);
+
+    /**
+     * Attempts to login the {@link java.security.Principal} on this realm.
+     * <p/>
+     * The login is a success if no Exception is thrown, and a {@link Subject} 
is returned.
+     *
+     * @param principal       the principal
+     * @return the subject for the logged in principal, must <b>not</b> be 
<tt>null</tt>
+     * @throws LoginException is thrown if error logging in the {@link 
java.security.Principal}
+     */
+    Subject login(HttpPrincipal principal) throws LoginException;
+
+    /**
+     * Attempt to logout the subject.
+     *
+     * @param subject  subject to logout
+     * @throws LoginException is thrown if error logging out subject
+     */
+    void logout(Subject subject) throws LoginException;
+
+    /**
+     * Gets the user roles from the given {@link Subject}
+     *
+     * @param subject the subject
+     * @return <tt>null</tt> if no roles, otherwise a String with roles 
separated by comma.
+     */
+    String getUserRoles(Subject subject);
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/db88eeda/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/SecurityAuthenticatorSupport.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/SecurityAuthenticatorSupport.java
 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/SecurityAuthenticatorSupport.java
new file mode 100644
index 0000000..f4622b4
--- /dev/null
+++ 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/SecurityAuthenticatorSupport.java
@@ -0,0 +1,127 @@
+/**
+ * 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.netty4.http;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.Locale;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A base class for {@link SecurityAuthenticator}.
+ */
+public abstract class SecurityAuthenticatorSupport implements 
SecurityAuthenticator {
+
+    private String name;
+    private String roleClassNames;
+
+    public SecurityAuthenticatorSupport() {
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setRoleClassNames(String roleClassNames) {
+        this.roleClassNames = roleClassNames;
+    }
+
+    /**
+     * Is the given principal a role class?
+     *
+     * @param principal the principal
+     * @return <tt>true</tt> if role class, <tt>false</tt> if not
+     */
+    protected boolean isRoleClass(Principal principal) {
+        if (roleClassNames == null) {
+            // by default assume its a role when the classname has role in its 
name
+            return 
principal.getClass().getName().toLowerCase(Locale.US).contains("role");
+        }
+
+        // check each role class name if they match the principal class name
+        Iterator<Object> it = ObjectHelper.createIterator(roleClassNames);
+        while (it.hasNext()) {
+            String name = it.next().toString().trim();
+            if (principal.getClass().getName().equals(name)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String getUserRoles(Subject subject) {
+        StringBuilder sb = new StringBuilder();
+        for (Principal p : subject.getPrincipals()) {
+            if (isRoleClass(p)) {
+                if (sb.length() > 0) {
+                    sb.append(",");
+                }
+                sb.append(p.getName());
+            }
+        }
+        if (sb.length() > 0) {
+            return sb.toString();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * {@link javax.security.auth.callback.CallbackHandler} that provides the 
username and password.
+     */
+    public static final class HttpPrincipalCallbackHandler implements 
CallbackHandler {
+
+        private static final Logger LOG = 
LoggerFactory.getLogger(HttpPrincipalCallbackHandler.class);
+
+        private final HttpPrincipal principal;
+
+        public HttpPrincipalCallbackHandler(HttpPrincipal principal) {
+            this.principal = principal;
+        }
+
+        @Override
+        public void handle(Callback[] callbacks) throws IOException, 
UnsupportedCallbackException {
+            for (Callback callback : callbacks) {
+                LOG.trace("Callback {}", callback);
+                if (callback instanceof PasswordCallback) {
+                    PasswordCallback pc = (PasswordCallback) callback;
+                    LOG.trace("Setting password on callback {}", pc);
+                    pc.setPassword(principal.getPassword().toCharArray());
+                } else if (callback instanceof NameCallback) {
+                    NameCallback nc = (NameCallback) callback;
+                    LOG.trace("Setting username on callback {}", nc);
+                    nc.setName(principal.getName());
+                }
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/db88eeda/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/SecurityConstraint.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/SecurityConstraint.java
 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/SecurityConstraint.java
new file mode 100644
index 0000000..8d56502
--- /dev/null
+++ 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/SecurityConstraint.java
@@ -0,0 +1,31 @@
+/**
+ * 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.netty4.http;
+
+public interface SecurityConstraint {
+
+    /**
+     * Performs a security restricted check for the given web resource.
+     * <p/>
+     * The returned value indicates which roles the user must be in to access 
the restricted resource.
+     *
+     * @param url   the web resource
+     * @return <tt>null</tt> if not restricted, otherwise <tt>*</tt> 
(wildcard) matches any roles, otherwise a comma separated String with roles
+     */
+    String restricted(String url);
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/db88eeda/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/SecurityConstraintMapping.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/SecurityConstraintMapping.java
 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/SecurityConstraintMapping.java
new file mode 100644
index 0000000..78cbac3
--- /dev/null
+++ 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/SecurityConstraintMapping.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.component.netty4.http;
+
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.camel.util.EndpointHelper;
+
+/**
+ * A default {@link SecurityConstraint} which can be used to define a set of 
mappings to
+ * as constraints.
+ * <p/>
+ * This constraint will match as <tt>true</tt> if no inclusions has been 
defined.
+ * First all the inclusions is check for matching. If a inclusion matches,
+ * then the exclusion is checked, and if any of them matches, then the 
exclusion
+ * will override the match and force returning <tt>false</tt>.
+ * <p/>
+ * Wildcards and regular expressions is supported as this implementation uses
+ * {@link EndpointHelper#matchPattern(String, String)} method for matching.
+ * <p/>
+ * This restricted constraint allows you to setup context path rules that will 
restrict
+ * access to paths, and then override and have exclusions that may allow 
access to
+ * public paths.
+ */
+public class SecurityConstraintMapping implements SecurityConstraint {
+
+    // url -> roles
+    private Map<String, String> inclusions;
+    // url
+    private Set<String> exclusions;
+
+    @Override
+    public String restricted(String url) {
+        // check excluded first
+        if (excludedUrl(url)) {
+            return null;
+        }
+
+        // is the url restricted?
+        String constraint = includedUrl(url);
+        if (constraint == null) {
+            return null;
+        }
+
+        // is there any roles for the restricted url?
+        String roles = inclusions != null ? inclusions.get(constraint) : null;
+        if (roles == null) {
+            // use wildcard to indicate any role is accepted
+            return "*";
+        } else {
+            return roles;
+        }
+    }
+
+    private String includedUrl(String url) {
+        String candidate = null;
+        if (inclusions != null && !inclusions.isEmpty()) {
+            for (String constraint : inclusions.keySet()) {
+                if (EndpointHelper.matchPattern(url, constraint)) {
+                    if (candidate == null) {
+                        candidate = constraint;
+                    } else if (constraint.length() > candidate.length()) {
+                        // we want the constraint that has the longest 
context-path matching as its
+                        // the most explicit for the target url
+                        candidate = constraint;
+                    }
+                }
+            }
+            return candidate;
+        }
+
+        // by default if no included has been configured then everything is 
restricted
+        return "*";
+    }
+
+    private boolean excludedUrl(String url) {
+        if (exclusions != null && !exclusions.isEmpty()) {
+            for (String constraint : exclusions) {
+                if (EndpointHelper.matchPattern(url, constraint)) {
+                    // force not matches if this was an exclusion
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    public void addInclusion(String constraint) {
+        if (inclusions == null) {
+            inclusions = new java.util.LinkedHashMap<String, String>();
+        }
+        inclusions.put(constraint, null);
+    }
+
+    public void addInclusion(String constraint, String roles) {
+        if (inclusions == null) {
+            inclusions = new java.util.LinkedHashMap<String, String>();
+        }
+        inclusions.put(constraint, roles);
+    }
+
+    public void addExclusion(String constraint) {
+        if (exclusions == null) {
+            exclusions = new LinkedHashSet<String>();
+        }
+        exclusions.add(constraint);
+    }
+
+    public void setInclusions(Map<String, String> inclusions) {
+        this.inclusions = inclusions;
+    }
+
+    public void setExclusions(Set<String> exclusions) {
+        this.exclusions = exclusions;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/db88eeda/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpClientChannelHandler.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpClientChannelHandler.java
 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpClientChannelHandler.java
new file mode 100644
index 0000000..f2bc20c
--- /dev/null
+++ 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpClientChannelHandler.java
@@ -0,0 +1,46 @@
+/**
+ * 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.netty4.http.handlers;
+
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.http.FullHttpResponse;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.component.netty4.handlers.ClientChannelHandler;
+import org.apache.camel.component.netty4.http.NettyHttpProducer;
+
+/**
+ * Netty HTTP {@link 
org.apache.camel.component.netty.handlers.ClientChannelHandler} that handles 
the response combing
+ * back from the HTTP server, called by this client.
+ *
+ */
+public class HttpClientChannelHandler extends ClientChannelHandler {
+    private final NettyHttpProducer producer;
+
+    public HttpClientChannelHandler(NettyHttpProducer producer) {
+        super(producer);
+        this.producer = producer;
+    }
+
+    @Override
+    protected Message getResponseMessage(Exchange exchange, 
ChannelHandlerContext ctx, Object message) throws Exception {
+        FullHttpResponse response = (FullHttpResponse) message;
+        // use the binding
+        return 
producer.getEndpoint().getNettyHttpBinding().toCamelMessage(response, exchange, 
producer.getConfiguration());
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/db88eeda/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerChannelHandler.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerChannelHandler.java
 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerChannelHandler.java
new file mode 100644
index 0000000..38e0798
--- /dev/null
+++ 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerChannelHandler.java
@@ -0,0 +1,316 @@
+/**
+ * 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.netty4.http.handlers;
+
+import java.net.SocketAddress;
+import java.net.URI;
+import java.nio.channels.ClosedChannelException;
+import java.nio.charset.Charset;
+import java.util.Iterator;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginException;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.base64.Base64;
+import io.netty.handler.codec.http.DefaultHttpResponse;
+import io.netty.handler.codec.http.HttpHeaders;
+import io.netty.handler.codec.http.HttpRequest;
+import io.netty.handler.codec.http.HttpResponse;
+import org.apache.camel.Exchange;
+import org.apache.camel.LoggingLevel;
+import org.apache.camel.component.netty4.NettyConsumer;
+import org.apache.camel.component.netty4.NettyConverter;
+import org.apache.camel.component.netty4.NettyHelper;
+import org.apache.camel.component.netty4.handlers.ServerChannelHandler;
+import org.apache.camel.component.netty4.http.HttpPrincipal;
+import org.apache.camel.component.netty4.http.NettyHttpConsumer;
+import org.apache.camel.component.netty4.http.NettyHttpSecurityConfiguration;
+import org.apache.camel.component.netty4.http.SecurityAuthenticator;
+import org.apache.camel.util.CamelLogger;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import static io.netty.handler.codec.http.HttpHeaders.isKeepAlive;
+import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST;
+import static 
io.netty.handler.codec.http.HttpResponseStatus.METHOD_NOT_ALLOWED;
+import static io.netty.handler.codec.http.HttpResponseStatus.OK;
+import static 
io.netty.handler.codec.http.HttpResponseStatus.SERVICE_UNAVAILABLE;
+import static io.netty.handler.codec.http.HttpResponseStatus.UNAUTHORIZED;
+import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
+
+/**
+ * Netty HTTP {@link ServerChannelHandler} that handles the incoming HTTP 
requests and routes
+ * the received message in Camel.
+ */
+public class HttpServerChannelHandler extends ServerChannelHandler {
+
+    // use NettyHttpConsumer as logger to make it easier to read the logs as 
this is part of the consumer
+    private static final Logger LOG = 
LoggerFactory.getLogger(NettyHttpConsumer.class);
+    private final NettyHttpConsumer consumer;
+    private HttpRequest request;
+
+    public HttpServerChannelHandler(NettyHttpConsumer consumer) {
+        super(consumer);
+        this.consumer = consumer;
+    }
+
+    public NettyHttpConsumer getConsumer() {
+        return consumer;
+    }
+
+    @Override
+    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws 
Exception {
+        // store request, as this channel handler is created per pipeline
+        request = (HttpRequest) msg;
+
+        LOG.debug("Message received: {}", request);
+
+        if (consumer.isSuspended()) {
+            // are we suspended?
+            LOG.debug("Consumer suspended, cannot service request {}", 
request);
+            HttpResponse response = new DefaultHttpResponse(HTTP_1_1, 
SERVICE_UNAVAILABLE);
+            response.headers().set(Exchange.CONTENT_TYPE, "text/plain");
+            response.headers().set(Exchange.CONTENT_LENGTH, 0);
+            ctx.writeAndFlush(response);
+            return;
+        }
+
+        // if its an OPTIONS request then return which methods is allowed
+        if ("OPTIONS".equals(request.getMethod().name())) {
+            String s;
+            if (consumer.getEndpoint().getHttpMethodRestrict() != null) {
+                s = "OPTIONS," + 
consumer.getEndpoint().getHttpMethodRestrict();
+            } else {
+                // allow them all
+                s = "GET,HEAD,POST,PUT,DELETE,TRACE,OPTIONS,CONNECT,PATCH";
+            }
+            HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
+            response.headers().set("Allow", s);
+            response.headers().set(Exchange.CONTENT_TYPE, "text/plain");
+            response.headers().set(Exchange.CONTENT_LENGTH, 0);
+            ctx.writeAndFlush(response);
+            return;
+        }
+        if (consumer.getEndpoint().getHttpMethodRestrict() != null
+                && 
!consumer.getEndpoint().getHttpMethodRestrict().contains(request.getMethod().name()))
 {
+            HttpResponse response = new DefaultHttpResponse(HTTP_1_1, 
METHOD_NOT_ALLOWED);
+            response.headers().set(Exchange.CONTENT_TYPE, "text/plain");
+            response.headers().set(Exchange.CONTENT_LENGTH, 0);
+            ctx.writeAndFlush(response);
+            return;
+        }
+        if ("TRACE".equals(request.getMethod().name()) && 
!consumer.getEndpoint().isTraceEnabled()) {
+            HttpResponse response = new DefaultHttpResponse(HTTP_1_1, 
METHOD_NOT_ALLOWED);
+            response.headers().set(Exchange.CONTENT_TYPE, "text/plain");
+            response.headers().set(Exchange.CONTENT_LENGTH, 0);
+            ctx.writeAndFlush(response);
+            return;
+        }
+        // must include HOST header as required by HTTP 1.1
+        if (!request.headers().names().contains(HttpHeaders.Names.HOST)) {
+            HttpResponse response = new DefaultHttpResponse(HTTP_1_1, 
BAD_REQUEST);
+            //response.setChunked(false);
+            response.headers().set(Exchange.CONTENT_TYPE, "text/plain");
+            response.headers().set(Exchange.CONTENT_LENGTH, 0);
+            ctx.writeAndFlush(response);
+            return;
+        }
+
+        // is basic auth configured
+        NettyHttpSecurityConfiguration security = 
consumer.getEndpoint().getSecurityConfiguration();
+        if (security != null && security.isAuthenticate() && 
"Basic".equalsIgnoreCase(security.getConstraint())) {
+            String url = request.getUri();
+
+            // drop parameters from url
+            if (url.contains("?")) {
+                url = ObjectHelper.before(url, "?");
+            }
+
+            // we need the relative path without the hostname and port
+            URI uri = new URI(request.getUri());
+            String target = uri.getPath();
+
+            // strip the starting endpoint path so the target is relative to 
the endpoint uri
+            String path = consumer.getConfiguration().getPath();
+            if (path != null && target.startsWith(path)) {
+                target = target.substring(path.length());
+            }
+
+            // is it a restricted resource?
+            String roles;
+            if (security.getSecurityConstraint() != null) {
+                // if restricted returns null, then the resource is not 
restricted and we should not authenticate the user
+                roles = security.getSecurityConstraint().restricted(target);
+            } else {
+                // assume any roles is valid if no security constraint has 
been configured
+                roles = "*";
+            }
+            if (roles != null) {
+                // basic auth subject
+                HttpPrincipal principal = extractBasicAuthSubject(request);
+
+                // authenticate principal and check if the user is in role
+                Subject subject = null;
+                boolean inRole = true;
+                if (principal != null) {
+                    subject = 
authenticate(security.getSecurityAuthenticator(), 
security.getLoginDeniedLoggingLevel(), principal);
+                    if (subject != null) {
+                        String userRoles = 
security.getSecurityAuthenticator().getUserRoles(subject);
+                        inRole = matchesRoles(roles, userRoles);
+                    }
+                }
+
+                if (principal == null || subject == null || !inRole) {
+                    if (principal == null) {
+                        LOG.debug("Http Basic Auth required for resource: {}", 
url);
+                    } else if (subject == null) {
+                        LOG.debug("Http Basic Auth not authorized for 
username: {}", principal.getUsername());
+                    } else {
+                        LOG.debug("Http Basic Auth not in role for username: 
{}", principal.getUsername());
+                    }
+                    // restricted resource, so send back 401 to require valid 
username/password
+                    HttpResponse response = new DefaultHttpResponse(HTTP_1_1, 
UNAUTHORIZED);
+                    response.headers().set("WWW-Authenticate", "Basic 
realm=\"" + security.getRealm() + "\"");
+                    response.headers().set(Exchange.CONTENT_TYPE, 
"text/plain");
+                    response.headers().set(Exchange.CONTENT_LENGTH, 0);
+                    ctx.writeAndFlush(response);
+                    return;
+                } else {
+                    LOG.debug("Http Basic Auth authorized for username: {}", 
principal.getUsername());
+                }
+            }
+        }
+
+        // let Camel process this message
+        super.channelRead0(ctx, msg);
+    }
+
+    protected boolean matchesRoles(String roles, String userRoles) {
+        // matches if no role restrictions or any role is accepted
+        if (roles.equals("*")) {
+            return true;
+        }
+
+        // see if any of the user roles is contained in the roles list
+        Iterator<Object> it = ObjectHelper.createIterator(userRoles);
+        while (it.hasNext()) {
+            String userRole = it.next().toString();
+            if (roles.contains(userRole)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Extracts the username and password details from the HTTP basic header 
Authorization.
+     * <p/>
+     * This requires that the <tt>Authorization</tt> HTTP header is provided, 
and its using Basic.
+     * Currently Digest is <b>not</b> supported.
+     *
+     * @return {@link HttpPrincipal} with username and password details, or 
<tt>null</tt> if not possible to extract
+     */
+    protected static HttpPrincipal extractBasicAuthSubject(HttpRequest 
request) {
+        String auth = request.headers().get("Authorization");
+        if (auth != null) {
+            String constraint = ObjectHelper.before(auth, " ");
+            if (constraint != null) {
+                if ("Basic".equalsIgnoreCase(constraint.trim())) {
+                    String decoded = ObjectHelper.after(auth, " ");
+                    // the decoded part is base64 encoded, so we need to 
decode that
+                    ByteBuf buf = 
NettyConverter.toByteBuffer(decoded.getBytes());
+                    ByteBuf out = Base64.decode(buf);
+                    String userAndPw = out.toString(Charset.defaultCharset());
+                    String username = ObjectHelper.before(userAndPw, ":");
+                    String password = ObjectHelper.after(userAndPw, ":");
+                    HttpPrincipal principal = new HttpPrincipal(username, 
password);
+
+                    LOG.debug("Extracted Basic Auth principal from HTTP 
header: {}", principal);
+                    return principal;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Authenticates the http basic auth subject.
+     *
+     * @param authenticator      the authenticator
+     * @param principal          the principal
+     * @return <tt>true</tt> if username and password is valid, <tt>false</tt> 
if not
+     */
+    protected Subject authenticate(SecurityAuthenticator authenticator, 
LoggingLevel deniedLoggingLevel, HttpPrincipal principal) {
+        try {
+            return authenticator.login(principal);
+        } catch (LoginException e) {
+            CamelLogger logger = new CamelLogger(LOG, deniedLoggingLevel);
+            logger.log("Cannot login " + principal.getName() + " due " + 
e.getMessage(), e);
+        }
+        return null;
+    }
+
+    @Override
+    protected void beforeProcess(Exchange exchange, final 
ChannelHandlerContext ctx, final Object message) {
+        if (consumer.getConfiguration().isBridgeEndpoint()) {
+            exchange.setProperty(Exchange.SKIP_GZIP_ENCODING, Boolean.TRUE);
+            exchange.setProperty(Exchange.SKIP_WWW_FORM_URLENCODED, 
Boolean.TRUE);
+        }
+    }
+
+    @Override
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) 
throws Exception {
+        
+        // only close if we are still allowed to run
+        if (consumer.isRunAllowed()) {
+
+            if (cause instanceof ClosedChannelException) {
+                LOG.debug("Channel already closed. Ignoring this exception.");
+            } else {
+                LOG.warn("Closing channel as an exception was thrown from 
Netty", cause);
+                // close channel in case an exception was thrown
+                NettyHelper.close(ctx.channel());
+            }
+        }
+    }
+
+    @Override
+    protected ChannelFutureListener createResponseFutureListener(NettyConsumer 
consumer, Exchange exchange, SocketAddress remoteAddress) {
+        // make sure to close channel if not keep-alive
+        if (request != null && isKeepAlive(request)) {
+            LOG.trace("Request has Connection: keep-alive so Channel is not 
being closed");
+            return null;
+        } else {
+            LOG.trace("Request is not Connection: close so Channel is being 
closed");
+            return ChannelFutureListener.CLOSE;
+        }
+    }
+
+    @Override
+    protected Object getResponseBody(Exchange exchange) throws Exception {
+        // use the binding
+        if (exchange.hasOut()) {
+            return 
consumer.getEndpoint().getNettyHttpBinding().toNettyResponse(exchange.getOut(), 
consumer.getConfiguration());
+        } else {
+            return 
consumer.getEndpoint().getNettyHttpBinding().toNettyResponse(exchange.getIn(), 
consumer.getConfiguration());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/db88eeda/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerMultiplexChannelHandler.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerMultiplexChannelHandler.java
 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerMultiplexChannelHandler.java
new file mode 100644
index 0000000..374a846
--- /dev/null
+++ 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerMultiplexChannelHandler.java
@@ -0,0 +1,235 @@
+/**
+ * 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.netty4.http.handlers;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandler.Sharable;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.handler.codec.http.DefaultFullHttpResponse;
+import io.netty.handler.codec.http.DefaultHttpResponse;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.HttpContent;
+import io.netty.handler.codec.http.HttpRequest;
+import io.netty.handler.codec.http.HttpResponse;
+import io.netty.util.Attribute;
+import io.netty.util.AttributeKey;
+import org.apache.camel.Exchange;
+import org.apache.camel.component.netty4.http.ContextPathMatcher;
+import org.apache.camel.component.netty4.http.HttpServerConsumerChannelFactory;
+import org.apache.camel.component.netty4.http.NettyHttpConsumer;
+import org.apache.camel.component.netty4.http.RestContextPathMatcher;
+import org.apache.camel.util.UnsafeUriCharactersEncoder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import static io.netty.handler.codec.http.HttpResponseStatus.NOT_FOUND;
+import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
+
+/**
+ * A multiplex {@link 
org.apache.camel.component.netty4.http.HttpServerPipelineFactory} which keeps a 
list of handlers, and delegates to the
+ * target handler based on the http context path in the incoming request. This 
is used to allow to reuse
+ * the same Netty consumer, allowing to have multiple routes on the same netty 
{@link io.netty.bootstrap.ServerBootstrap}
+ */
+@Sharable
+public class HttpServerMultiplexChannelHandler extends 
SimpleChannelInboundHandler<Object> implements HttpServerConsumerChannelFactory 
{
+
+    // use NettyHttpConsumer as logger to make it easier to read the logs as 
this is part of the consumer
+    private static final Logger LOG = 
LoggerFactory.getLogger(NettyHttpConsumer.class);
+    private static final AttributeKey<HttpServerChannelHandler> 
SERVER_HANDLER_KEY = AttributeKey.valueOf("serverHandler");
+    private final ConcurrentMap<ContextPathMatcher, HttpServerChannelHandler> 
consumers = new ConcurrentHashMap<ContextPathMatcher, 
HttpServerChannelHandler>();
+    private int port;
+    private String token;
+    private int len;
+
+    public HttpServerMultiplexChannelHandler() {
+        // must have default no-arg constructor to allow IoC containers to 
manage it
+    }
+
+    public void init(int port) {
+        this.port = port;
+        this.token = ":" + port;
+        this.len = token.length();
+    }
+
+    public void addConsumer(NettyHttpConsumer consumer) {
+        String rawPath = consumer.getConfiguration().getPath();
+        String path = pathAsKey(consumer.getConfiguration().getPath());
+        // use rest path matcher in case Rest DSL is in use
+        ContextPathMatcher matcher = new RestContextPathMatcher(rawPath, path, 
consumer.getConfiguration().isMatchOnUriPrefix());
+        consumers.put(matcher, new HttpServerChannelHandler(consumer));
+    }
+
+    public void removeConsumer(NettyHttpConsumer consumer) {
+        String rawPath = consumer.getConfiguration().getPath();
+        String path = pathAsKey(consumer.getConfiguration().getPath());
+        // use rest path matcher in case Rest DSL is in use
+        ContextPathMatcher matcher = new RestContextPathMatcher(rawPath, path, 
consumer.getConfiguration().isMatchOnUriPrefix());
+        consumers.remove(matcher);
+    }
+
+    public int consumers() {
+        return consumers.size();
+    }
+
+    public int getPort() {
+        return port;
+    }
+
+    public ChannelHandler getChannelHandler() {
+        return this;
+    }
+
+    @Override
+    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws 
Exception {
+        // store request, as this channel handler is created per pipeline
+        HttpRequest request = (HttpRequest) msg;
+      
+        LOG.debug("Message received: {}", request);
+
+        HttpServerChannelHandler handler = getHandler(request);
+        if (handler != null) {
+            Attribute<HttpServerChannelHandler> attr = 
ctx.attr(SERVER_HANDLER_KEY);
+            // store handler as attachment
+            attr.set(handler);
+            if (msg instanceof HttpContent) {
+                // need to hold the reference of content
+                HttpContent httpContent = (HttpContent) msg;
+                httpContent.content().retain();
+            }   
+            handler.channelRead(ctx, request);
+        } else {
+            // this resource is not found, so send empty response back
+            HttpResponse response = new DefaultHttpResponse(HTTP_1_1, 
NOT_FOUND);
+            response.headers().set(Exchange.CONTENT_TYPE, "text/plain");
+            response.headers().set(Exchange.CONTENT_LENGTH, 0);
+            ctx.writeAndFlush(response);
+        }
+    }
+
+    @Override
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) 
throws Exception {
+        Attribute<HttpServerChannelHandler> attr = 
ctx.attr(SERVER_HANDLER_KEY);
+        HttpServerChannelHandler handler = attr.get();
+        if (handler != null) {
+            handler.exceptionCaught(ctx, cause);
+        } else {
+            // we cannot throw the exception here
+            LOG.warn("HttpServerChannelHandler is not found as attachment to 
handle exception, send 404 back to the client.", cause);
+            // Now we just send 404 back to the client
+            HttpResponse response = new DefaultHttpResponse(HTTP_1_1, 
NOT_FOUND);
+            response.headers().set(Exchange.CONTENT_TYPE, "text/plain");
+            response.headers().set(Exchange.CONTENT_LENGTH, 0);
+            ctx.writeAndFlush(response);
+        }
+    }
+
+    private HttpServerChannelHandler getHandler(HttpRequest request) {
+        HttpServerChannelHandler answer = null;
+
+        // need to strip out host and port etc, as we only need the 
context-path for matching
+        String method = request.getMethod().name();
+        if (method == null) {
+            return null;
+        }
+
+        String path = request.getUri();
+        int idx = path.indexOf(token);
+        if (idx > -1) {
+            path = path.substring(idx + len);
+        }
+        // use the path as key to find the consumer handler to use
+        path = pathAsKey(path);
+
+
+        List<Map.Entry<ContextPathMatcher, HttpServerChannelHandler>> 
candidates = new ArrayList<Map.Entry<ContextPathMatcher, 
HttpServerChannelHandler>>();
+
+        // first match by http method
+        for (Map.Entry<ContextPathMatcher, HttpServerChannelHandler> entry : 
consumers.entrySet()) {
+            NettyHttpConsumer consumer = entry.getValue().getConsumer();
+            String restrict = consumer.getEndpoint().getHttpMethodRestrict();
+            if (entry.getKey().matchMethod(method, restrict)) {
+                candidates.add(entry);
+            }
+        }
+
+        // then see if we got a direct match
+        Iterator<Map.Entry<ContextPathMatcher, HttpServerChannelHandler>> it = 
candidates.iterator();
+        while (it.hasNext()) {
+            Map.Entry<ContextPathMatcher, HttpServerChannelHandler> entry = 
it.next();
+            if (entry.getKey().matchesRest(path, false)) {
+                answer = entry.getValue();
+                break;
+            }
+        }
+
+        // then match by non wildcard path
+        if (answer == null) {
+            it = candidates.iterator();
+            while (it.hasNext()) {
+                Map.Entry<ContextPathMatcher, HttpServerChannelHandler> entry 
= it.next();
+                if (!entry.getKey().matchesRest(path, true)) {
+                    it.remove();
+                }
+            }
+
+            // there should only be one
+            if (candidates.size() == 1) {
+                answer = candidates.get(0).getValue();
+            }
+        }
+
+        // fallback to regular matching
+        if (answer == null) {
+            for (Map.Entry<ContextPathMatcher, HttpServerChannelHandler> entry 
: consumers.entrySet()) {
+                if (entry.getKey().matches(path)) {
+                    answer = entry.getValue();
+                    break;
+                }
+            }
+        }
+
+        return answer;
+    }
+
+    private static String pathAsKey(String path) {
+        // cater for default path
+        if (path == null || path.equals("/")) {
+            path = "";
+        }
+
+        // strip out query parameters
+        int idx = path.indexOf('?');
+        if (idx > -1) {
+            path = path.substring(0, idx);
+        }
+
+        // strip of ending /
+        if (path.endsWith("/")) {
+            path = path.substring(0, path.length() - 1);
+        }
+
+        return UnsafeUriCharactersEncoder.encodeHttpURI(path);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/db88eeda/components/camel-netty4-http/src/main/resources/META-INF/LICENSE.txt
----------------------------------------------------------------------
diff --git 
a/components/camel-netty4-http/src/main/resources/META-INF/LICENSE.txt 
b/components/camel-netty4-http/src/main/resources/META-INF/LICENSE.txt
new file mode 100644
index 0000000..6b0b127
--- /dev/null
+++ b/components/camel-netty4-http/src/main/resources/META-INF/LICENSE.txt
@@ -0,0 +1,203 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
+

http://git-wip-us.apache.org/repos/asf/camel/blob/db88eeda/components/camel-netty4-http/src/main/resources/META-INF/NOTICE.txt
----------------------------------------------------------------------
diff --git 
a/components/camel-netty4-http/src/main/resources/META-INF/NOTICE.txt 
b/components/camel-netty4-http/src/main/resources/META-INF/NOTICE.txt
new file mode 100644
index 0000000..2e215bf
--- /dev/null
+++ b/components/camel-netty4-http/src/main/resources/META-INF/NOTICE.txt
@@ -0,0 +1,11 @@
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the Apache Camel distribution.                    ==
+   =========================================================================
+
+   This product includes software developed by
+   The Apache Software Foundation (http://www.apache.org/).
+
+   Please read the different LICENSE files present in the licenses directory of
+   this distribution.

http://git-wip-us.apache.org/repos/asf/camel/blob/db88eeda/components/camel-netty4-http/src/main/resources/META-INF/services/org/apache/camel/TypeConverter
----------------------------------------------------------------------
diff --git 
a/components/camel-netty4-http/src/main/resources/META-INF/services/org/apache/camel/TypeConverter
 
b/components/camel-netty4-http/src/main/resources/META-INF/services/org/apache/camel/TypeConverter
new file mode 100644
index 0000000..b9e3cc7
--- /dev/null
+++ 
b/components/camel-netty4-http/src/main/resources/META-INF/services/org/apache/camel/TypeConverter
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+org.apache.camel.component.netty4.http.NettyHttpConverter
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/db88eeda/components/camel-netty4-http/src/main/resources/META-INF/services/org/apache/camel/component/netty4-http
----------------------------------------------------------------------
diff --git 
a/components/camel-netty4-http/src/main/resources/META-INF/services/org/apache/camel/component/netty4-http
 
b/components/camel-netty4-http/src/main/resources/META-INF/services/org/apache/camel/component/netty4-http
new file mode 100644
index 0000000..b26f6af
--- /dev/null
+++ 
b/components/camel-netty4-http/src/main/resources/META-INF/services/org/apache/camel/component/netty4-http
@@ -0,0 +1,17 @@
+# 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.
+#
+
+class=org.apache.camel.component.netty4.http.NettyHttpComponent

http://git-wip-us.apache.org/repos/asf/camel/blob/db88eeda/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/BaseNettyTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/BaseNettyTest.java
 
b/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/BaseNettyTest.java
new file mode 100644
index 0000000..c511d89
--- /dev/null
+++ 
b/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/BaseNettyTest.java
@@ -0,0 +1,95 @@
+/**
+ * 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.netty4.http;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.Properties;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.properties.PropertiesComponent;
+import org.apache.camel.converter.IOConverter;
+import org.apache.camel.impl.JndiRegistry;
+import org.apache.camel.test.AvailablePortFinder;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+/**
+ *
+ */
+public class BaseNettyTest extends CamelTestSupport {
+    private static volatile int port;
+
+    @BeforeClass
+    public static void initPort() throws Exception {
+        File file = new File("target/nettyport.txt");
+
+        if (!file.exists()) {
+            // start from somewhere in the 26xxx range
+            port = AvailablePortFinder.getNextAvailable(26000);
+        } else {
+            // read port number from file
+            String s = IOConverter.toString(file, null);
+            port = Integer.parseInt(s);
+            // use next free port
+            port = AvailablePortFinder.getNextAvailable(port + 1);
+        }
+
+    }
+
+    @AfterClass
+    public static void savePort() throws Exception {
+        File file = new File("target/nettyport.txt");
+
+        // save to file, do not append
+        FileOutputStream fos = new FileOutputStream(file, false);
+        try {
+            fos.write(String.valueOf(port).getBytes());
+        } finally {
+            fos.close();
+        }
+    }
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        CamelContext context = super.createCamelContext();
+        context.addComponent("properties", new 
PropertiesComponent("ref:prop"));
+        return context;
+    }
+
+    @Override
+    protected JndiRegistry createRegistry() throws Exception {
+        JndiRegistry jndi = super.createRegistry();
+
+        Properties prop = new Properties();
+        prop.setProperty("port", "" + getPort());
+        jndi.bind("prop", prop);
+
+        return jndi;
+    }
+
+    protected int getNextPort() {
+        port = AvailablePortFinder.getNextAvailable(port + 1);
+        return port;
+    }
+
+    protected int getPort() {
+        return port;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/db88eeda/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/ManagedNettyEndpointTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/ManagedNettyEndpointTest.java
 
b/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/ManagedNettyEndpointTest.java
new file mode 100644
index 0000000..0363450
--- /dev/null
+++ 
b/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/ManagedNettyEndpointTest.java
@@ -0,0 +1,81 @@
+/**
+ * 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.netty4.http;
+
+import java.util.Set;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.Test;
+
+public class ManagedNettyEndpointTest extends BaseNettyTest {
+
+    @Override
+    protected boolean useJmx() {
+        return true;
+    }
+
+    protected CamelContext createCamelContext() throws Exception {
+        CamelContext context = super.createCamelContext();
+        return context;
+    }
+
+    protected MBeanServer getMBeanServer() {
+        return 
context.getManagementStrategy().getManagementAgent().getMBeanServer();
+    }
+
+    @Test
+    public void testManagement() throws Exception {
+        // JMX tests dont work well on AIX CI servers (hangs them)
+        if (isPlatform("aix")) {
+            return;
+        }
+
+        // should not add 10 endpoints
+        getMockEndpoint("mock:foo").expectedMessageCount(10);
+        for (int i = 0; i < 10; i++) {
+            String out = 
template.requestBody("netty4-http:http://localhost:{{port}}/foo?param"; + i + 
"=value" + i, "Hello World", String.class);
+            assertEquals("param" + i + "=value" + i, out);
+        }
+        assertMockEndpointsSatisfied();
+
+        MBeanServer mbeanServer = getMBeanServer();
+
+        ObjectName on = 
ObjectName.getInstance("org.apache.camel:context=camel-1,type=endpoints,name=\"http://0.0.0.0:";
 + getPort() + "/foo\"");
+        mbeanServer.isRegistered(on);
+        
+        // should only be 2 endpoints in JMX
+        Set<ObjectName> set = getMBeanServer().queryNames(new 
ObjectName("*:context=camel-1,type=endpoints,*"), null);
+        assertEquals(2, set.size());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("netty4-http:http://0.0.0.0:{{port}}/foo";)
+                    .to("mock:foo")
+                    .transform().header(Exchange.HTTP_QUERY);
+            }
+        };
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/db88eeda/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/MyLoginModule.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/MyLoginModule.java
 
b/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/MyLoginModule.java
new file mode 100644
index 0000000..2954688
--- /dev/null
+++ 
b/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/MyLoginModule.java
@@ -0,0 +1,102 @@
+/**
+ * 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.netty4.http;
+
+import java.io.IOException;
+import java.util.Map;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+
+public class MyLoginModule implements LoginModule {
+
+    private Subject subject;
+    private CallbackHandler callbackHandler;
+
+    @Override
+    public void initialize(Subject subject, CallbackHandler callbackHandler, 
Map<String, ?> sharedState, Map<String, ?> options) {
+        this.subject = subject;
+        this.callbackHandler = callbackHandler;
+    }
+
+    @Override
+    public boolean login() throws LoginException {
+
+        // get username and password
+        Callback[] callbacks = new Callback[2];
+        callbacks[0] = new NameCallback("username");
+        callbacks[1] = new PasswordCallback("password", false);
+
+        try {
+            callbackHandler.handle(callbacks);
+            String username = ((NameCallback)callbacks[0]).getName();
+            char[] tmpPassword = 
((PasswordCallback)callbacks[1]).getPassword();
+            String password = new String(tmpPassword);
+            ((PasswordCallback)callbacks[1]).clearPassword();
+
+            // only allow login if password is secret
+            // as this is just for testing purpose
+            if (!"secret".equals(password)) {
+                throw new LoginException("Login denied");
+            }
+
+            // add roles
+            if ("scott".equals(username)) {
+                subject.getPrincipals().add(new MyRolePrincipal("admin"));
+                subject.getPrincipals().add(new MyRolePrincipal("guest"));
+            } else if ("guest".equals(username)) {
+                subject.getPrincipals().add(new MyRolePrincipal("guest"));
+            }
+
+        } catch (IOException ioe) {
+            LoginException le = new LoginException(ioe.toString());
+            le.initCause(ioe);
+            throw le;
+        } catch (UnsupportedCallbackException uce) {
+            LoginException le = new LoginException("Error: " + 
uce.getCallback().toString()
+                    + " not available to gather authentication information 
from the user");
+            le.initCause(uce);
+            throw le;
+        }
+
+
+        return true;
+    }
+
+    @Override
+    public boolean commit() throws LoginException {
+        return true;
+    }
+
+    @Override
+    public boolean abort() throws LoginException {
+        return true;
+    }
+
+    @Override
+    public boolean logout() throws LoginException {
+        subject = null;
+        callbackHandler = null;
+        return true;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/db88eeda/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/MyRolePrincipal.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/MyRolePrincipal.java
 
b/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/MyRolePrincipal.java
new file mode 100644
index 0000000..3d11406
--- /dev/null
+++ 
b/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/MyRolePrincipal.java
@@ -0,0 +1,33 @@
+/**
+ * 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.netty4.http;
+
+import java.security.Principal;
+
+public class MyRolePrincipal implements Principal {
+
+    private final String role;
+
+    public MyRolePrincipal(String role) {
+        this.role = role;
+    }
+
+    @Override
+    public String getName() {
+        return role;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/db88eeda/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/NettyHttp500ErrorTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/NettyHttp500ErrorTest.java
 
b/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/NettyHttp500ErrorTest.java
new file mode 100644
index 0000000..ef8ddbe
--- /dev/null
+++ 
b/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/NettyHttp500ErrorTest.java
@@ -0,0 +1,66 @@
+/**
+ * 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.netty4.http;
+
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.Test;
+
+public class NettyHttp500ErrorTest extends BaseNettyTest {
+
+    @Test
+    public void testHttp500Error() throws Exception {
+        getMockEndpoint("mock:input").expectedBodiesReceived("Hello World");
+
+        try {
+            template.requestBody("netty4-http:http://localhost:{{port}}/foo";, 
"Hello World", String.class);
+            fail("Should have failed");
+        } catch (CamelExecutionException e) {
+            NettyHttpOperationFailedException cause = 
assertIsInstanceOf(NettyHttpOperationFailedException.class, e.getCause());
+            assertEquals(500, cause.getStatusCode());
+            assertEquals("Camel cannot do this", 
context.getTypeConverter().convertTo(String.class, 
cause.getHttpContent().content()));
+        }
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testHttp500ErrorDisabled() throws Exception {
+        getMockEndpoint("mock:input").expectedBodiesReceived("Hello World");
+
+        String body = 
template.requestBody("netty4-http:http://localhost:{{port}}/foo?throwExceptionOnFailure=false";,
 "Hello World", String.class);
+        assertEquals("Camel cannot do this", body);
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("netty4-http:http://0.0.0.0:{{port}}/foo";)
+                    .to("mock:input")
+                    // trigger failure by setting error code to 500
+                    .setHeader(Exchange.HTTP_RESPONSE_CODE, constant(500))
+                    .setBody().constant("Camel cannot do this");
+            }
+        };
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/db88eeda/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/NettyHttp500ErrorThrowExceptionOnServerTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/NettyHttp500ErrorThrowExceptionOnServerTest.java
 
b/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/NettyHttp500ErrorThrowExceptionOnServerTest.java
new file mode 100644
index 0000000..b5aa37b
--- /dev/null
+++ 
b/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/NettyHttp500ErrorThrowExceptionOnServerTest.java
@@ -0,0 +1,67 @@
+/**
+ * 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.netty4.http;
+
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.Test;
+
+public class NettyHttp500ErrorThrowExceptionOnServerTest extends BaseNettyTest 
{
+
+    @Test
+    public void testHttp500Error() throws Exception {
+        getMockEndpoint("mock:input").expectedBodiesReceived("Hello World");
+
+        try {
+            template.requestBody("netty4-http:http://localhost:{{port}}/foo";, 
"Hello World", String.class);
+            fail("Should have failed");
+        } catch (CamelExecutionException e) {
+            NettyHttpOperationFailedException cause = 
assertIsInstanceOf(NettyHttpOperationFailedException.class, e.getCause());
+            assertEquals(500, cause.getStatusCode());
+            String trace = context.getTypeConverter().convertTo(String.class, 
cause.getHttpContent().content());
+            assertNotNull(trace);
+            assertTrue(trace.startsWith("java.lang.IllegalArgumentException: 
Camel cannot do this"));
+            assertEquals("http://localhost:"; + getPort() + "/foo", 
cause.getUri());
+        }
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testHttp500ErrorDisabled() throws Exception {
+        getMockEndpoint("mock:input").expectedBodiesReceived("Hello World");
+
+        String body = 
template.requestBody("netty4-http:http://localhost:{{port}}/foo?throwExceptionOnFailure=false";,
 "Hello World", String.class);
+        assertTrue(body.startsWith("java.lang.IllegalArgumentException: Camel 
cannot do this"));
+
+        assertMockEndpointsSatisfied();
+    }
+
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("netty4-http:http://0.0.0.0:{{port}}/foo";)
+                    .to("mock:input")
+                    .throwException(new IllegalArgumentException("Camel cannot 
do this"));
+            }
+        };
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/db88eeda/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/NettyHttpAccessHttpRequestAndResponseBeanTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/NettyHttpAccessHttpRequestAndResponseBeanTest.java
 
b/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/NettyHttpAccessHttpRequestAndResponseBeanTest.java
new file mode 100644
index 0000000..6e32b85
--- /dev/null
+++ 
b/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/NettyHttpAccessHttpRequestAndResponseBeanTest.java
@@ -0,0 +1,74 @@
+/**
+ * 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.netty4.http;
+
+import java.nio.charset.Charset;
+
+import io.netty.handler.codec.http.DefaultFullHttpResponse;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.HttpHeaders;
+import io.netty.handler.codec.http.HttpResponse;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import io.netty.handler.codec.http.HttpVersion;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.netty4.NettyConverter;
+import org.junit.Test;
+
+public class NettyHttpAccessHttpRequestAndResponseBeanTest extends 
BaseNettyTest {
+
+    @Test
+    public void testRawHttpRequestAndResponseInBean() throws Exception {
+        getMockEndpoint("mock:input").expectedBodiesReceived("World", "Camel");
+
+        String out = 
template.requestBody("netty4-http:http://localhost:{{port}}/foo";, "World", 
String.class);
+        assertEquals("Bye World", out);
+
+        String out2 = 
template.requestBody("netty4-http:http://localhost:{{port}}/foo";, "Camel", 
String.class);
+        assertEquals("Bye Camel", out2);
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("netty4-http:http://0.0.0.0:{{port}}/foo";)
+                    .to("mock:input")
+                    
.transform().method(NettyHttpAccessHttpRequestAndResponseBeanTest.class, 
"myTransformer");
+            }
+        };
+    }
+
+    /**
+     * We can use both a netty http request and response type for 
transformation
+     */
+    public static HttpResponse myTransformer(FullHttpRequest request) {
+        String in = request.content().toString(Charset.forName("UTF-8"));
+        String reply = "Bye " + in;
+
+        HttpResponse response = new 
DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
+                                                            
NettyConverter.toByteBuffer(reply.getBytes()));
+        
+        response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, 
reply.length());
+
+        return response;
+    }
+
+}

Reply via email to