jicarilla-sandbox/platform/container-integration/src/java/org/jicarilla/container/integration/dna DefaultConfigurationValidator.java,NONE,1.1 InvalidTypeException.java,NONE,1.1 DnaUtil.java,1.1,1.2 ResourceLocatorBasedKeyAwareComponentAdapter.java,1.1,1.2
Leo Simons <[email protected]>
| Newsgroups | gmane.comp.java.jicarilla.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/jicarilla/jicarilla-sandbox/platform/container-integration/src/java/org/jicarilla/container/integration/dna In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16675/platform/container-integration/src/java/org/jicarilla/container/integration/dna Modified Files: DnaUtil.java ResourceLocatorBasedKeyAwareComponentAdapter.java Added Files: DefaultConfigurationValidator.java InvalidTypeException.java Log Message: starting work on the metadata-based verification of dna contracts --- NEW FILE: DefaultConfigurationValidator.java --- /* * Copyright (C) 2004, Leo Simons. All rights reserved. * Copyright (C) The JContainer Group. All rights reserved. * * ==================================================================== * JContainer Software License, version 1.1 * * Copyright (c) 2003, JContainer Group. All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. Neither the name of the JContainer Group nor the name "Loom" nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * ==================================================================== * * Jicarilla includes code from the Apache Software Foundation * * ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 1997-2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software * itself, if and wherever such third-party acknowledgments * normally appear. * * 4. The names "Jakarta", "Avalon", and "Apache Software Foundation" * must not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact [email protected]. * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ package org.jicarilla.container.integration.dna; import org.codehaus.spice.configkit.ComponentConfigUtil; import org.codehaus.spice.configkit.ConfigValidator; import org.codehaus.spice.configkit.ValidateException; import org.codehaus.spice.configkit.ValidationIssue; import org.codehaus.spice.configkit.ValidationResult; import org.jcontainer.dna.Configuration; import org.jcontainer.dna.impl.ConfigurationUtil; import org.w3c.dom.Element; /** * This component validates the components configuration using the ConfigKit * toolkit. * * @author Peter Donald * @author Peter Royal * @author Leo Simons * @version $Id: DefaultConfigurationValidator.java,v 1.1 2004/04/04 11:43:46 lsimons Exp $ */ public class DefaultConfigurationValidator { public static boolean validate( final Configuration configuration, final String className, final ClassLoader classLoader, final String schemaLocation, final String schemaType ) throws ValidateException { final ConfigValidator validator; try { validator = ComponentConfigUtil.getComponentConfigValidator( className, classLoader, schemaLocation, schemaType ); } catch( Exception e ) { final String message = "Missing schema for component of type " + className + " with schema " + schemaLocation + " of type " + schemaType; throw new ValidateException( message, e ); } final Element element = ConfigurationUtil.toElement( configuration ); final ValidationResult result = validator.validate( element ); processValidationResults( result ); return true; } public static void processValidationResults( final ValidationResult result ) throws ValidateException { if( !result.isValid() ) { final ValidationIssue[] issues = result.getIssues(); throw result.getException(); } } } --- NEW FILE: InvalidTypeException.java --- /* ==================================================================== The Jicarilla Software License Copyright (c) 2003 Leo Simons. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ==================================================================== */ package org.jicarilla.container.integration.dna; import org.jcontainer.dna.tools.verifier.VerifyIssue; import org.jicarilla.container.JicarillaInstantiationException; /** * * * @author <a href="lsimons at jicarilla dot org">Leo Simons</a> * @version $Id: InvalidTypeException.java,v 1.1 2004/04/04 11:43:46 lsimons Exp $ */ public class InvalidTypeException extends JicarillaInstantiationException { protected final String m_message; public InvalidTypeException( final Class type, final VerifyIssue[] issues ) { StringBuffer message = new StringBuffer( "Error creating instance of '" ); message.append( type.getName() ); message.append ( "'. The issues were:" ); for( int i = 0; i < issues.length; i++ ) { VerifyIssue issue = issues[i]; message.append( "\n" ); message.append( " " ); if( issue.isWarning() ) message.append( "W " ); if( issue.isError() ) message.append( "E" ); message.append( issue.getDescription() ); } m_message = message.toString(); } public String getMessage() { return m_message; } } Index: DnaUtil.java =================================================================== RCS file: /cvsroot/jicarilla/jicarilla-sandbox/platform/container-integration/src/java/org/jicarilla/container/integration/dna/DnaUtil.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- DnaUtil.java 3 Apr 2004 12:09:21 -0000 1.1 +++ DnaUtil.java 4 Apr 2004 11:43:46 -0000 1.2 @@ -25,27 +25,34 @@ ==================================================================== */ package org.jicarilla.container.integration.dna; -import org.jicarilla.container.Resolver; -import org.jicarilla.collections.NodeUtil; -import org.jcontainer.dna.impl.ContainerUtil; -import org.jcontainer.dna.impl.ConsoleLogger; -import org.jcontainer.dna.impl.ConfigurationUtil; -import org.jcontainer.dna.impl.DefaultParameters; -import org.jcontainer.dna.Logger; -import org.jcontainer.dna.ResourceLocator; +import com.thoughtworks.xstream.XStream; +import org.jcontainer.dna.Composable; import org.jcontainer.dna.Configurable; -import org.jcontainer.dna.Parameterizable; import org.jcontainer.dna.Configuration; -import org.jcontainer.dna.Parameters; import org.jcontainer.dna.ConfigurationException; +import org.jcontainer.dna.LogEnabled; +import org.jcontainer.dna.Logger; +import org.jcontainer.dna.MissingResourceException; +import org.jcontainer.dna.ReleaseUtil; +import org.jcontainer.dna.ResourceLocator; +import org.jcontainer.dna.impl.ConfigurationUtil; +import org.jcontainer.dna.impl.ConsoleLogger; +import org.jcontainer.dna.impl.ContainerUtil; +import org.jcontainer.dna.tools.verifier.ComponentVerifier; +import org.jcontainer.dna.tools.verifier.VerifyIssue; +import org.jicarilla.container.Resolver; +import org.jicarilla.lang.Assert; +import org.realityforge.metaclass.Attributes; +import org.realityforge.metaclass.model.Attribute; import org.xml.sax.InputSource; import java.io.Reader; import java.io.StringReader; -import java.util.Properties; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Iterator; - -import com.thoughtworks.xstream.XStream; +import java.util.List; /** * @@ -57,6 +64,8 @@ { public final static String CONFIGURATION_POSTFIX = "Configuration"; + protected final static ComponentVerifier verifier = new ComponentVerifier(); + public final static ConsoleLogger FallbackLogger = new ConsoleLogger( ConsoleLogger.LEVEL_WARN ); @@ -65,26 +74,26 @@ { try { - ContainerUtil.enableLogging( instance, - getLogger( container, instance.getClass().getName() ) ); - ContainerUtil.compose( instance, getResourceLocator( container ) ); + final Logger logger = ( instance instanceof LogEnabled )? + getLogger( + container, instance.getClass().getName() ) : null; - if( instance instanceof Configurable || - instance instanceof Parameterizable ) - { - final Configuration configuration = - getConfiguration( container, - instance.getClass().getName() ); - ContainerUtil.configure( instance, configuration ); - - if( instance instanceof Parameterizable ) - { - Parameters parameters = - configurationToParameters( configuration ); - ContainerUtil.parameterize( instance, parameters ); - } - } + final ResourceLocator locator = ( instance instanceof Composable )? + getResourceLocator( container ) : null; + + final Configuration configuration = + ( instance instanceof Configuration )? + getConfiguration( container, + instance.getClass().getName() ) : null; + + // TODO: test verifyStrictDnaContract( instance.getClass(), + // logger, locator, configuration ); + + ContainerUtil.enableLogging( instance, logger ); + ContainerUtil.compose( instance, locator ); + ContainerUtil.configure( instance, configuration ); ContainerUtil.initialize( instance ); + } catch( Exception e ) { @@ -145,26 +154,223 @@ return configuration; } - protected static Parameters configurationToParameters( - final Configuration configuration ) + protected static void verifyStrictDnaContract( Class type, + Logger logger, + ResourceLocator availableResources, Configuration configuration ) + throws Exception { - final Properties properties = NodeUtil.toProperties( - NodeUtil.fromElement( - ConfigurationUtil.toElement( configuration ) - ) - ); - final DefaultParameters parameters = - new DefaultParameters(); - Iterator it = properties.keySet().iterator(); - while( it.hasNext() ) + final List issues = new ArrayList(); + + // TODO: check that only declared resources are provided... + + verifySatisfiableDnaContract( type, logger, + availableResources, configuration, issues ); + + handleIssues( issues, type ); + } + + protected static void handleIssues( final List issues, Class type ) + { + if( issues.size() > 0 ) { - Object key = it.next(); - if( key == null ) continue; - String keyString = key.toString(); - parameters.setParameter( keyString, - properties.getProperty( keyString ) ); + boolean isError = false; + Iterator it = issues.iterator(); + while( it.hasNext() ) + { + VerifyIssue issue = (VerifyIssue)it.next(); + if( issue.isError() ) + { + isError= true; + break; + } + } + if( isError ) + { + throw new InvalidTypeException( + type, + (VerifyIssue[])issues.toArray( + new VerifyIssue[issues.size()] + ) + ); + } + else + { + // warnings & notices only....ignore + } } - parameters.makeReadOnly(); - return parameters; + } + + protected static void verifySatisfiableDnaContract( Class type, + Logger logger, + ResourceLocator availableResources, Configuration configuration, + List issues ) + throws Exception + { + Assert.assertNotNull( "type argument may not be null", type ); + + verifyBasicDnaContract( type, issues ); + + if( LogEnabled.class.isAssignableFrom( type) ) + verifySatisfiableLoggers( logger, issues ); + if( Composable.class.isAssignableFrom( type) ) + verifySatisfiableDependencies( availableResources, issues ); + if( Configurable.class.isAssignableFrom( type) ) + verifyValidConfiguration( type, configuration, issues ); + } + + protected static void verifyBasicDnaContract( Class type, List issues ) + throws InvalidTypeException + { + issues.addAll( Arrays.asList( verifier.verifyType( type ) ) ); + } + + protected static void verifySatisfiableLoggers( Logger logger, + List issues ) throws NoSuchMethodException + { + Assert.assertNotNull( "logger argument may not be null", logger ); + + final Method method = LogEnabled.class.getMethod( "enableLogging", + new Class[] { Logger.class } ); + final Attribute[] attributes = Attributes.getAttributes( method, + "dna.logger" ); + + for( int i = 0; i < attributes.length; i++ ) + { + Attribute attribute = attributes[i]; + verifySatisfiableLogger( logger, attribute, issues ); + } + } + + protected static void verifySatisfiableLogger( Logger logger, + Attribute attribute, List issues ) + { + final String name = attribute.getParameter( "name" ); + if( name == null ) + return; + else + { + Logger child = logger.getChildLogger( name ); + if( child == null ) + { + issues.add( new VerifyIssue( VerifyIssue.ERROR, + "Logger with name '" + name + + "' cannot be satisfied." )); + } + } + } + + protected static void verifySatisfiableDependencies( + ResourceLocator availableResources, List issues ) + throws NoSuchMethodException + { + Assert.assertNotNull( "availableResources argument may not be null", + availableResources ); + + final Method method = Composable.class.getMethod( "compose", + new Class[] { ResourceLocator.class } ); + final Attribute[] attributes = Attributes.getAttributes( method, + "dna.dependency" ); + + for( int i = 0; i < attributes.length; i++ ) + { + Attribute attribute = attributes[i]; + verifySatisfiableDependency( + availableResources, attribute, issues ); + } + } + + protected static void verifySatisfiableDependency( + ResourceLocator availableResources, Attribute attribute, + List issues ) + { + final String dependencyType = attribute.getParameter( "type" ); + String key = attribute.getParameter( "key" ); + if( key == null ) key = dependencyType; + final boolean available = availableResources.contains( key ); + + if( !available ) + { + issues.add( new VerifyIssue( VerifyIssue.ERROR, + "Dependency '" + key + "' cannot be satisfied." )); + return; + } + + Object instance = null; + try + { + Class clazz = instance.getClass().getClassLoader() + .loadClass( dependencyType ); + instance = availableResources.lookup( key ); + + if( !clazz.isInstance( instance ) ) + { + issues.add( new VerifyIssue( VerifyIssue.ERROR, + "Dependency returned for '" + key + "' is not of the" + + " expected type '" + dependencyType + "'.")); + return; + } + } + catch( MissingResourceException e ) + { + issues.add( new VerifyIssue( VerifyIssue.ERROR, + "Dependency '" + key + "' cannot be satisfied." )); + return; + } + catch( ClassNotFoundException e ) + { + issues.add( + new VerifyIssue( + VerifyIssue.ERROR, + "Expected type '" + dependencyType + + "' cannot be loaded." + ) + ); + return; + } + finally + { + if( instance != null ) + ReleaseUtil.release( instance ); + } + } + + protected static void verifyValidConfiguration( Class type, + Configuration configuration, List issues ) + throws Exception + { + Assert.assertNotNull( "configuration argument may not be null", + configuration ); + + final Method method = Configurable.class.getMethod( "configure", + new Class[] { Configuration.class } ); + + final Attribute attribute = Attributes.getAttribute( method, + "dna.configuration" ); + if( attribute == null ) return; + + final String schemaFile = attribute.getParameter( "location" ); + String schemaType = attribute.getParameter( "type" ); + if( schemaType == null ) + { + if( schemaType.indexOf( ".") != -1 ) + schemaType = schemaFile.substring( + schemaFile.lastIndexOf( "." ) ); + else + { + issues.add( + new VerifyIssue( + VerifyIssue.ERROR, + "Cannot determine the type of the configuration schema" + ) + ); + return; + } + } + + DefaultConfigurationValidator.validate( configuration, + type.getName(), + type.getClassLoader(), + schemaFile, + schemaType ); } } Index: ResourceLocatorBasedKeyAwareComponentAdapter.java =================================================================== RCS file: /cvsroot/jicarilla/jicarilla-sandbox/platform/container-integration/src/java/org/jicarilla/container/integration/dna/ResourceLocatorBasedKeyAwareComponentAdapter.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- ResourceLocatorBasedKeyAwareComponentAdapter.java 3 Apr 2004 12:59:18 -0000 1.1 +++ ResourceLocatorBasedKeyAwareComponentAdapter.java 4 Apr 2004 11:43:46 -0000 1.2 @@ -65,6 +65,7 @@ public void releaseInstance( final Object component ) throws Exception { + // TODO: proxy the component in getInstance so this results in something ReleaseUtil.release( component ); } } ------------------------------------------------------- This SF.Net email is sponsored by: IBM Linux Tutorials Free Linux tutorial presented by Daniel Robbins, President and CEO of GenToo technologies. Learn everything from fundamentals to system administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click