/** * Deployment model defintion. * * @author <a href="mailto:[email protected]">Avalon Development Team</a> * @version $Id: DefaultComponentModel.java 31079 2004-08-01 17:04:08Z niclas $ */ public class DefaultComponentModel extends DefaultDeploymentModel implements ComponentModel { // -------------------------------------------------------------- // static // -------------------------------------------------------------- private static final Resources REZ = ResourceManager.getPackageResources(DefaultComponentModel.class); private static final String CONTEXTUALIZABLE = "org.apache.avalon.framework.context.Contextualizable"; private static final Configuration EMPTY_CONFIGURATION = new DefaultConfiguration("configuration", ComponentModel.class.getName()); // -------------------------------------------------------------- // immutable state // -------------------------------------------------------------- private final ComponentContext m_context; private final ContextModel m_contextModel; private final DependencyModel[] m_dependencies; private final StageModel[] m_stages; private final DefaultState m_assembly = new DefaultState(); // -------------------------------------------------------------- // mutable state // -------------------------------------------------------------- private Configuration m_config; private Parameters m_parameters; private boolean m_activation; private int m_collection; // -------------------------------------------------------------- // constructor // -------------------------------------------------------------- /** * Creation of a new deployment model. * * @param context the deployment context */ public DefaultComponentModel(ComponentContext context, SecurityModel security) throws ModelException { super(context, security); m_context = context; m_activation = getDefaultActivationPolicy(); setCollectionPolicy(m_context.getComponentProfile().getCollectionPolicy()); ClassLoader classLoader = m_context.getClassLoader(); if (isConfigurable()) { final Configuration defaults = m_context.getType().getConfiguration(); final Configuration explicit = m_context.getComponentProfile().getConfiguration(); final Configuration consolidated = consolidateConfigurations(explicit, defaults); if (consolidated != null) { m_config = consolidated; } else { m_config = EMPTY_CONFIGURATION; } } if (isParameterizable()) { Parameters staticDefaults = m_context.getType().getParameters(); final Parameters parameters = m_context.getComponentProfile().getParameters(); if (parameters != null) { if (null == staticDefaults) { m_parameters = parameters; } else { m_parameters = new Parameters(); m_parameters.merge(staticDefaults); m_parameters.merge(parameters); } } else { if (null == staticDefaults) { m_parameters = Parameters.EMPTY_PARAMETERS; } else { m_parameters = staticDefaults; } } } final ContextDescriptor contextDescriptor = m_context.getType().getContext(); final ContextDirective contextDirective = m_context.getComponentProfile().getContext(); final Logger log = getLogger().getChildLogger("context"); m_contextModel = new DefaultContextModel(log, contextDescriptor, contextDirective, context); // // create the dependency models for subsequent assembly // management // DependencyDescriptor[] dependencies = m_context.getType().getDependencies(); m_dependencies = new DefaultDependencyModel[dependencies.length]; for (int i = 0; i < dependencies.length; i++) { DependencyDescriptor descriptor = dependencies[i]; DependencyDirective directive = context.getComponentProfile().getDependencyDirective(descriptor.getKey()); m_dependencies[i] = new DefaultDependencyModel( context.getLogger().getChildLogger("deps"), context.getPartitionName(), context.getProfile().getName(), descriptor, directive); } // // create the stage models for subsequent assembly // management // StageDescriptor[] stages = m_context.getType().getStages(); m_stages = new DefaultStageModel[stages.length]; for (int i = 0; i < stages.length; i++) { StageDescriptor descriptor = stages[i]; StageDirective directive = context.getComponentProfile().getStageDirective(descriptor.getKey()); m_stages[i] = new DefaultStageModel( context.getLogger().getChildLogger("stages"), context.getPartitionName(), descriptor, directive); } } /** Get the default activation policy for the model. */ public boolean getDefaultActivationPolicy() { final int activation = m_context.getComponentProfile().getActivationDirective(); if (activation != DeploymentProfile.DEFAULT) { return (activation == DeploymentProfile.ENABLED); } else { if (m_context.getProfile().getMode() == Mode.EXPLICIT) { Type type = m_context.getType(); if (type.getInfo().getLifestyle().equals(InfoDescriptor.TRANSIENT)) { return false; } else { return true; } } else { return false; } } } // -------------------------------------------------------------- // Commissionable // -------------------------------------------------------------- /** * Commission the model. * * @exception Exception if a commissioning error occurs */ public void commission() throws Exception { if (isAssembled()) { super.commission(); } else { final String error = "Illegal attempt to commission a non-assembled component model: " + this; throw new ModelException(error); } } // -------------------------------------------------------------- // Composite // -------------------------------------------------------------- /** * Returns the assembled state of the model. * * @return true if this model is assembled */ public boolean isAssembled() { return (isContextAssembled() && isStageAssembled() && isServiceAssembled()); } private boolean isContextAssembled() { ContextModel model = getContextModel(); if (model.isEnabled()) { DeliveryDescriptor delivery = getContextModel().getDeliveryDescriptor(); if (delivery instanceof StagedDeliveryDescriptor) { return (null != getContextModel().getProvider()); } } return true; } private boolean isStageAssembled() { StageModel[] stages = getStageModels(); for (int i = 0; i < stages.length; i++) { if (null == stages[i].getProvider()) return false; } return true; } private boolean isServiceAssembled() { DependencyModel[] dependencies = getDependencyModels(); for (int i = 0; i < dependencies.length; i++) { DependencyModel dep = dependencies[i]; if (null == dep.getProvider() && dep.getDependency().isRequired()) { return false; } } return true; } /** * Return the set of models assigned as providers. * * @return the providers consumed by the model * @exception IllegalStateException if the model is not in an assembled state */ public DeploymentModel[] getProviders() { if (!isAssembled()) { final String error = "Model is not assembled " + this; throw new IllegalStateException(error); } final ArrayList list = new ArrayList(); if (getContextModel().isEnabled()) { DeploymentModel provider = getContextModel().getProvider(); if (provider != null) { list.add(provider); } } StageModel[] stages = getStageModels(); for (int i = 0; i < stages.length; i++) { StageModel stage = stages[i]; list.add(stage.getProvider()); } DependencyModel[] dependencies = getDependencyModels(); for (int i = 0; i < dependencies.length; i++) { DependencyModel dependency = dependencies[i]; DeploymentModel provider = dependency.getProvider(); if (provider != null) list.add(provider); } return (DeploymentModel[]) list.toArray(new DeploymentModel[0]); } // -------------------------------------------------------------- // DeploymentModel // -------------------------------------------------------------- /** * Return the set of services produced by the model. * * @return the service descriptors */ public ServiceDescriptor[] getServices() { return m_context.getType().getServices(); } /** * Return TRUE is this model is capable of supporting a supplied depedendency. * * @param dependency the dependency descriptor * @return true if this model can fulfill the dependency */ public boolean isaCandidate(DependencyDescriptor dependency) { return isaCandidate(dependency.getReference()); } /** * Return TRUE is this model is capable of supporting a supplied stage dependency. * * @param stage the stage descriptor * @return TRUE if this model can fulfill the stage dependency */ public boolean isaCandidate(StageDescriptor stage) { return m_context.getType().getExtension(stage) != null; } /** * Return TRUE is this model is capable of supporting a supplied service. * * @param reference the service reference descriptor * @return true if this model can fulfill the service */ public boolean isaCandidate(ReferenceDescriptor reference) { return m_context.getType().getService(reference) != null; } // -------------------------------------------------------------- // ComponentModel // -------------------------------------------------------------- /** * Return the collection policy for the model. If a profile does not declare a collection policy, * then the collection policy declared by the underlying component type will be used. * * @return the collection policy * @see InfoDescriptor#WEAK * @see InfoDescriptor#SOFT * @see InfoDescriptor#HARD * @see InfoDescriptor#UNDEFINED */ public int getCollectionPolicy() { if (m_collection == InfoDescriptor.UNDEFINED) { return getTypeCollectionPolicy(); } else { return m_collection; } } /** * Set the collection policy for the model. * * @param policy the collection policy * @see InfoDescriptor#WEAK * @see InfoDescriptor#SOFT * @see InfoDescriptor#HARD */ public void setCollectionPolicy(int policy) { if (policy == InfoDescriptor.UNDEFINED) { m_collection = InfoDescriptor.UNDEFINED; } else { int minimum = getTypeCollectionPolicy(); if (policy >= minimum) { m_collection = policy; } else { final String warning = "Ignoring collection policy override [" + policy + "] because the value is higher that type threshhold [" + minimum + "]."; getLogger().warn(warning); } } } private int getTypeCollectionPolicy() { return m_context.getType().getInfo().getCollectionPolicy(); } /** * Return the proxy enabled policy for the model. If the system wide proxy enabled is disabled the * operation will return false otherwise the value returned is true unless overriden by the * "urn:composition:proxy" attribute. * * @return the proxy policy */ public boolean getProxyPolicy() { if (m_context.getSystemContext().isProxyEnabled()) { if (getType().getInfo().getAttribute(PROXY_KEY, "true").equals("false")) { return false; } else { return true; } } else { return false; } } /** * Return the activation policy for the model. * * @return the activaltion policy */ public boolean getActivationPolicy() { return m_activation; } /** * Set the activation policy for the model. * * @param policy the activaltion policy */ public void setActivationPolicy(boolean policy) { m_activation = policy; } /** * Return the component type descriptor. * * @return the type descriptor */ public Type getType() { return m_context.getType(); } /** * Return the class for the deployable target. * * @return the class */ public Class getDeploymentClass() { return m_context.getDeploymentClass(); } /** * Rest if the component type backing the model is parameterizable. * * @return TRUE if the compoent type is parameterizable otherwise FALSE */ public boolean isParameterizable() { return (Parameterizable.class.isAssignableFrom(getDeploymentClass()) || isaConstructorArg(Parameters.class)); } /** * Set the parameters to the supplied value. The supplied parameters value will replace the * existing parameters value. * * @param parameters the supplied parameters value * @exception IllegalStateException if the component type backing the model does not implement the * parameteriazable interface * @exception NullPointerException if the supplied parameters are null */ public void setParameters(Parameters parameters) { setParameters(parameters, true); } /** * Set the parameters to the supplied value. The supplied parameters value may suppliment or * replace the existing parameters value. * * @param parameters the supplied parameters * @param merge if TRUE the supplied parameters are merged with existing parameters otherwise the * supplied parameters replace any existing parameters * @exception IllegalStateException if the component type backing the model does not implement the * parameteriazable interface * @exception NullPointerException if the supplied parameters are null */ public void setParameters(Parameters parameters, boolean merge) throws IllegalStateException { if (!isParameterizable()) { final String error = REZ.getString( "deployment.parameters.irrational", getDeploymentClass().getName(), this.toString()); throw new IllegalStateException(error); } if (parameters == null) { throw new NullPointerException("parameters"); } if (merge) { Properties props = Parameters.toProperties(m_parameters); Properties suppliment = Parameters.toProperties(parameters); Enumeration list = suppliment.propertyNames(); while (list.hasMoreElements()) { String name = (String) list.nextElement(); String value = suppliment.getProperty(name); if (value == null) { props.remove(name); } else { props.setProperty(name, value); } } m_parameters = Parameters.fromProperties(props); } else { m_parameters = parameters; } } /** * Return the parameters to be applied to the component. * * @return the assigned parameters */ public Parameters getParameters() { Parameters params = new Parameters(); if (null != m_parameters) { params.merge(m_parameters); } params.makeReadOnly(); return params; } /** * Rest if the component type backing the model is configurable. * * @return TRUE if the component type is configurable otherwise FALSE */ public boolean isConfigurable() { return (Configurable.class.isAssignableFrom(getDeploymentClass()) || isaConstructorArg(Configuration.class)); } /** * Set the configuration to the supplied value. The supplied configuration will replace the * existing configuration. * * @param config the supplied configuration * @exception IllegalStateException if the component type backing the model does not implement the * configurable interface * @exception NullPointerException if the supplied configuration is null */ public void setConfiguration(Configuration config) throws IllegalStateException, NullPointerException { setConfiguration(config, true); } /** * Set the configuration to the supplied value. The supplied configuration may suppliment or * replace the existing configuration. * * @param config the supplied configuration * @param policy if FALSE the supplied configuration replaces the current configuration otherwise * the resoved configuration shall be layed above the configuration supplied with the profile * which in turn is layer above the type default configuration (if any) * @exception IllegalStateException if the component type backing the model does not implement the * configurable interface * @exception NullPointerException if the supplied configuration is null */ public void setConfiguration(Configuration config, boolean policy) throws IllegalStateException, NullPointerException { if (!isConfigurable()) { final String error = REZ.getString( "deployment.configuration.irrational", getDeploymentClass().getName(), this.toString()); throw new IllegalStateException(error); } if (config == null) { throw new NullPointerException("config"); } if (policy) { m_config = consolidateConfigurations(config, m_config); } else { m_config = config; } } /** * Return the configuration to be applied to the component. The implementation returns the current * configuration state. If the the component type does not implementation the Configurable * interface, the implementation returns null. * * @return the qualified configuration */ public Configuration getConfiguration() { return m_config; } /** * Return the context model for this deployment model. * * @return the context model if this model is context dependent, else the return value is null */ public ContextModel getContextModel() { return m_contextModel; } /** * Return the dependency models for this component type. * * @return the dependency models */ public DependencyModel[] getDependencyModels() { return m_dependencies; } /** * Return a dependency model matching the supplied descriptor. If no model matches the supplied * descriptor the implementation will return null. * * @param dependency the dependency descriptor * @return the matching stage model */ public DependencyModel getDependencyModel(DependencyDescriptor dependency) { DependencyModel[] models = getDependencyModels(); for (int i = 0; i < models.length; i++) { DependencyModel model = models[i]; if (dependency.equals(model.getDependency())) { return model; } } return null; } /** * Return the stage models for this component type. * * @return the stage models */ public StageModel[] getStageModels() { return m_stages; } /** * Return a stage model matching the supplied descriptor. If no stage model matches the supplied * descriptor the implementation will return null. * * @param stage the stage descriptor * @return the matching stage model */ public StageModel getStageModel(StageDescriptor stage) { StageModel[] stages = getStageModels(); for (int i = 0; i < stages.length; i++) { StageModel model = stages[i]; if (stage.equals(model.getStage())) { return model; } } return null; } /** * Return the set of services produced by the model as a array of classes. * * @return the service classes */ public Class[] getInterfaces() { // // TODO: add a SoftReference to hold the service class array // instad of generating each time // ClassLoader classLoader = m_context.getClassLoader(); ArrayList list = new ArrayList(); ServiceDescriptor[] services = getServices(); for (int i = 0; i < services.length; i++) { final ServiceDescriptor service = services[i]; final String classname = service.getReference().getClassname(); list.add(getComponentClass(classLoader, classname)); } // // if the component is an extension then add all implemented // interfaces // if (getType().getExtensions().length > 0) { Class[] interfaces = getDeploymentClass().getInterfaces(); for (int i = 0; i < interfaces.length; i++) { list.add(interfaces[i]); } } return (Class[]) list.toArray(new Class[0]); } /** * Return the deployment timeout value for the component. * * @return the default deployment timeout value */ public long getDeploymentTimeout() { String value = m_context.getType().getInfo().getAttribute(DEPLOYMENT_TIMEOUT_KEY, null); if (null != value) { try { return Long.parseLong(value); } catch (NumberFormatException nfe) { final String error = "Invalid timout parameter [" + value + "] in component type [" + m_context.getType() + "]."; throw new ModelRuntimeException(error, nfe); } } else { return super.getDeploymentTimeout(); } } // ============================================================== // implementation // ============================================================== /** * Test to determin if the first constructor supports the context base class as a parameter type. * * @return TRUE or FALSE */ private boolean isaConstructorArg(Class base) { if (null == base) return false; Class clazz = getDeploymentClass(); Constructor[] constructors = clazz.getConstructors(); if (constructors.length == 0) return false; Constructor constructor = constructors[0]; Class[] types = constructor.getParameterTypes(); for (int i = 0; i < types.length; i++) { if (base.isAssignableFrom(types[i])) return true; } return false; } private Class getComponentClass(ClassLoader classLoader, String classname) { if (classLoader == null) { throw new NullPointerException("classLoader"); } if (classname == null) { throw new NullPointerException("classname"); } try { return classLoader.loadClass(classname); } catch (ClassNotFoundException e) { return null; } } private Configuration consolidateConfigurations( final Configuration primary, final Configuration defaults) { if (primary == null) { return defaults; } else { if (defaults == null) { return primary; } else { return new CascadingConfiguration(primary, defaults); } } } }
/** * A ContainmentProfileBuilder is responsible for building {@link ContainmentProfile} objects from a * configuration object. * * @author <a href="mailto:[email protected]">Avalon Development Team</a> * @version $Id: ContainmentProfileBuilder.java 30977 2004-07-30 08:57:54Z niclas $ */ public final class ContainmentProfileBuilder implements ContainmentProfileCreator { private static final Resources REZ = ResourceManager.getPackageResources(ContainmentProfileBuilder.class); private XMLContainmentProfileCreator m_xml = new XMLContainmentProfileCreator(); private final SerializedContainmentProfileCreator m_serial = new SerializedContainmentProfileCreator(); /** * Create a {@link ContainmentProfile} from a stream. * * @param inputStream the stream that the resource is loaded from * @return the containment profile * @exception Exception if a error occurs during profile creation */ public ContainmentProfile createContainmentProfile(InputStream inputStream) throws Exception { // we backup the inputstream content in a bytearray final byte[] buffer = new byte[1024]; final ByteArrayOutputStream baos = new ByteArrayOutputStream(); for (int read = 0; read >= 0; ) { baos.write(buffer, 0, read); read = inputStream.read(buffer); } inputStream = new ByteArrayInputStream(baos.toByteArray()); try { final ContainmentProfile profile = buildFromSerDescriptor(inputStream); if (null != profile) { return profile; } } catch (Throwable e) { // exception case here is not clear - basically we get a // java.io.StreamCorruptedException if wthe input stream is // referencing an XML stream - for the moment just go ahead // and see if we can resolve the source as an XML input but // sooner or later we will need to update the serialized // to return null if the source isn' a serialized source inputStream = new ByteArrayInputStream(baos.toByteArray()); } return buildFromXMLDescriptor(inputStream); } /** * Build ContainmentProfile from the serialized format. * * @throws Exception if an error occurs */ private ContainmentProfile buildFromSerDescriptor(InputStream inputStream) throws Exception { return m_serial.createContainmentProfile(inputStream); } /** * Build ContainmentProfile from an XML descriptor. * * @param stream the input stream * @throws Exception if an error occurs */ private ContainmentProfile buildFromXMLDescriptor(InputStream stream) throws Exception { final InputSource source = new InputSource(stream); Configuration config = ConfigurationBuilder.build(source); return m_xml.createContainmentProfile(config); } }
/** * A log target factory that establishes log targets based on a artifact reference. * * @author <a href="mailto:[email protected]">Avalon Development Team</a> * @version $Id: PluginTargetFactory.java 30977 2004-07-30 08:57:54Z niclas $ */ public class PluginTargetFactory implements LogTargetFactory { // -------------------------------------------------------------- // static // -------------------------------------------------------------- private static final Resources REZ = ResourceManager.getPackageResources(PluginTargetFactory.class); // -------------------------------------------------------------- // immutable state // -------------------------------------------------------------- private final LogTargetFactoryBuilder m_builder; private final ClassLoader m_classloader; private final InitialContext m_context; private final Map m_factories = new HashMap(); // -------------------------------------------------------------- // constructor // -------------------------------------------------------------- public PluginTargetFactory( ClassLoader classloader, InitialContext context, LogTargetFactoryBuilder builder) { m_builder = builder; m_classloader = classloader; m_context = context; } // -------------------------------------------------------------- // LogTargetFactory // -------------------------------------------------------------- /** * Create a LogTarget based on a supplied configuration * * @param config the target coonfiguration * @return the log target */ public LogTarget createTarget(final Configuration config) throws LogTargetException { final String spec = config.getAttribute("artifact", null); if (null == spec) { final String error = REZ.getString("plugin.error.missing-artifact"); throw new LogTargetException(error); } LogTargetFactory factory = getLogTargetFactory(spec); return factory.createTarget(config); } private LogTargetFactory getLogTargetFactory(String spec) throws LogTargetException { if (m_factories.containsKey(spec)) { return (LogTargetFactory) m_factories.get(spec); } // // otherwise we need to construct the factory, register it // under the spec key and return it to the client // try { String uri = getURI(spec); Artifact artifact = Artifact.createArtifact(uri); Builder builder = m_context.newBuilder(m_classloader, artifact); Class clazz = builder.getFactoryClass(); LogTargetFactory factory = m_builder.buildLogTargetFactory(clazz); m_factories.put(uri, factory); return factory; } catch (Throwable e) { final String error = REZ.getString("plugin.error.build", spec); throw new LogTargetException(error, e); } } private String getURI(String spec) { if (spec.startsWith("artifact:")) return spec; return "artifact:" + spec; } }