/*
* 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.subsystem.core.internal;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.aries.subsystem.AriesSubsystem;
import org.apache.aries.subsystem.core.capabilityset.CapabilitySetRepository;
import org.apache.aries.subsystem.core.repository.Repository;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
import org.osgi.util.tracker.BundleTrackerCustomizer;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
public class SystemRepository
implements
Repository,
BundleTrackerCustomizer<AtomicReference<BundleRevisionResource>>,
ServiceTrackerCustomizer<AriesSubsystem, BasicSubsystem> {
private final BundleContext bundleContext;
private final CapabilitySetRepository repository;
public SystemRepository(BundleContext bundleContext) {
this.bundleContext = bundleContext;
repository = new CapabilitySetRepository();
}
@Override
public AtomicReference<BundleRevisionResource> addingBundle(Bundle bundle, BundleEvent event) {
// The state mask must guarantee this will only be called when the bundle is in the INSTALLED state.
BundleRevision revision = bundle.adapt(BundleRevision.class);
BundleRevisionResource resource = new BundleRevisionResource(revision);
if (ThreadLocalSubsystem.get() == null) {
// This is an explicitly installed bundle. It must be prevented
// from resolving as part of adding it to the repository. Searching
// for service requirements and capabilities will result in a call
// to findEntries which will cause the framework to attempt a
// resolution.
ThreadLocalBundleRevision.set(revision);
try {
repository.addResource(resource);
}
finally {
ThreadLocalBundleRevision.remove();
}
}
else {
// If this is a bundle being installed as part of a subsystem
// installation, it is already protected.
repository.addResource(resource);
}
return new AtomicReference<BundleRevisionResource>(resource);
}
@Override
public BasicSubsystem addingService(ServiceReference<AriesSubsystem> reference) {
// Intentionally letting the ClassCastException propagate. Everything received should be a BasicSubsystem.
BasicSubsystem subsystem = (BasicSubsystem)bundleContext.getService(reference);
repository.addResource(subsystem);
return subsystem;
}
@Override
public Map<Requirement, Collection<Capability>> findProviders(Collection<? extends Requirement> requirements) {
return repository.findProviders(requirements);
}
@Override
public void modifiedBundle(Bundle bundle, BundleEvent event, AtomicReference<BundleRevisionResource> object) {
if (BundleEvent.UPDATED == event.getType()) {
BundleRevision revision = bundle.adapt(BundleRevision.class);
BundleRevisionResource resource = new BundleRevisionResource(revision);
repository.removeResource(object.getAndSet(resource));
repository.addResource(resource);
}
}
@Override
public void modifiedService(ServiceReference<AriesSubsystem> reference, BasicSubsystem service) {
// Nothing.
}
@Override
public void removedBundle(Bundle bundle, BundleEvent event, AtomicReference<BundleRevisionResource> object) {
// The state mask must guarantee this will only be called when the bundle is in the UNINSTALLED state.
repository.removeResource(object.get());
}
@Override
public void removedService(ServiceReference<AriesSubsystem> reference, BasicSubsystem service) {
repository.removeResource(service);
}
}