You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gn...@apache.org on 2014/03/24 17:32:03 UTC
[05/24] git commit: [KARAF-2845] Move SingleServiceTracker to util
[KARAF-2845] Move SingleServiceTracker to util
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/e7f67746
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/e7f67746
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/e7f67746
Branch: refs/heads/master
Commit: e7f677469bec4cf253a82ef7756ed551a68e85c9
Parents: a0f482c
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Fri Mar 21 17:55:29 2014 +0100
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Mon Mar 24 17:30:12 2014 +0100
----------------------------------------------------------------------
region/persist/pom.xml | 15 +-
.../region/persist/internal/Activator.java | 2 +-
.../internal/util/SingleServiceTracker.java | 171 -------------------
shell/core/pom.xml | 1 +
.../osgi/secured/SecuredSessionFactoryImpl.java | 1 +
.../osgi/secured/SingleServiceTracker.java | 171 -------------------
shell/ssh/pom.xml | 3 +-
.../org/apache/karaf/shell/ssh/Activator.java | 2 +-
.../shell/ssh/util/SingleServiceTracker.java | 171 -------------------
.../util/tracker/SingleServiceTracker.java | 171 +++++++++++++++++++
10 files changed, 190 insertions(+), 518 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/e7f67746/region/persist/pom.xml
----------------------------------------------------------------------
diff --git a/region/persist/pom.xml b/region/persist/pom.xml
index 1ae0793..6eaf68b 100644
--- a/region/persist/pom.xml
+++ b/region/persist/pom.xml
@@ -56,6 +56,12 @@
</dependency>
<dependency>
+ <groupId>org.apache.karaf</groupId>
+ <artifactId>org.apache.karaf.util</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
<scope>provided</scope>
@@ -107,8 +113,13 @@
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
- <Bundle-Activator>org.apache.karaf.region.persist.internal.Activator</Bundle-Activator>
- <Export-Package>org.apache.karaf.region.persist;version=${project.version};-split-package:=merge-first</Export-Package>
+ <Bundle-Activator>
+ org.apache.karaf.region.persist.internal.Activator
+ </Bundle-Activator>
+ <Private-Package>
+ org.apache.karaf.region.persist.internal.*,
+ org.apache.karaf.util.tracker
+ </Private-Package>
</instructions>
</configuration>
</plugin>
http://git-wip-us.apache.org/repos/asf/karaf/blob/e7f67746/region/persist/src/main/java/org/apache/karaf/region/persist/internal/Activator.java
----------------------------------------------------------------------
diff --git a/region/persist/src/main/java/org/apache/karaf/region/persist/internal/Activator.java b/region/persist/src/main/java/org/apache/karaf/region/persist/internal/Activator.java
index e6ab85b..4705818 100644
--- a/region/persist/src/main/java/org/apache/karaf/region/persist/internal/Activator.java
+++ b/region/persist/src/main/java/org/apache/karaf/region/persist/internal/Activator.java
@@ -23,7 +23,7 @@ package org.apache.karaf.region.persist.internal;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.karaf.region.persist.RegionsPersistence;
-import org.apache.karaf.region.persist.internal.util.SingleServiceTracker;
+import org.apache.karaf.util.tracker.SingleServiceTracker;
import org.eclipse.equinox.region.RegionDigraph;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
http://git-wip-us.apache.org/repos/asf/karaf/blob/e7f67746/region/persist/src/main/java/org/apache/karaf/region/persist/internal/util/SingleServiceTracker.java
----------------------------------------------------------------------
diff --git a/region/persist/src/main/java/org/apache/karaf/region/persist/internal/util/SingleServiceTracker.java b/region/persist/src/main/java/org/apache/karaf/region/persist/internal/util/SingleServiceTracker.java
deleted file mode 100644
index 16f554f..0000000
--- a/region/persist/src/main/java/org/apache/karaf/region/persist/internal/util/SingleServiceTracker.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * 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.karaf.region.persist.internal.util;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicReference;
-
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.Filter;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceEvent;
-import org.osgi.framework.ServiceListener;
-import org.osgi.framework.ServiceReference;
-
-//This is from aries util
-public final class SingleServiceTracker<T> {
- public static interface SingleServiceListener {
- public void serviceFound();
-
- public void serviceLost();
-
- public void serviceReplaced();
- }
-
- private final BundleContext ctx;
- private final String className;
- private final AtomicReference<T> service = new AtomicReference<T>();
- private final AtomicReference<ServiceReference> ref = new AtomicReference<ServiceReference>();
- private final AtomicBoolean open = new AtomicBoolean(false);
- private final SingleServiceListener serviceListener;
- private String filterString;
- private Filter filter;
-
- private final ServiceListener listener = new ServiceListener() {
- public void serviceChanged(ServiceEvent event) {
- if (open.get()) {
- if (event.getType() == ServiceEvent.UNREGISTERING) {
- ServiceReference deadRef = event.getServiceReference();
- if (deadRef.equals(ref.get())) {
- findMatchingReference(deadRef);
- }
- } else if (event.getType() == ServiceEvent.REGISTERED && ref.get() == null) {
- findMatchingReference(null);
- }
- }
- }
- };
-
- public SingleServiceTracker(BundleContext context, Class<T> clazz, SingleServiceListener sl) {
- ctx = context;
- this.className = clazz.getName();
- serviceListener = sl;
- }
-
- public SingleServiceTracker(BundleContext context, Class<T> clazz, String filterString, SingleServiceListener sl) throws InvalidSyntaxException {
- this(context, clazz, sl);
- this.filterString = filterString;
- if (filterString != null) filter = context.createFilter(filterString);
- }
-
- public T getService() {
- return service.get();
- }
-
- public ServiceReference getServiceReference() {
- return ref.get();
- }
-
- public void open() {
- if (open.compareAndSet(false, true)) {
- try {
- String filterString = '(' + Constants.OBJECTCLASS + '=' + className + ')';
- if (filter != null) filterString = "(&" + filterString + filter + ')';
- ctx.addServiceListener(listener, filterString);
- findMatchingReference(null);
- } catch (InvalidSyntaxException e) {
- // this can never happen. (famous last words :)
- }
- }
- }
-
- private void findMatchingReference(ServiceReference original) {
- boolean clear = true;
- ServiceReference ref = ctx.getServiceReference(className);
- if (ref != null && (filter == null || filter.match(ref))) {
- @SuppressWarnings("unchecked")
- T service = (T) ctx.getService(ref);
- if (service != null) {
- clear = false;
-
- // We do the unget out of the lock so we don't exit this class while holding a lock.
- if (!!!update(original, ref, service)) {
- ctx.ungetService(ref);
- }
- }
- } else if (original == null) {
- clear = false;
- }
-
- if (clear) {
- update(original, null, null);
- }
- }
-
- private boolean update(ServiceReference deadRef, ServiceReference newRef, T service) {
- boolean result = false;
- int foundLostReplaced = -1;
-
- // Make sure we don't try to get a lock on null
- Object lock;
-
- // we have to choose our lock.
- if (newRef != null) lock = newRef;
- else if (deadRef != null) lock = deadRef;
- else lock = this;
-
- // This lock is here to ensure that no two threads can set the ref and service
- // at the same time.
- synchronized (lock) {
- if (open.get()) {
- result = this.ref.compareAndSet(deadRef, newRef);
- if (result) {
- this.service.set(service);
-
- if (deadRef == null && newRef != null) foundLostReplaced = 0;
- if (deadRef != null && newRef == null) foundLostReplaced = 1;
- if (deadRef != null && newRef != null) foundLostReplaced = 2;
- }
- }
- }
-
- if (serviceListener != null) {
- if (foundLostReplaced == 0) serviceListener.serviceFound();
- else if (foundLostReplaced == 1) serviceListener.serviceLost();
- else if (foundLostReplaced == 2) serviceListener.serviceReplaced();
- }
-
- return result;
- }
-
- public void close() {
- if (open.compareAndSet(true, false)) {
- ctx.removeServiceListener(listener);
-
- synchronized (this) {
- ServiceReference deadRef = ref.getAndSet(null);
- service.set(null);
- if (deadRef != null) ctx.ungetService(deadRef);
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/e7f67746/shell/core/pom.xml
----------------------------------------------------------------------
diff --git a/shell/core/pom.xml b/shell/core/pom.xml
index 47c1d34..c45f473 100644
--- a/shell/core/pom.xml
+++ b/shell/core/pom.xml
@@ -154,6 +154,7 @@
<Private-Package>
org.apache.karaf.service.guard.tools,
org.apache.karaf.shell.impl.*,
+ org.apache.karaf.util.tracker,
org.apache.felix.utils.properties,
org.apache.felix.utils.extender,
org.apache.felix.utils.manifest,
http://git-wip-us.apache.org/repos/asf/karaf/blob/e7f67746/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredSessionFactoryImpl.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredSessionFactoryImpl.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredSessionFactoryImpl.java
index 567575d..6c4048a 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredSessionFactoryImpl.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredSessionFactoryImpl.java
@@ -37,6 +37,7 @@ import org.apache.karaf.service.guard.tools.ACLConfigurationParser;
import org.apache.karaf.shell.api.console.Command;
import org.apache.karaf.shell.api.console.Session;
import org.apache.karaf.shell.impl.console.SessionFactoryImpl;
+import org.apache.karaf.util.tracker.SingleServiceTracker;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceRegistration;
http://git-wip-us.apache.org/repos/asf/karaf/blob/e7f67746/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SingleServiceTracker.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SingleServiceTracker.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SingleServiceTracker.java
deleted file mode 100644
index fb57ee1..0000000
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SingleServiceTracker.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * 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.karaf.shell.impl.console.osgi.secured;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicReference;
-
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.Filter;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceEvent;
-import org.osgi.framework.ServiceListener;
-import org.osgi.framework.ServiceReference;
-
-//This is from aries util
-public final class SingleServiceTracker<T> {
- public static interface SingleServiceListener {
- public void serviceFound();
-
- public void serviceLost();
-
- public void serviceReplaced();
- }
-
- private final BundleContext ctx;
- private final String className;
- private final AtomicReference<T> service = new AtomicReference<T>();
- private final AtomicReference<ServiceReference> ref = new AtomicReference<ServiceReference>();
- private final AtomicBoolean open = new AtomicBoolean(false);
- private final SingleServiceListener serviceListener;
- private String filterString;
- private Filter filter;
-
- private final ServiceListener listener = new ServiceListener() {
- public void serviceChanged(ServiceEvent event) {
- if (open.get()) {
- if (event.getType() == ServiceEvent.UNREGISTERING) {
- ServiceReference deadRef = event.getServiceReference();
- if (deadRef.equals(ref.get())) {
- findMatchingReference(deadRef);
- }
- } else if (event.getType() == ServiceEvent.REGISTERED && ref.get() == null) {
- findMatchingReference(null);
- }
- }
- }
- };
-
- public SingleServiceTracker(BundleContext context, Class<T> clazz, SingleServiceListener sl) {
- ctx = context;
- this.className = clazz.getName();
- serviceListener = sl;
- }
-
- public SingleServiceTracker(BundleContext context, Class<T> clazz, String filterString, SingleServiceListener sl) throws InvalidSyntaxException {
- this(context, clazz, sl);
- this.filterString = filterString;
- if (filterString != null) filter = context.createFilter(filterString);
- }
-
- public T getService() {
- return service.get();
- }
-
- public ServiceReference getServiceReference() {
- return ref.get();
- }
-
- public void open() {
- if (open.compareAndSet(false, true)) {
- try {
- String filterString = '(' + Constants.OBJECTCLASS + '=' + className + ')';
- if (filter != null) filterString = "(&" + filterString + filter + ')';
- ctx.addServiceListener(listener, filterString);
- findMatchingReference(null);
- } catch (InvalidSyntaxException e) {
- // this can never happen. (famous last words :)
- }
- }
- }
-
- private void findMatchingReference(ServiceReference original) {
- boolean clear = true;
- ServiceReference ref = ctx.getServiceReference(className);
- if (ref != null && (filter == null || filter.match(ref))) {
- @SuppressWarnings("unchecked")
- T service = (T) ctx.getService(ref);
- if (service != null) {
- clear = false;
-
- // We do the unget out of the lock so we don't exit this class while holding a lock.
- if (!!!update(original, ref, service)) {
- ctx.ungetService(ref);
- }
- }
- } else if (original == null) {
- clear = false;
- }
-
- if (clear) {
- update(original, null, null);
- }
- }
-
- private boolean update(ServiceReference deadRef, ServiceReference newRef, T service) {
- boolean result = false;
- int foundLostReplaced = -1;
-
- // Make sure we don't try to get a lock on null
- Object lock;
-
- // we have to choose our lock.
- if (newRef != null) lock = newRef;
- else if (deadRef != null) lock = deadRef;
- else lock = this;
-
- // This lock is here to ensure that no two threads can set the ref and service
- // at the same time.
- synchronized (lock) {
- if (open.get()) {
- result = this.ref.compareAndSet(deadRef, newRef);
- if (result) {
- this.service.set(service);
-
- if (deadRef == null && newRef != null) foundLostReplaced = 0;
- if (deadRef != null && newRef == null) foundLostReplaced = 1;
- if (deadRef != null && newRef != null) foundLostReplaced = 2;
- }
- }
- }
-
- if (serviceListener != null) {
- if (foundLostReplaced == 0) serviceListener.serviceFound();
- else if (foundLostReplaced == 1) serviceListener.serviceLost();
- else if (foundLostReplaced == 2) serviceListener.serviceReplaced();
- }
-
- return result;
- }
-
- public void close() {
- if (open.compareAndSet(true, false)) {
- ctx.removeServiceListener(listener);
-
- synchronized (this) {
- ServiceReference deadRef = ref.getAndSet(null);
- service.set(null);
- if (deadRef != null) ctx.ungetService(deadRef);
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/e7f67746/shell/ssh/pom.xml
----------------------------------------------------------------------
diff --git a/shell/ssh/pom.xml b/shell/ssh/pom.xml
index 84135eb..cffaa0b 100644
--- a/shell/ssh/pom.xml
+++ b/shell/ssh/pom.xml
@@ -104,7 +104,8 @@
*
</Import-Package>
<Private-Package>
- org.apache.karaf.util
+ org.apache.karaf.util,
+ org.apache.karaf.util.tracker
</Private-Package>
<Bundle-Activator>org.apache.karaf.shell.ssh.Activator</Bundle-Activator>
</instructions>
http://git-wip-us.apache.org/repos/asf/karaf/blob/e7f67746/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/Activator.java
----------------------------------------------------------------------
diff --git a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/Activator.java b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/Activator.java
index 575c871..af5fd54 100644
--- a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/Activator.java
+++ b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/Activator.java
@@ -29,9 +29,9 @@ import java.util.concurrent.Callable;
import java.util.concurrent.CopyOnWriteArrayList;
import org.apache.karaf.shell.api.action.lifecycle.Manager;
-import org.apache.karaf.shell.ssh.util.SingleServiceTracker;
import org.apache.karaf.shell.api.console.Session;
import org.apache.karaf.shell.api.console.SessionFactory;
+import org.apache.karaf.util.tracker.SingleServiceTracker;
import org.apache.sshd.SshServer;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.server.command.ScpCommandFactory;
http://git-wip-us.apache.org/repos/asf/karaf/blob/e7f67746/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/util/SingleServiceTracker.java
----------------------------------------------------------------------
diff --git a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/util/SingleServiceTracker.java b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/util/SingleServiceTracker.java
deleted file mode 100644
index c883dc0..0000000
--- a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/util/SingleServiceTracker.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * 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.karaf.shell.ssh.util;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicReference;
-
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.Filter;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceEvent;
-import org.osgi.framework.ServiceListener;
-import org.osgi.framework.ServiceReference;
-
-//This is from aries util
-public final class SingleServiceTracker<T> {
- public static interface SingleServiceListener {
- public void serviceFound();
-
- public void serviceLost();
-
- public void serviceReplaced();
- }
-
- private final BundleContext ctx;
- private final String className;
- private final AtomicReference<T> service = new AtomicReference<T>();
- private final AtomicReference<ServiceReference> ref = new AtomicReference<ServiceReference>();
- private final AtomicBoolean open = new AtomicBoolean(false);
- private final SingleServiceListener serviceListener;
- private String filterString;
- private Filter filter;
-
- private final ServiceListener listener = new ServiceListener() {
- public void serviceChanged(ServiceEvent event) {
- if (open.get()) {
- if (event.getType() == ServiceEvent.UNREGISTERING) {
- ServiceReference deadRef = event.getServiceReference();
- if (deadRef.equals(ref.get())) {
- findMatchingReference(deadRef);
- }
- } else if (event.getType() == ServiceEvent.REGISTERED && ref.get() == null) {
- findMatchingReference(null);
- }
- }
- }
- };
-
- public SingleServiceTracker(BundleContext context, Class<T> clazz, SingleServiceListener sl) {
- ctx = context;
- this.className = clazz.getName();
- serviceListener = sl;
- }
-
- public SingleServiceTracker(BundleContext context, Class<T> clazz, String filterString, SingleServiceListener sl) throws InvalidSyntaxException {
- this(context, clazz, sl);
- this.filterString = filterString;
- if (filterString != null) filter = context.createFilter(filterString);
- }
-
- public T getService() {
- return service.get();
- }
-
- public ServiceReference getServiceReference() {
- return ref.get();
- }
-
- public void open() {
- if (open.compareAndSet(false, true)) {
- try {
- String filterString = '(' + Constants.OBJECTCLASS + '=' + className + ')';
- if (filter != null) filterString = "(&" + filterString + filter + ')';
- ctx.addServiceListener(listener, filterString);
- findMatchingReference(null);
- } catch (InvalidSyntaxException e) {
- // this can never happen. (famous last words :)
- }
- }
- }
-
- private void findMatchingReference(ServiceReference original) {
- boolean clear = true;
- ServiceReference ref = ctx.getServiceReference(className);
- if (ref != null && (filter == null || filter.match(ref))) {
- @SuppressWarnings("unchecked")
- T service = (T) ctx.getService(ref);
- if (service != null) {
- clear = false;
-
- // We do the unget out of the lock so we don't exit this class while holding a lock.
- if (!!!update(original, ref, service)) {
- ctx.ungetService(ref);
- }
- }
- } else if (original == null) {
- clear = false;
- }
-
- if (clear) {
- update(original, null, null);
- }
- }
-
- private boolean update(ServiceReference deadRef, ServiceReference newRef, T service) {
- boolean result = false;
- int foundLostReplaced = -1;
-
- // Make sure we don't try to get a lock on null
- Object lock;
-
- // we have to choose our lock.
- if (newRef != null) lock = newRef;
- else if (deadRef != null) lock = deadRef;
- else lock = this;
-
- // This lock is here to ensure that no two threads can set the ref and service
- // at the same time.
- synchronized (lock) {
- if (open.get()) {
- result = this.ref.compareAndSet(deadRef, newRef);
- if (result) {
- this.service.set(service);
-
- if (deadRef == null && newRef != null) foundLostReplaced = 0;
- if (deadRef != null && newRef == null) foundLostReplaced = 1;
- if (deadRef != null && newRef != null) foundLostReplaced = 2;
- }
- }
- }
-
- if (serviceListener != null) {
- if (foundLostReplaced == 0) serviceListener.serviceFound();
- else if (foundLostReplaced == 1) serviceListener.serviceLost();
- else if (foundLostReplaced == 2) serviceListener.serviceReplaced();
- }
-
- return result;
- }
-
- public void close() {
- if (open.compareAndSet(true, false)) {
- ctx.removeServiceListener(listener);
-
- synchronized (this) {
- ServiceReference deadRef = ref.getAndSet(null);
- service.set(null);
- if (deadRef != null) ctx.ungetService(deadRef);
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/e7f67746/util/src/main/java/org/apache/karaf/util/tracker/SingleServiceTracker.java
----------------------------------------------------------------------
diff --git a/util/src/main/java/org/apache/karaf/util/tracker/SingleServiceTracker.java b/util/src/main/java/org/apache/karaf/util/tracker/SingleServiceTracker.java
new file mode 100644
index 0000000..c96e73a
--- /dev/null
+++ b/util/src/main/java/org/apache/karaf/util/tracker/SingleServiceTracker.java
@@ -0,0 +1,171 @@
+/*
+ * 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.karaf.util.tracker;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+
+//This is from aries util
+public final class SingleServiceTracker<T> {
+ public static interface SingleServiceListener {
+ public void serviceFound();
+
+ public void serviceLost();
+
+ public void serviceReplaced();
+ }
+
+ private final BundleContext ctx;
+ private final String className;
+ private final AtomicReference<T> service = new AtomicReference<T>();
+ private final AtomicReference<ServiceReference> ref = new AtomicReference<ServiceReference>();
+ private final AtomicBoolean open = new AtomicBoolean(false);
+ private final SingleServiceListener serviceListener;
+ private String filterString;
+ private Filter filter;
+
+ private final ServiceListener listener = new ServiceListener() {
+ public void serviceChanged(ServiceEvent event) {
+ if (open.get()) {
+ if (event.getType() == ServiceEvent.UNREGISTERING) {
+ ServiceReference deadRef = event.getServiceReference();
+ if (deadRef.equals(ref.get())) {
+ findMatchingReference(deadRef);
+ }
+ } else if (event.getType() == ServiceEvent.REGISTERED && ref.get() == null) {
+ findMatchingReference(null);
+ }
+ }
+ }
+ };
+
+ public SingleServiceTracker(BundleContext context, Class<T> clazz, SingleServiceListener sl) {
+ ctx = context;
+ this.className = clazz.getName();
+ serviceListener = sl;
+ }
+
+ public SingleServiceTracker(BundleContext context, Class<T> clazz, String filterString, SingleServiceListener sl) throws InvalidSyntaxException {
+ this(context, clazz, sl);
+ this.filterString = filterString;
+ if (filterString != null) filter = context.createFilter(filterString);
+ }
+
+ public T getService() {
+ return service.get();
+ }
+
+ public ServiceReference getServiceReference() {
+ return ref.get();
+ }
+
+ public void open() {
+ if (open.compareAndSet(false, true)) {
+ try {
+ String filterString = '(' + Constants.OBJECTCLASS + '=' + className + ')';
+ if (filter != null) filterString = "(&" + filterString + filter + ')';
+ ctx.addServiceListener(listener, filterString);
+ findMatchingReference(null);
+ } catch (InvalidSyntaxException e) {
+ // this can never happen. (famous last words :)
+ }
+ }
+ }
+
+ private void findMatchingReference(ServiceReference original) {
+ boolean clear = true;
+ ServiceReference ref = ctx.getServiceReference(className);
+ if (ref != null && (filter == null || filter.match(ref))) {
+ @SuppressWarnings("unchecked")
+ T service = (T) ctx.getService(ref);
+ if (service != null) {
+ clear = false;
+
+ // We do the unget out of the lock so we don't exit this class while holding a lock.
+ if (!!!update(original, ref, service)) {
+ ctx.ungetService(ref);
+ }
+ }
+ } else if (original == null) {
+ clear = false;
+ }
+
+ if (clear) {
+ update(original, null, null);
+ }
+ }
+
+ private boolean update(ServiceReference deadRef, ServiceReference newRef, T service) {
+ boolean result = false;
+ int foundLostReplaced = -1;
+
+ // Make sure we don't try to get a lock on null
+ Object lock;
+
+ // we have to choose our lock.
+ if (newRef != null) lock = newRef;
+ else if (deadRef != null) lock = deadRef;
+ else lock = this;
+
+ // This lock is here to ensure that no two threads can set the ref and service
+ // at the same time.
+ synchronized (lock) {
+ if (open.get()) {
+ result = this.ref.compareAndSet(deadRef, newRef);
+ if (result) {
+ this.service.set(service);
+
+ if (deadRef == null && newRef != null) foundLostReplaced = 0;
+ if (deadRef != null && newRef == null) foundLostReplaced = 1;
+ if (deadRef != null && newRef != null) foundLostReplaced = 2;
+ }
+ }
+ }
+
+ if (serviceListener != null) {
+ if (foundLostReplaced == 0) serviceListener.serviceFound();
+ else if (foundLostReplaced == 1) serviceListener.serviceLost();
+ else if (foundLostReplaced == 2) serviceListener.serviceReplaced();
+ }
+
+ return result;
+ }
+
+ public void close() {
+ if (open.compareAndSet(true, false)) {
+ ctx.removeServiceListener(listener);
+
+ synchronized (this) {
+ ServiceReference deadRef = ref.getAndSet(null);
+ service.set(null);
+ if (deadRef != null) ctx.ungetService(deadRef);
+ }
+ }
+ }
+}