/**
* 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.cdi.container.internal.container;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.osgi.framework.Filter;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cdi.CdiEvent;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
public class Phase_Reference implements Phase {
public Phase_Reference(BootstrapContainer bc) {
_bc = bc;
}
@Override
public void close() {
if (_serviceTracker != null) {
_serviceTracker.close();
_serviceTracker = null;
}
else {
_lock.lock();
try {
if (_nextPhase != null) {
_nextPhase.close();
_nextPhase = null;
}
}
finally {
_lock.unlock();
}
}
}
@Override
public void open() {
if (_bc.hasReferences()) {
Filter filter = FilterBuilder.createReferenceFilter(_bc.getReferences());
_bc.fire(CdiEvent.Type.WAITING_FOR_SERVICES, filter.toString());
_serviceTracker = new ServiceTracker<>(_bc.getBundleContext(), filter, new ReferencePhaseCustomizer());
_serviceTracker.open();
}
_lock.lock();
try {
if ((_nextPhase == null) && dependenciesAreEmptyOrAllOptional()) {
_nextPhase = new Phase_Publish(_bc);
_nextPhase.open();
}
}
finally {
_lock.unlock();
}
}
private boolean dependenciesAreEmptyOrAllOptional() {
if (!_bc.hasReferences()) {
return true;
}
for (ReferenceDependency referenceDependency : _bc.getReferences()) {
if (referenceDependency.getMinCardinality() > 0) {
return false;
}
}
return true;
}
private final BootstrapContainer _bc;
private final Lock _lock = new ReentrantLock(true);
private Phase _nextPhase;
ServiceTracker<?, ?> _serviceTracker;
private class ReferencePhaseCustomizer implements ServiceTrackerCustomizer<Object, Object> {
@Override
public Object addingService(ServiceReference<Object> reference) {
_lock.lock();
try {
if (_nextPhase != null) {
return null;
}
boolean matches = false;
boolean resolved = true;
for (ReferenceDependency referenceDependency : _bc.getReferences()) {
if (referenceDependency.matches(reference)) {
referenceDependency.resolve(reference);
matches = true;
}
if (!referenceDependency.isResolved()) {
resolved = false;
}
}
if (!matches) {
return null;
}
if (resolved) {
_nextPhase = new Phase_Publish(_bc);
_nextPhase.open();
}
return new Object();
}
finally {
_lock.unlock();
}
}
@Override
public void modifiedService(ServiceReference<Object> reference, Object object) {
}
@Override
public void removedService(ServiceReference<Object> reference, Object object) {
_lock.lock();
try {
if (_nextPhase != null) {
_nextPhase.close();
_nextPhase = null;
_bc.fire(CdiEvent.Type.WAITING_FOR_SERVICES);
}
for (ReferenceDependency referenceDependency : _bc.getReferences()) {
if (referenceDependency.matches(reference)) {
referenceDependency.unresolve(reference);
}
}
}
finally {
_lock.unlock();
}
}
}
}