// Copyright 2004 Apache Software Foundation // // 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. namespace Apache.Avalon.Activation.Default { using System; using System.Collections; using Apache.Avalon.Framework; using Apache.Avalon.Composition.Model; /// /// Summary description for DefaultLookupManager. /// public class DefaultLookupManager : ILookupManager { //------------------------------------------------------------------- // immutable state //------------------------------------------------------------------- private IComponentModel m_model; private ILogger m_logger; /// /// A table of identity hashcode integers of established objects /// that map to the lookup key that was uased to establish the object. /// Used to track which model is providing an object when we /// handle release of objects. /// private Hashtable m_table = new Hashtable(); /// /// A table of dependency models keyed by lookup key. /// private Hashtable m_map; /// /// Construct a new ServiceManager. /// /// component model of the component that is to be services public DefaultLookupManager( IComponentModel model ) { if( model == null ) { throw new ArgumentNullException( "model" ); } m_model = model; m_logger = model.Logger; m_map = new Hashtable(); IDependencyModel[] dependencies = model.DependencyModels; foreach(IDependencyModel dependency in dependencies) { String key = dependency.Dependency.Key; m_map[ key ] = dependency; } } #region ILookupManager Members public object this[string role] { get { if( role == null ) { throw new ArgumentNullException( "role" ); } if( !Contains( role ) ) { String error = "Unknown key: " + role; throw new LookupException( role, error ); } // // locate the provider model that is prividing components // for this dependency // IDependencyModel dependency = (IDependencyModel) m_map[ role ]; IDeploymentModel provider = dependency.Provider; if( null == provider ) { String error = "service.error.null-provider " + role; throw new ApplicationException( error ); } // // get a proxy to the service from the provider // (note that it is up to a provider to determine if // a proxy if generated based on its service export // parameters) // try { Object instance = provider.Resolve(); // // otherwise we need to hold a reference linking the // object with the source provider // String id = "" + instance.GetHashCode(); m_table[ id ] = role; if( Logger.IsDebugEnabled ) { String message = "resolved service [" + id + "] for the role [" + role + "]."; Logger.Debug( message ); } return instance; } catch( Exception e ) { // // TODO: framework states that ServiceException is thrown // if the service is not found - and in this case that isn't // the issue - in effect we have a good key, but we simply // have not been able to go from key to instance - // should look into some more concrete subtypes of // ServiceException String error = "Unexpected runtime error while attempting to resolve service for key: " + role; throw new FatalServiceException( role, error, e ); } } } public void Release(object instance) { if( instance == null ) return; // // otherwise we need to locate the source ourselves // String id = "" + instance.GetHashCode(); String key = (String) m_table[ id ]; if( key == null ) { if( Logger.IsWarnEnabled ) { String warning = "Unrecognized object identity [" + id + "]. " + "Either this object was not provided by this service manager " + "or it has already been released."; Logger.Warn( warning ); } return; } IDependencyModel dependency = (IDependencyModel) m_map[ key ]; IDeploymentModel provider = dependency.Provider; if( provider == null ) { if( Logger.IsErrorEnabled ) { String error = "Unable to release component as no provider could be found for the key [" + key + "]."; Logger.Warn( error ); } return; } provider.Release( instance ); if( Logger.IsDebugEnabled ) { String message = "released service [" + id + "] from the key [" + key + "]."; Logger.Debug( message ); } m_table.Remove( id ); } public bool Contains(string role) { if( role == null ) { return false; } return m_map.Contains( role ); } #endregion private ILogger Logger { get { return m_logger; } } } }