/**
* 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.aries.jndi.tracker;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.naming.spi.InitialContextFactory;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.service.jndi.JNDIConstants;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
public class ServiceTrackerCustomizers
{
public static interface CachingServiceTracker extends ServiceTrackerCustomizer {
public ServiceReference find(String identifier);
}
private static abstract class BaseCachingServiceTracker implements CachingServiceTracker {
/** The cached references */
protected ConcurrentMap<String, ServiceReference> cache = new ConcurrentHashMap<String, ServiceReference>();
/** A list of service references that are being tracked */
protected List<ServiceReference> trackedReferences = new ArrayList<ServiceReference>();
public ServiceReference find(String identifier)
{
return cache.get(identifier);
}
public synchronized Object addingService(ServiceReference reference)
{
List<String> cacheKeys = getProperty(reference);
for (String key : cacheKeys) {
cache.putIfAbsent(key, reference);
}
trackedReferences.add(reference);
return reference;
}
protected abstract List<String> getProperty(ServiceReference reference);
public synchronized void removedService(ServiceReference reference, Object service)
{
trackedReferences.remove(reference);
List<String> keysToProcess = new ArrayList<String>(getProperty(reference));
refLoop: for (ServiceReference ref : trackedReferences) {
List<String> refInt = getProperty(ref);
for (String interfaceName : refInt) {
int index = keysToProcess.indexOf(interfaceName);
if (index >= 0) {
keysToProcess.remove(index);
if (cache.replace(interfaceName, reference, ref)) {
if (keysToProcess.isEmpty()) break refLoop;
}
}
}
}
for (String interfaceName : keysToProcess) {
cache.remove(interfaceName, reference);
}
}
public void modifiedService(ServiceReference reference, Object service) { }
}
public static final ServiceTrackerCustomizer LAZY = new ServiceTrackerCustomizer() {
public Object addingService(ServiceReference reference)
{
return reference;
}
public void modifiedService(ServiceReference reference, Object service) { }
public void removedService(ServiceReference reference, Object service) { }
};
public static final CachingServiceTracker ICF_CACHE = new BaseCachingServiceTracker() {
public List<String> getProperty(ServiceReference ref)
{
String[] interfaces = (String[]) ref.getProperty(Constants.OBJECTCLASS);
List<String> resultList = new ArrayList<String>();
for (String interfaceName : interfaces) {
if (!!!InitialContextFactory.class.getName().equals(interfaceName)) {
resultList.add(interfaceName);
}
}
return resultList;
}
};
// TODO we should probably cope with the url.scheme property changing.
public static final CachingServiceTracker URL_FACTORY_CACHE = new BaseCachingServiceTracker() {
protected List<String> getProperty(ServiceReference reference) {
Object scheme = reference.getProperty(JNDIConstants.JNDI_URLSCHEME);
List<String> result;
if (scheme instanceof String) {
result = new ArrayList<String>();
result.add((String) scheme);
} else if (scheme instanceof String[]) {
result = Arrays.asList((String[])scheme);
} else {
result = Collections.emptyList();
}
return result;
}
};
}