summaryrefslogtreecommitdiffstats
path: root/branches/sca-java-1.x/modules/binding-ws-axis2-jms/src/main/java/org/apache/tuscany/sca/binding/ws/axis2/transport/base/tracker/AxisServiceTracker.java
diff options
context:
space:
mode:
authorantelder <antelder@13f79535-47bb-0310-9956-ffa450edef68>2009-05-11 07:45:29 +0000
committerantelder <antelder@13f79535-47bb-0310-9956-ffa450edef68>2009-05-11 07:45:29 +0000
commita3cbf8e5ffabac239cd965d8c0f9c680a83246f7 (patch)
tree03eede7de9657506784538ce0e3786a808e4ab22 /branches/sca-java-1.x/modules/binding-ws-axis2-jms/src/main/java/org/apache/tuscany/sca/binding/ws/axis2/transport/base/tracker/AxisServiceTracker.java
parenta7a97f2875dc162750736b9611e3e8bc8c13f145 (diff)
Add a new soap/jms transport module copied from the Apache WS Commons transports but with the code backported to work with Axis2 1.4.1
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@773489 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'branches/sca-java-1.x/modules/binding-ws-axis2-jms/src/main/java/org/apache/tuscany/sca/binding/ws/axis2/transport/base/tracker/AxisServiceTracker.java')
-rw-r--r--branches/sca-java-1.x/modules/binding-ws-axis2-jms/src/main/java/org/apache/tuscany/sca/binding/ws/axis2/transport/base/tracker/AxisServiceTracker.java245
1 files changed, 245 insertions, 0 deletions
diff --git a/branches/sca-java-1.x/modules/binding-ws-axis2-jms/src/main/java/org/apache/tuscany/sca/binding/ws/axis2/transport/base/tracker/AxisServiceTracker.java b/branches/sca-java-1.x/modules/binding-ws-axis2-jms/src/main/java/org/apache/tuscany/sca/binding/ws/axis2/transport/base/tracker/AxisServiceTracker.java
new file mode 100644
index 0000000000..fca85ee71e
--- /dev/null
+++ b/branches/sca-java-1.x/modules/binding-ws-axis2-jms/src/main/java/org/apache/tuscany/sca/binding/ws/axis2/transport/base/tracker/AxisServiceTracker.java
@@ -0,0 +1,245 @@
+/*
+ * 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.tuscany.sca.binding.ws.axis2.transport.base.tracker;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.Set;
+
+import org.apache.axiom.om.OMElement;
+import org.apache.axis2.AxisFault;
+import org.apache.axis2.description.AxisModule;
+import org.apache.axis2.description.AxisService;
+import org.apache.axis2.description.AxisServiceGroup;
+import org.apache.axis2.description.Parameter;
+import org.apache.axis2.engine.AxisConfiguration;
+import org.apache.axis2.engine.AxisEvent;
+import org.apache.axis2.engine.AxisObserver;
+
+/**
+ * <p>Tracks services deployed in a given {@link AxisConfiguration}.
+ * The tracker is configured with references to three objects:</p>
+ * <ol>
+ * <li>An {@link AxisConfiguration} to watch.</li>
+ * <li>An {@link AxisServiceFilter} restricting the services to track.</li>
+ * <li>An {@link AxisServiceTrackerListener} receiving tracking events.</li>
+ * </ol>
+ * <p>An instance of this class maintains an up-to-date list of services
+ * satisfying all of the following criteria:</p>
+ * <ol>
+ * <li>The service is deployed in the given {@link AxisConfiguration}.</li>
+ * <li>The service is started, i.e. {@link AxisService#isActive()} returns true.</li>
+ * <li>The service matches the criteria specified by the given
+ * {@link AxisServiceFilter} instance.</li>
+ * </ol>
+ * <p>Whenever a service appears on the list, the tracker will call
+ * {@link AxisServiceTrackerListener#serviceAdded(AxisService)}. When a service disappears, it
+ * will call {@link AxisServiceTrackerListener#serviceRemoved(AxisService)}.</p>
+ * <p>When the tracker is created, it is initially in the stopped state. In this state no
+ * events will be sent to the listener. It can be started using {@link #start()} and stopped again
+ * using {@link #stop()}. The tracker list is defined to be empty when the tracker is in the
+ * stopped state. This implies that a call to {@link #start()} will generate
+ * {@link AxisServiceTrackerListener#serviceAdded(AxisService)} events for all services that meet
+ * the above criteria at that point in time. In the same way, {@link #stop()} will generate
+ * {@link AxisServiceTrackerListener#serviceRemoved(AxisService)} events for the current entries
+ * in the list.</p>
+ * <p>As a corollary the tracker guarantees that during a complete lifecycle (start-stop),
+ * there will be exactly one {@link AxisServiceTrackerListener#serviceRemoved(AxisService)} event
+ * for every {@link AxisServiceTrackerListener#serviceAdded(AxisService)} event and vice-versa.
+ * This property is important when the tracker is used to allocate resources for a dynamic set
+ * of services.</p>
+ *
+ * <h2>Limitations</h2>
+ *
+ * <p>The tracker is not able to detect property changes on services. E.g. if a service initially
+ * matches the filter criteria, but later changes so that it doesn't match the criteria any more,
+ * the tracker will not be able to detect this and the service will not be removed from the tracker
+ * list.</p>
+ */
+public class AxisServiceTracker {
+ private final AxisObserver observer = new AxisObserver() {
+ public void init(AxisConfiguration axisConfig) {}
+
+ public void serviceUpdate(AxisEvent event, final AxisService service) {
+ switch (event.getEventType()) {
+ case AxisEvent.SERVICE_DEPLOY:
+ case AxisEvent.SERVICE_START:
+ if (filter.matches(service)) {
+ boolean pending;
+ synchronized (lock) {
+ if (pending = (pendingActions != null)) {
+ pendingActions.add(new Runnable() {
+ public void run() {
+ serviceAdded(service);
+ }
+ });
+ }
+ }
+ if (!pending) {
+ serviceAdded(service);
+ }
+ }
+ break;
+ case AxisEvent.SERVICE_REMOVE:
+ case AxisEvent.SERVICE_STOP:
+ // Don't check filter here because the properties of the service may have
+ // changed in the meantime.
+ boolean pending;
+ synchronized (lock) {
+ if (pending = (pendingActions != null)) {
+ pendingActions.add(new Runnable() {
+ public void run() {
+ serviceRemoved(service);
+ }
+ });
+ }
+ }
+ if (!pending) {
+ serviceRemoved(service);
+ }
+ }
+ }
+
+ public void moduleUpdate(AxisEvent event, AxisModule module) {}
+ public void addParameter(Parameter param) throws AxisFault {}
+ public void removeParameter(Parameter param) throws AxisFault {}
+ public void deserializeParameters(OMElement parameterElement) throws AxisFault {}
+ public Parameter getParameter(String name) { return null; }
+ public ArrayList<Parameter> getParameters() { return null; }
+ public boolean isParameterLocked(String parameterName) { return false; }
+ public void serviceGroupUpdate(AxisEvent event, AxisServiceGroup serviceGroup) {}
+ };
+
+ private final AxisConfiguration config;
+ final AxisServiceFilter filter;
+ private final AxisServiceTrackerListener listener;
+
+ /**
+ * Object used to synchronize access to {@link #pendingActions} and {@link #services}.
+ */
+ final Object lock = new Object();
+
+ /**
+ * Queue for notifications received by the {@link AxisObserver} during startup of the tracker.
+ * We need this because the events may already be reflected in the list of services returned
+ * by {@link AxisConfiguration#getServices()} (getting the list of currently deployed services
+ * and adding the observer can't be done atomically). It also allows us to make sure that
+ * events are sent to the listener in the right order, e.g. when a service is being removed
+ * during startup of the tracker.
+ */
+ Queue<Runnable> pendingActions;
+
+ /**
+ * The current list of services. <code>null</code> if the tracker is stopped.
+ */
+ private Set<AxisService> services;
+
+ public AxisServiceTracker(AxisConfiguration config, AxisServiceFilter filter,
+ AxisServiceTrackerListener listener) {
+ this.config = config;
+ this.filter = filter;
+ this.listener = listener;
+ }
+
+ /**
+ * Check whether the tracker is started.
+ *
+ * @return <code>true</code> if the tracker is started
+ */
+ public boolean isStarted() {
+ return services != null;
+ }
+
+ /**
+ * Start the tracker.
+ *
+ * @throws IllegalStateException if the tracker has already been started
+ */
+ public void start() {
+ if (services != null) {
+ throw new IllegalStateException();
+ }
+ synchronized (lock) {
+ pendingActions = new LinkedList<Runnable>();
+ config.addObservers(observer);
+ services = new HashSet<AxisService>();
+ }
+ for (Object o : config.getServices().values()) {
+ AxisService service = (AxisService)o;
+ if (service.isActive() && filter.matches(service)) {
+ serviceAdded(service);
+ }
+ }
+ while (true) {
+ Runnable action;
+ synchronized (lock) {
+ action = pendingActions.poll();
+ if (action == null) {
+ pendingActions = null;
+ break;
+ }
+ }
+ action.run();
+ }
+ }
+
+ void serviceAdded(AxisService service) {
+ // callListener may be false because the observer got an event for a service that
+ // was already in the initial list of services retrieved by AxisConfiguration#getServices.
+ boolean callListener;
+ synchronized (lock) {
+ callListener = services.add(service);
+ }
+ if (callListener) {
+ listener.serviceAdded(service);
+ }
+ }
+
+ void serviceRemoved(AxisService service) {
+ // callListener may be false because the observer invokes this method without applying the
+ // filter.
+ boolean callListener;
+ synchronized (lock) {
+ callListener = services.remove(service);
+ }
+ if (callListener) {
+ listener.serviceRemoved(service);
+ }
+ }
+
+ /**
+ * Stop the tracker.
+ *
+ * @throws IllegalStateException if the tracker is not started
+ */
+ public void stop() {
+ if (services == null) {
+ throw new IllegalStateException();
+ }
+ // TODO: This is very bad, but AxisConfiguration has no removeObserver method!
+ config.getObserversList().remove(observer);
+ for (AxisService service : services) {
+ listener.serviceRemoved(service);
+ }
+ services = null;
+ }
+}