blob: a68215686654337e7835db0330bcc3ab28c3c379 [file] [log] [blame]
/*
* 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.axiom.locator;
import java.net.URL;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import org.apache.axiom.om.OMMetaFactory;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.util.tracker.BundleTrackerCustomizer;
final class OSGiOMMetaFactoryLocator extends PriorityBasedOMMetaFactoryLocator implements BundleTrackerCustomizer<List<RegisteredImplementation>> {
private final BundleContext apiBundleContext;
private final List<Implementation> implementations = new ArrayList<Implementation>();
OSGiOMMetaFactoryLocator(BundleContext apiBundleContext) {
this.apiBundleContext = apiBundleContext;
}
// Need to synchronize access because the implementations may be reloaded concurrently
@Override
public synchronized OMMetaFactory getOMMetaFactory(String feature) {
return super.getOMMetaFactory(feature);
}
@Override
public List<RegisteredImplementation> addingBundle(Bundle bundle, BundleEvent event) {
URL descriptorUrl = bundle.getEntry(ImplementationFactory.DESCRIPTOR_RESOURCE);
if (descriptorUrl != null) {
List<Implementation> discoveredImplementations = ImplementationFactory.parseDescriptor(new OSGiLoader(bundle), descriptorUrl);
List<RegisteredImplementation> registeredImplementations = new ArrayList<RegisteredImplementation>(discoveredImplementations.size());
synchronized (this) {
implementations.addAll(discoveredImplementations);
loadImplementations(implementations);
}
for (Implementation implementation : discoveredImplementations) {
List<ServiceRegistration<?>> registrations = new ArrayList<ServiceRegistration<?>>();
List<ServiceReference<?>> references = new ArrayList<ServiceReference<?>>();
for (Feature feature : implementation.getFeatures()) {
List<String> clazzes = new ArrayList<String>();
clazzes.add(OMMetaFactory.class.getName());
for (Class<?> extensionInterface : feature.getExtensionInterfaces()) {
clazzes.add(extensionInterface.getName());
}
Hashtable<String,Object> properties = new Hashtable<String,Object>();
properties.put("implementationName", implementation.getName());
properties.put("feature", feature.getName());
properties.put(Constants.SERVICE_RANKING, feature.getPriority());
ServiceRegistration<?> registration = bundle.getBundleContext().registerService(clazzes.toArray(new String[clazzes.size()]), implementation.getMetaFactory(), properties);
registrations.add(registration);
ServiceReference<?> reference = registration.getReference();
references.add(reference);
// Let the OSGi runtime know that the axiom-api bundle is using the service
apiBundleContext.getService(reference);
}
registeredImplementations.add(new RegisteredImplementation(implementation, registrations, references));
}
return registeredImplementations;
} else {
return null;
}
}
@Override
public void modifiedBundle(Bundle bundle, BundleEvent event, List<RegisteredImplementation> object) {
}
@Override
public void removedBundle(Bundle bundle, BundleEvent event, List<RegisteredImplementation> object) {
for (RegisteredImplementation registeredImplementation : object) {
for (ServiceReference<?> reference : registeredImplementation.getReferences()) {
apiBundleContext.ungetService(reference);
}
for (ServiceRegistration<?> registration : registeredImplementation.getRegistrations()) {
registration.unregister();
}
synchronized (this) {
implementations.remove(registeredImplementation.getImplementation());
}
}
synchronized (this) {
loadImplementations(implementations);
}
}
}