| /* |
| * 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); |
| } |
| } |
| } |