/* * Copyright 2003-2004 The 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.Composition.Model.Default { using System; using Apache.Avalon.Meta; using Apache.Avalon.Composition.Data; /// A utility class that assists in the location of a model relative /// a supplied path. /// /// /// Avalon Development Team /// /// $Revision: 1.2 $ $Date: 2004/03/07 22:06:40 $ /// class DefaultContainmentModelAssemblyHelper { //------------------------------------------------------------------- // immutable state //------------------------------------------------------------------- private IContainmentContext m_context; private DefaultContainmentModel m_model; //------------------------------------------------------------------- // constructor //------------------------------------------------------------------- public DefaultContainmentModelAssemblyHelper(IContainmentContext context, DefaultContainmentModel model) { m_context = context; m_model = model; } //------------------------------------------------------------------- // implementation //------------------------------------------------------------------- /// Assemble a target model during which all deployment and runtime /// dependencies are assigned a provider model. /// /// /// the target model to be assembled /// /// the model requesting the assembly /// public virtual void assembleModel(IDeploymentModel model, System.Collections.IList subjects) { if (null == model) { throw new System.ArgumentNullException("model"); } if (null == subjects) { throw new System.ArgumentNullException("subjects"); } if (subjects.Contains(model)) { return ; } if (model.IsAssembled) { return ; } if (model is IComponentModel) { AssembleComponent((IComponentModel) model, subjects); } else { model.Assemble(subjects); } } private void AssembleComponent(IComponentModel model, System.Collections.IList subjects) { IModelRepository repository = m_context.ModelRepository; // // locate and assemble the component context handler // if (model.ContextModel != null) { IContextModel context = model.ContextModel; System.Type type = context.StrategyClass; if (!type.FullName.Equals(Apache.Avalon.Composition.Model.IContextModel_Fields.DEFAULT_STRATEGY_CLASSNAME)) { if (null == context.Provider) { try { subjects.Add(model); StageDescriptor stage = new StageDescriptor(type.FullName); IDeploymentModel provider = findExtensionProvider(repository, stage, subjects); context.Provider = provider; } catch (System.Exception e) { String error = "Unable to assemble component: " + model + " due to a component context phase handler establishment failure."; throw new AssemblyException(error, e); } finally { subjects.Remove(model); } } } } // // locate and resolve the stage providers // IStageModel[] stages = model.StageModels; for (int i = 0; i < stages.Length; i++) { IStageModel stage = stages[i]; if (null == stage.Provider) { try { subjects.Add(model); IDeploymentModel provider = findExtensionProvider(repository, stage, subjects); stage.Provider = provider; } catch (System.Exception e) { String error = "Unable to assemble component: " + model + " due to a component extension handler establishment failure."; throw new AssemblyException(error, e); } finally { subjects.Remove(model); } } } // // locate and resolve the service providers // IDependencyModel[] dependencies = model.DependencyModels; for (int i = 0; i < dependencies.Length; i++) { IDependencyModel dependency = dependencies[i]; if (null == dependency.Provider) { try { subjects.Add(model); IDeploymentModel provider = findDependencyProvider(repository, dependency, subjects); dependency.Provider = provider; } catch (System.Exception e) { String error = "Unable to assemble component: " + model + " due to a service provider establishment failure."; throw new AssemblyException(error, e); } finally { subjects.Remove(model); } } } } private IDeploymentModel findDependencyProvider(IModelRepository repository, IDependencyModel dependency, System.Collections.IList subjects) { String path = dependency.Path; if (null != (System.Object) path) { IDeploymentModel model = m_model.GetModel(path); if (null == model) { String error = "Could not locate a model at the address: [" + path + "] in " + this + "."; throw new AssemblyException(error); } assembleModel(model, subjects); return model; } else { return findDependencyProvider(repository, dependency.Dependency, subjects); } } private IDeploymentModel findDependencyProvider(IModelRepository repository, DependencyDescriptor dependency, System.Collections.IList subjects) { IDeploymentModel[] candidates = repository.GetCandidateProviders(dependency); IModelSelector selector = new DefaultModelSelector(); IDeploymentModel model = selector.Select(candidates, dependency); if (model != null) { assembleModel(model, subjects); return model; } // // otherwise, check for any packaged profiles that // we could use to construct the model // DeploymentProfile[] profiles = findDependencyProfiles(dependency); IProfileSelector profileSelector = new DefaultProfileSelector(); DeploymentProfile profile = profileSelector.Select(profiles, dependency); if (profile != null) { try { IDeploymentModel solution = m_model.CreateDeploymentModel(profile); assembleModel(solution, subjects); m_model.AddModel(solution); return solution; } catch (AssemblyException ae) { String error = "Nested assembly failure while attempting to construct model" + " for the profile: [" + profile + "] for the dependency: [" + dependency + "]."; throw new AssemblyException(error, ae); } catch (ModelException me) { String error = "Nested model failure while attempting to add model" + " for the profile: [" + profile + "] for the dependency: [" + dependency + "]."; throw new AssemblyException(error, me); } } else { String error = "Unable to locate a service provider for the dependency: [ " + dependency + "]."; throw new AssemblyException(error); } } private IDeploymentModel findExtensionProvider(IModelRepository repository, IStageModel stage, System.Collections.IList subjects) { String path = stage.Path; if (null != (System.Object) path) { IDeploymentModel model = m_model.GetModel(path); if (null == model) { String error = "Could not locate a model at the address: [" + path + "] in " + this + "."; throw new AssemblyException(error); } assembleModel(model, subjects); return model; } else { return findExtensionProvider(repository, stage.Stage, subjects); } } private IDeploymentModel findExtensionProvider(IModelRepository repository, StageDescriptor stage, System.Collections.IList subjects) { IDeploymentModel[] candidates = repository.GetCandidateProviders(stage); IModelSelector selector = new DefaultModelSelector(); IDeploymentModel model = selector.Select(candidates, stage); if (model != null) { assembleModel(model, subjects); return model; } // // otherwise, check for any packaged profiles that // we could use to construct the model // DeploymentProfile[] profiles = findExtensionProfiles(stage); IProfileSelector profileSelector = new DefaultProfileSelector(); DeploymentProfile profile = profileSelector.Select(profiles, stage); if (profile != null) { try { IDeploymentModel solution = m_model.CreateDeploymentModel(profile); assembleModel(solution, subjects); m_model.AddModel(solution); return solution; } catch (AssemblyException ae) { String error = "Nested assembly failure while attempting to construct model" + " for the extension profile: [" + profile + "] for the stage dependency: [" + stage + "]."; throw new AssemblyException(error, ae); } catch (ModelException me) { String error = "Nested model failure while attempting to add model" + " for the extension profile: [" + profile + "] for the stage dependency: [" + stage + "]."; throw new AssemblyException(error, me); } } else { String error = "Unable to locate a extension provider for the stage: [ " + stage + "]."; throw new AssemblyException(error); } } private DeploymentProfile[] findExtensionProfiles(StageDescriptor stage) { ITypeRepository repository = m_context.TypeLoaderModel.TypeRepository; TypeDescriptor[] types = repository.GetTypes(stage); try { return getProfiles(repository, types); } catch (TypeUnknownException tue) { // will not happen String error = "An irrational condition has occured."; throw new ModelRuntimeException(error, tue); } } private DeploymentProfile[] findDependencyProfiles(DependencyDescriptor dependency) { ITypeRepository repository = m_context.TypeLoaderModel.TypeRepository; TypeDescriptor[] types = repository.GetTypes(dependency); try { return getProfiles(repository, types); } catch (TypeUnknownException tue) { // will not happen String error = "An irrational condition has occured."; throw new ModelRuntimeException(error, tue); } } private DeploymentProfile[] getProfiles(ITypeRepository repository, TypeDescriptor[] types) { System.Collections.ArrayList list = new System.Collections.ArrayList(); for (int i = 0; i < types.Length; i++) { DeploymentProfile[] profiles = repository.GetProfiles(types[i]); for (int j = 0; j < profiles.Length; j++) { list.Add(profiles[j]); } } return (DeploymentProfile[]) list.ToArray( typeof(DeploymentProfile) ); } } }