| /* |
| * 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.felix.scr.impl.manager; |
| |
| |
| import java.util.Comparator; |
| import java.util.Dictionary; |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.TreeMap; |
| import java.util.concurrent.CountDownLatch; |
| import java.util.concurrent.TimeUnit; |
| |
| import org.apache.felix.scr.impl.helper.ComponentServiceObjectsHelper; |
| import org.apache.felix.scr.impl.helper.ReadOnlyDictionary; |
| import org.apache.felix.scr.impl.inject.RefPair; |
| import org.apache.felix.scr.impl.inject.ScrComponentContext; |
| import org.apache.felix.scr.impl.logger.ComponentLogger; |
| import org.apache.felix.scr.impl.metadata.ComponentMetadata; |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.framework.ServiceReference; |
| import org.osgi.framework.ServiceRegistration; |
| import org.osgi.service.component.ComponentInstance; |
| import org.osgi.service.log.LogService; |
| |
| |
| /** |
| * Implementation for the ComponentContext interface |
| * |
| */ |
| public class ComponentContextImpl<S> implements ScrComponentContext { |
| |
| private final SingleComponentManager<S> m_componentManager; |
| |
| private final EdgeInfo[] edgeInfos; |
| |
| private final ComponentInstance<S> m_componentInstance = new ComponentInstanceImpl<>(this); |
| |
| private final Bundle m_usingBundle; |
| |
| private volatile ServiceRegistration<S> m_serviceRegistration; |
| |
| private volatile S m_implementationObject; |
| |
| private volatile boolean m_implementationAccessible; |
| |
| private final CountDownLatch accessibleLatch = new CountDownLatch(1); |
| |
| private final ComponentServiceObjectsHelper serviceObjectsHelper; |
| |
| /** Mapping of ref pairs to value bound */ |
| private Map<String, Map<RefPair<?, ?>, Object>> boundValues; |
| |
| public ComponentContextImpl( final SingleComponentManager<S> componentManager, |
| final Bundle usingBundle, |
| ServiceRegistration<S> serviceRegistration ) |
| { |
| m_componentManager = componentManager; |
| m_usingBundle = usingBundle; |
| m_serviceRegistration = serviceRegistration; |
| edgeInfos = new EdgeInfo[componentManager.getComponentMetadata().getDependencies().size()]; |
| for (int i = 0; i< edgeInfos.length; i++) |
| { |
| edgeInfos[i] = new EdgeInfo(); |
| } |
| this.serviceObjectsHelper = new ComponentServiceObjectsHelper(usingBundle.getBundleContext()); |
| } |
| |
| public void unsetServiceRegistration() |
| { |
| m_serviceRegistration = null; |
| } |
| |
| public void cleanup() |
| { |
| this.serviceObjectsHelper.cleanup(); |
| } |
| |
| @Override |
| public ComponentServiceObjectsHelper getComponentServiceObjectsHelper() |
| { |
| return this.serviceObjectsHelper; |
| } |
| |
| public void setImplementationObject(S implementationObject) |
| { |
| this.m_implementationObject = implementationObject; |
| } |
| |
| |
| public void setImplementationAccessible(boolean implementationAccessible) |
| { |
| this.m_implementationAccessible = implementationAccessible; |
| if (implementationAccessible) |
| { |
| accessibleLatch.countDown(); |
| } |
| } |
| |
| EdgeInfo getEdgeInfo(DependencyManager<S, ?> dm) |
| { |
| int index = dm.getIndex(); |
| return edgeInfos[index]; |
| } |
| |
| ServiceRegistration<S> getServiceRegistration() |
| { |
| return m_serviceRegistration; |
| } |
| |
| protected SingleComponentManager<S> getComponentManager() |
| { |
| return m_componentManager; |
| } |
| |
| public ComponentMetadata getComponentMetadata() |
| { |
| return m_componentManager.getComponentMetadata(); |
| } |
| |
| @Override |
| public final Dictionary<String, Object> getProperties() |
| { |
| // 112.12.3.5 The Dictionary is read-only and cannot be modified |
| return new ReadOnlyDictionary( m_componentManager.getProperties() ); |
| } |
| |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public Object locateService( String name ) |
| { |
| m_componentManager.obtainActivationReadLock( ); |
| try |
| { |
| DependencyManager<S, ?> dm = m_componentManager.getDependencyManager( name ); |
| return ( dm != null ) ? dm.getService(this) : null; |
| } |
| finally |
| { |
| m_componentManager.releaseActivationReadLock( ); |
| } |
| } |
| |
| |
| @SuppressWarnings({ "unchecked", "rawtypes" }) |
| @Override |
| public Object locateService( String name, ServiceReference ref ) |
| { |
| m_componentManager.obtainActivationReadLock( ); |
| try |
| { |
| DependencyManager<S, ?> dm = m_componentManager.getDependencyManager( name ); |
| return ( dm != null ) ? dm.getService( this, ref ) : null; |
| } |
| finally |
| { |
| m_componentManager.releaseActivationReadLock( ); |
| } |
| } |
| |
| |
| @Override |
| public Object[] locateServices( String name ) |
| { |
| m_componentManager.obtainActivationReadLock( ); |
| try |
| { |
| DependencyManager<S, ?> dm = m_componentManager.getDependencyManager( name ); |
| return ( dm != null ) ? dm.getServices(this) : null; |
| } |
| finally |
| { |
| m_componentManager.releaseActivationReadLock( ); |
| } |
| } |
| |
| |
| @Override |
| public BundleContext getBundleContext() |
| { |
| return m_componentManager.getBundleContext(); |
| } |
| |
| |
| @Override |
| public Bundle getUsingBundle() |
| { |
| return m_usingBundle; |
| } |
| |
| @Override |
| public ComponentLogger getLogger() |
| { |
| return this.m_componentManager.getLogger(); |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public ComponentInstance<S> getComponentInstance() |
| { |
| return m_componentInstance; |
| } |
| |
| |
| @Override |
| public void enableComponent( String name ) |
| { |
| m_componentManager.getActivator().enableComponent( name ); |
| } |
| |
| |
| @Override |
| public void disableComponent( String name ) |
| { |
| m_componentManager.getActivator().disableComponent( name ); |
| } |
| |
| |
| @Override |
| public ServiceReference<S> getServiceReference() |
| { |
| return m_serviceRegistration == null? null: m_serviceRegistration.getReference(); |
| } |
| |
| |
| //---------- Speculative MutableProperties interface ------------------------------ |
| |
| @Override |
| public void setServiceProperties(Dictionary<String, ?> properties) |
| { |
| getComponentManager().setServiceProperties(properties ); |
| } |
| |
| //---------- ComponentInstance interface support ------------------------------ |
| |
| S getImplementationObject( boolean requireAccessible ) |
| { |
| if ( !requireAccessible || m_implementationAccessible ) |
| { |
| return m_implementationObject; |
| } |
| try |
| { |
| if (accessibleLatch.await( m_componentManager.getLockTimeout(), TimeUnit.MILLISECONDS ) && m_implementationAccessible) |
| { |
| return m_implementationObject; |
| } |
| } |
| catch ( InterruptedException e ) |
| { |
| try |
| { |
| if (accessibleLatch.await( m_componentManager.getLockTimeout(), TimeUnit.MILLISECONDS ) && m_implementationAccessible) |
| { |
| return m_implementationObject; |
| } |
| } |
| catch ( InterruptedException e1 ) |
| { |
| m_componentManager.getLogger().log( LogService.LOG_INFO, "Interrupted twice waiting for implementation object to become accessible", e1 ); |
| } |
| Thread.currentThread().interrupt(); |
| return null; |
| } |
| return null; |
| } |
| |
| private static class ComponentInstanceImpl<S> implements ComponentInstance<S> |
| { |
| private final ComponentContextImpl<S> m_componentContext; |
| |
| private ComponentInstanceImpl(ComponentContextImpl<S> m_componentContext) |
| { |
| this.m_componentContext = m_componentContext; |
| } |
| |
| |
| @Override |
| public S getInstance() |
| { |
| return m_componentContext.getImplementationObject(true); |
| } |
| |
| |
| @Override |
| public void dispose() |
| { |
| m_componentContext.getComponentManager().dispose(); |
| } |
| |
| } |
| |
| @Override |
| public synchronized Map<RefPair<?, ?>, Object> getBoundValues(final String key) |
| { |
| if ( this.boundValues == null ) |
| { |
| this.boundValues = new HashMap<>(); |
| } |
| Map<RefPair<?, ?>, Object> map = this.boundValues.get(key); |
| if ( map == null ) |
| { |
| map = createNewFieldHandlerMap(); |
| this.boundValues.put(key, map); |
| } |
| return map; |
| } |
| |
| private Map<RefPair<?, ?>, Object> createNewFieldHandlerMap() |
| { |
| return new TreeMap<>( |
| new Comparator<RefPair<?, ?>>() |
| { |
| |
| @Override |
| public int compare(final RefPair<?, ?> o1, final RefPair<?, ?> o2) |
| { |
| return o1.getRef().compareTo(o2.getRef()); |
| } |
| }); |
| } |
| } |