/*
* Licensed 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.subsystem.core.internal;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map;
import org.apache.aries.subsystem.AriesSubsystem;
import org.eclipse.equinox.region.Region;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.subsystem.Subsystem;
import org.osgi.service.subsystem.SubsystemConstants;
public class SubsystemServiceRegistrar {
private final BundleContext context;
private final Map<Subsystem, ServiceRegistration<?>> map = new HashMap<Subsystem, ServiceRegistration<?>>();
public SubsystemServiceRegistrar(BundleContext context) {
if (context == null)
throw new NullPointerException("Missing required parameter: context");
this.context = context;
}
public void addRegion(BasicSubsystem subsystem, Region region) {
ServiceRegistration<?> registration;
Dictionary<String, Object> properties;
synchronized (this) {
registration = map.get(subsystem);
if (registration == null)
throw new IllegalStateException("Subsystem '" + subsystem + "' is not registered");
Collection<String> currentRegions = (Collection<String>)registration.getReference().getProperty(Constants.SubsystemServicePropertyRegions);
String regionName = region.getName();
if (currentRegions.contains(regionName))
return;
Collection<String> newRegions = new HashSet<String>(currentRegions.size() + 1);
newRegions.addAll(currentRegions);
newRegions.add(regionName);
properties = properties(subsystem);
properties.put(Constants.SubsystemServicePropertyRegions, Collections.unmodifiableCollection(newRegions));
}
registration.setProperties(properties);
}
public synchronized Subsystem getSubsystemService(BasicSubsystem subsystem) {
ServiceRegistration<?> registration = map.get(subsystem);
if (registration == null)
return null;
return (Subsystem)Activator.getInstance().getBundleContext().getService(registration.getReference());
}
public void register(BasicSubsystem child, BasicSubsystem parent) {
Dictionary<String, Object> properties;
synchronized (this) {
if (map.containsKey(child))
return;
map.put(child, null);
properties = properties(child, parent);
}
ServiceRegistration<?> registration = null;
try {
registration = context.registerService(
new String[] {Subsystem.class.getName(), AriesSubsystem.class.getName()},
child, properties);
}
finally {
synchronized (this) {
if (registration == null)
map.remove(child);
else
map.put(child, registration);
}
}
}
public void removeRegion(BasicSubsystem subsystem, Region region) {
ServiceRegistration<?> registration;
Dictionary<String, Object> properties;
synchronized (this) {
registration = map.get(subsystem);
if (registration == null)
return;
Collection<String> regions = (Collection<String>)registration.getReference().getProperty(Constants.SubsystemServicePropertyRegions);
String regionName = region.getName();
if (regions == null || !regions.contains(regionName))
return;
regions = new HashSet<String>(regions);
regions.remove(regionName);
properties = properties(subsystem);
properties.put(Constants.SubsystemServicePropertyRegions, Collections.unmodifiableCollection(regions));
}
registration.setProperties(properties);
}
public void unregister(Subsystem subsystem) {
ServiceRegistration<?> registration;
synchronized (this) {
registration = map.remove(subsystem);
if (registration == null)
throw new IllegalStateException("Subsystem '" + subsystem + "' is not registered");
}
registration.unregister();
}
public void update(BasicSubsystem subsystem) {
ServiceRegistration<?> registration;
Dictionary<String, Object> properties;
synchronized (this) {
registration = map.get(subsystem);
if (registration == null)
throw new IllegalStateException("Subsystem '" + subsystem + "' is not registered");
properties = properties(subsystem, registration);
}
registration.setProperties(properties);
}
private Dictionary<String, Object> properties(BasicSubsystem subsystem) {
Dictionary<String, Object> result = new Hashtable<String, Object>();
result.put(SubsystemConstants.SUBSYSTEM_ID_PROPERTY, subsystem.getSubsystemId());
result.put(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME_PROPERTY, subsystem.getSymbolicName());
result.put(SubsystemConstants.SUBSYSTEM_VERSION_PROPERTY, subsystem.getVersion());
result.put(SubsystemConstants.SUBSYSTEM_TYPE_PROPERTY, subsystem.getType());
result.put(SubsystemConstants.SUBSYSTEM_STATE_PROPERTY, subsystem.getState());
result.put(Constants.SubsystemServicePropertyRegions, Collections.singleton(subsystem.getRegionName()));
return result;
}
private Dictionary<String, Object> properties(BasicSubsystem child, BasicSubsystem parent) {
Dictionary<String, Object> result = properties(child);
if (parent == null)
return result;
Collection<String> currentRegions = (Collection<String>)result.get(Constants.SubsystemServicePropertyRegions);
Collection<String> newRegions = new HashSet<String>(currentRegions.size() + 1);
newRegions.addAll(currentRegions);
newRegions.add(parent.getRegion().getName());
result.put(Constants.SubsystemServicePropertyRegions, Collections.unmodifiableCollection(newRegions));
return result;
}
private Dictionary<String, Object> properties(BasicSubsystem subsystem, ServiceRegistration<?> registration) {
Dictionary<String, Object> result = properties(subsystem);
Collection<String> regions = (Collection<String>)registration.getReference().getProperty(Constants.SubsystemServicePropertyRegions);
if (regions == null)
return result;
result.put(Constants.SubsystemServicePropertyRegions, regions);
return result;
}
}