FELIX-5207 : Flexible Customizer for 'Enable Proxy/Load Balancer Connection'. Apply slightly modified patch from Antonio Sanso
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1734779 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/http/jetty/src/main/java/org/apache/felix/http/jetty/LoadBalancerCustomizerFactory.java b/http/jetty/src/main/java/org/apache/felix/http/jetty/LoadBalancerCustomizerFactory.java
new file mode 100644
index 0000000..e8c717f
--- /dev/null
+++ b/http/jetty/src/main/java/org/apache/felix/http/jetty/LoadBalancerCustomizerFactory.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.felix.http.jetty;
+
+import org.eclipse.jetty.server.HttpConfiguration.Customizer;
+import org.osgi.annotation.versioning.ConsumerType;
+
+
+/**
+ * The <code>LoadBalancerCustomizerFactory</code> is a service interface which allows
+ * extensions to inject custom Jetty {@code Customizer} instances to add
+ * to the Jetty server in order to handle the Proxy Load Balancer connection.
+ *
+ * {@code LoadBalancerCustomizerFactory } services are responsible for creating the
+ * {@code Customizer} instances and providing base configuration.
+ *
+ * @since 2.1
+ */
+@ConsumerType
+public interface LoadBalancerCustomizerFactory
+{
+ /**
+ * Creates new Jetty {@code Customizer} instances.
+ *
+ * <p>
+ * @return A configured Jetty {@code Customizer} instance.
+ */
+ Customizer createCustomizer();
+
+}
diff --git a/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/CustomizerWrapper.java b/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/CustomizerWrapper.java
new file mode 100644
index 0000000..0edc793
--- /dev/null
+++ b/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/CustomizerWrapper.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.jetty.internal;
+
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.HttpConfiguration;
+import org.eclipse.jetty.server.HttpConfiguration.Customizer;
+import org.eclipse.jetty.server.Request;
+
+public class CustomizerWrapper implements Customizer
+{
+
+ private volatile Customizer customizer;
+
+ public void setCustomizer(final Customizer customizer)
+ {
+ this.customizer = customizer;
+ }
+
+ @Override
+ public void customize(final Connector connector,
+ final HttpConfiguration channelConfig,
+ final Request request)
+ {
+ final Customizer local = this.customizer;
+ if (local!= null )
+ {
+ local.customize(connector, channelConfig, request);
+ }
+ }
+}
diff --git a/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/ForwardedRequestCustomizerFactory.java b/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/ForwardedRequestCustomizerFactory.java
new file mode 100644
index 0000000..5bfb052
--- /dev/null
+++ b/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/ForwardedRequestCustomizerFactory.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.felix.http.jetty.internal;
+
+import org.apache.felix.http.jetty.LoadBalancerCustomizerFactory;
+import org.eclipse.jetty.server.ForwardedRequestCustomizer;
+import org.eclipse.jetty.server.HttpConfiguration.Customizer;
+
+public class ForwardedRequestCustomizerFactory implements LoadBalancerCustomizerFactory
+{
+
+ @Override
+ public Customizer createCustomizer()
+ {
+ return new ForwardedRequestCustomizer();
+ }
+}
diff --git a/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/LoadBalancerCustomizerFactoryTracker.java b/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/LoadBalancerCustomizerFactoryTracker.java
new file mode 100644
index 0000000..5f9e5b0
--- /dev/null
+++ b/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/LoadBalancerCustomizerFactoryTracker.java
@@ -0,0 +1,106 @@
+/*
+ * 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.felix.http.jetty.internal;
+
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.apache.felix.http.jetty.LoadBalancerCustomizerFactory;
+import org.eclipse.jetty.server.HttpConfiguration.Customizer;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+
+public class LoadBalancerCustomizerFactoryTracker extends ServiceTracker<LoadBalancerCustomizerFactory, ServiceReference<LoadBalancerCustomizerFactory>>
+{
+
+ private final CustomizerWrapper customizerWrapper;
+ private final BundleContext bundleContext;
+ private final SortedSet<ServiceReference<LoadBalancerCustomizerFactory>> set = new TreeSet<ServiceReference<LoadBalancerCustomizerFactory>>();
+
+ public LoadBalancerCustomizerFactoryTracker(final BundleContext context, final CustomizerWrapper customizerWrapper)
+ {
+ super(context, LoadBalancerCustomizerFactory.class.getName(), null);
+ this.bundleContext =context;
+ this.customizerWrapper = customizerWrapper;
+ }
+
+ @Override
+ public ServiceReference<LoadBalancerCustomizerFactory> addingService(final ServiceReference<LoadBalancerCustomizerFactory> reference)
+ {
+ super.addingService(reference);
+
+ final ServiceReference<LoadBalancerCustomizerFactory> highestReference;
+ synchronized (set)
+ {
+ set.add(reference);
+ highestReference = set.last();
+ }
+
+ boolean updated = false;
+ if (highestReference != null)
+ {
+ final LoadBalancerCustomizerFactory factory = bundleContext.getService(highestReference);
+ if (factory != null)
+ {
+ final Customizer customizer = factory.createCustomizer();
+ customizerWrapper.setCustomizer(customizer);
+ updated = true;
+ }
+ }
+ // something went wrong, null out wrapper
+ if ( !updated )
+ {
+ customizerWrapper.setCustomizer(null);
+ }
+
+ return reference;
+ }
+
+ @Override
+ public void removedService(final ServiceReference<LoadBalancerCustomizerFactory> reference, final ServiceReference<LoadBalancerCustomizerFactory> service)
+ {
+ super.removedService(reference, service);
+
+ final ServiceReference<LoadBalancerCustomizerFactory> highestReference;
+ synchronized (set)
+ {
+ set.remove(reference);
+ highestReference = set.last();
+ }
+
+ boolean updated = false;
+ if (highestReference != null)
+ {
+ //update the customizer Wrapper
+ final LoadBalancerCustomizerFactory factory = bundleContext.getService(highestReference);
+ if (factory != null)
+ {
+ final Customizer customizer = factory.createCustomizer();
+ customizerWrapper.setCustomizer(customizer);
+ updated = true;
+ }
+ }
+ // something went wrong / or no service registered anymore, null out wrapper
+ if ( !updated )
+ {
+ customizerWrapper.setCustomizer(null);
+ }
+ }
+}