cziegeler 2004/04/02 00:29:45 Added: fortress/meta/src/java/org/apache/avalon/fortress/tools Component.java ComponentMetaInfoCollector.java Service.java Removed: fortress/meta/src/java/org/apache/avalon/fortress/meta ComponentMetaInfoCollector.java Component.java Service.java Log: Correct package name Revision Changes Path 1.1 avalon-excalibur/fortress/meta/src/java/org/apache/avalon/fortress/tools/Component.java Index: Component.java =================================================================== /* * 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. */ package org.apache.avalon.fortress.tools; import com.thoughtworks.qdox.model.*; import org.apache.avalon.fortress.MetaInfoEntry; import org.apache.avalon.fortress.util.dag.Vertex; import org.apache.tools.ant.BuildException; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.*; /** * Represents a component, and output the meta information. * * @author <a href="mailto:dev@avalon.apache.org">The Avalon Team</a> * @version CVS $Revision: 1.1 $ $Date: 2004/04/02 08:29:44 $ */ final class Component { private static final String SINGLE_THREADED = "org.apache.avalon.framework.thread.SingleThreaded"; private static final String THREAD_SAFE = "org.apache.avalon.framework.thread.ThreadSafe"; private static final String POOLABLE = "org.apache.avalon.excalibur.pool.Poolable"; private static final String RECYCLABLE = "org.apache.avalon.excalibur.pool.Recyclable"; private static final String SERVICE_MANAGER = "org.apache.avalon.framework.service.ServiceManager"; static final String ATTR_TYPE = "type"; static final String ATTR_NAME = "name"; private static final String TAG_SERVICE = "avalon.service"; private static final String TAG_DEPENDENCY = "avalon.dependency"; private static final String TAG_LIFESTYLE = "x-avalon.lifestyle"; private static final String TAG_HANDLER = "fortress.handler"; private static final String TAG_INFO = "x-avalon.info"; private static final String TAG_NAME = "fortress.name"; private static final String META_NAME = "x-avalon.name"; private static final String METH_SERVICE = "service"; /** The repository of components. */ static final Set m_repository = new HashSet(); private final JavaClass m_javaClass; private final Properties m_attributes; private final List m_dependencies; private final Vertex m_vertex; private final List m_dependencyNames; private final List m_serviceNames; /** * Initialize a service with the type name. * * @param javaClass */ public Component( final JavaClass javaClass ) { if ( javaClass == null ) throw new NullPointerException( "javaClass" ); m_javaClass = javaClass; m_attributes = new Properties(); m_dependencies = new ArrayList( 10 ); m_vertex = new Vertex( this ); m_dependencyNames = new ArrayList( 10 ); m_serviceNames = new ArrayList( 10 ); final DocletTag[] tags = javaClass.getTagsByName( TAG_SERVICE ); for ( int t = 0; t < tags.length; t++ ) { if ( tags[t].getNamedParameter( Component.ATTR_TYPE ) == null ) { throw new BuildException( "The \"type\" tag is missing from the " + "\"@" + TAG_SERVICE + "\" meta tag in " + javaClass.getName() ); } final String serviceName = resolveClassName( m_javaClass.getParentSource(), tags[t].getNamedParameter( Component.ATTR_TYPE ) ); m_serviceNames.add( serviceName ); } discoverLifecycleType(); discoverNameInfo(); discoverDependencies(); m_repository.add( this ); } /** * Recursively discover dependencies from the local class hierarchy. This does not, and cannot * discover dependencies from classes from other JARs. */ private void discoverDependencies() { JavaClass currClass = m_javaClass; while ( currClass != null && discoverDependencies( currClass ) ) { currClass = currClass.getSuperJavaClass(); } } /** * Discover the dependencies that this component class requires. * * @param fromClass The JavaClass object to gather the dependency set from. */ private boolean discoverDependencies( final JavaClass fromClass ) { boolean isSuccessful = true; JavaMethod[] methods = fromClass.getMethods(); for ( int i = 0; i < methods.length; i++ ) { if ( methods[i].getName().equals( METH_SERVICE ) ) { if ( methods[i].getParameters().length == 1 && methods[i].getParameters()[0].getType().getValue().equals( SERVICE_MANAGER ) ) { DocletTag[] dependencies = methods[i].getTagsByName( TAG_DEPENDENCY ); for ( int d = 0; d < dependencies.length; d++ ) { if ( dependencies[d].getNamedParameter( ATTR_TYPE ) == null ) { throw new BuildException( "The \"type\" tag is missing from a " + "\"@" + TAG_DEPENDENCY + "\" meta tag of the " + METH_SERVICE + " method in " + fromClass.getName() ); } String type = resolveClassName( fromClass.getParentSource(), dependencies[d].getNamedParameter( ATTR_TYPE ) ); //String optional = dependencies[d].getNamedParameter("optional"); if ( null == type ) { isSuccessful = false; } else { m_dependencyNames.add( type ); } } } } } return isSuccessful; } private void discoverNameInfo() { DocletTag avalonConfigName = m_javaClass.getTagByName( TAG_INFO ); if ( null == avalonConfigName ) avalonConfigName = m_javaClass.getTagByName( TAG_NAME ); String name = MetaInfoEntry.createShortName(m_javaClass.getName()); if ( avalonConfigName != null ) { name = avalonConfigName.getNamedParameter( ATTR_NAME ); } setAttribute( META_NAME, name ); } private void discoverLifecycleType() { final DocletTag avalonLifecycle = m_javaClass.getTagByName( TAG_LIFESTYLE ); final DocletTag fortressHandler = m_javaClass.getTagByName( TAG_HANDLER ); String lifecycle = null; String handler = null; if ( avalonLifecycle == null && fortressHandler == null ) { final Type[] interfaces = m_javaClass.getImplements(); for ( int i = 0; i < interfaces.length && handler != null; i++ ) { if ( interfaces[i].getClass().getName().equals( THREAD_SAFE ) ) { handler = MetaInfoEntry.THREADSAFE_HANDLER; } else if ( interfaces[i].getClass().getName().equals( POOLABLE ) || interfaces[i].getClass().getName().equals( RECYCLABLE ) ) { handler = MetaInfoEntry.POOLABLE_HANDLER; } else if ( interfaces[i].getClass().getName().equals( SINGLE_THREADED ) ) { handler = MetaInfoEntry.FACTORY_HANDLER; } } } if ( null != avalonLifecycle ) // lifecycle specified directly { lifecycle = stripQuotes( avalonLifecycle.getNamedParameter( ATTR_TYPE ) ); } else if ( null != fortressHandler ) // handler specified directly { handler = stripQuotes( fortressHandler.getNamedParameter( ATTR_TYPE ) ); } else // no lifecycle or handler specified, and no inspection match { handler = MetaInfoEntry.PER_THREAD_HANDLER; } if ( null != lifecycle ) setAttribute( TAG_LIFESTYLE, lifecycle ); if ( null != handler ) setAttribute( TAG_HANDLER, handler ); } /** * Get the type name. * * @return String */ public String getType() { return m_javaClass.getFullyQualifiedName(); } public Iterator getDependencyNames() { return m_dependencyNames.iterator(); } public Iterator getServiceNames() { return m_serviceNames.iterator(); } /** * Add a dependency to this type. * * @param service The name of the service that depends on this. */ public void addDependency( Service service ) { if ( !m_dependencies.contains( service ) ) { m_dependencies.add( service ); } } public Vertex getVertex() { if ( m_vertex.getDependencies().size() != 0 ) { Iterator it = m_dependencies.iterator(); while ( it.hasNext() ) { Service service = (Service) it.next(); Iterator cit = service.getComponents(); while ( cit.hasNext() ) { Component component = (Component) cit.next(); m_vertex.addDependency( component.getVertex() ); } } } return m_vertex; } /** * Set the component attribute. * * @param name The name of the attribute * @param value The attribute value */ public void setAttribute( final String name, final String value ) { m_attributes.setProperty( name, value ); } /** * Output the meta information. * * @param rootDir * @throws IOException */ public void serialize( final File rootDir ) throws IOException { final String fileName = getType().replace( '.', '/' ).concat( ".meta" ); final String depsName = getType().replace( '.', '/' ).concat( ".deps" ); File output = new File( rootDir, fileName ); FileOutputStream writer = null; try { writer = new FileOutputStream( output ); m_attributes.store( writer, "Meta information for " + getType() ); if ( m_dependencies.size() > 0 ) { writer.close(); output = new File( rootDir, depsName ); writer = new FileOutputStream( output ); Iterator it = m_dependencies.iterator(); while ( it.hasNext() ) { Service service = (Service) it.next(); String name = service.getType() + "\n"; writer.write( name.getBytes() ); } } } finally { if ( null != writer ) { writer.close(); } } } private String stripQuotes( final String value ) { if ( null == value ) return null; if ( value.length() < 2 ) return value; String retVal = value.trim(); if ( retVal.startsWith( "\"" ) && retVal.endsWith( "\"" ) ) { retVal = retVal.substring( 1, retVal.length() - 1 ); } return retVal; } /** * Resolve the classname from the "@avalon.service" javadoc tags. * * @param serviceName The service type name * @return The fully qualified class name */ protected String resolveClassName( final JavaSource sourceCode, final String serviceName ) { if ( null == sourceCode ) { return null; } if ( null == serviceName ) { // This should be checked by the caller so that a message which better // describes the problem in a given context can be given. throw new IllegalStateException( "The serviceName parameter was null." ); } final String className = stripQuotes( serviceName ); if ( className != null || className.length() > 0 ) { if ( className.indexOf( '.' ) < 0 ) { String checkName = checkPackage(sourceCode, sourceCode.getPackage(), className); if ( ! checkName.equals(className) ) return checkName; String[] imports = sourceCode.getImports(); for ( int t = 0; t < imports.length; t++ ) { checkName = checkImport( sourceCode, imports[t], className); if ( ! checkName.equals( className ) ) return checkName; } } } return className; } private String checkImport ( final JavaSource sourceCode, final String type, final String className) { final String tail = type.substring( type.lastIndexOf( '.' ) + 1 ); if ( tail.equals( className ) ) { return type; } else if ( tail.equals( "*" ) ) { final String pack = type.substring( 0, type.lastIndexOf( '.' ) ); String checkName = checkPackage( sourceCode, pack, className ); if ( !checkName.equals( className ) ) return checkName; } return className; } private String checkPackage( final JavaSource sourceCode, final String pack, final String serviceName ) { String className = serviceName; final JavaClass klass = sourceCode.getClassLibrary().getClassByName( pack + "." + serviceName ); if ( null != klass ) className = klass.getFullyQualifiedName(); return className; } } 1.1 avalon-excalibur/fortress/meta/src/java/org/apache/avalon/fortress/tools/ComponentMetaInfoCollector.java Index: ComponentMetaInfoCollector.java =================================================================== /* * 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. */ package org.apache.avalon.fortress.tools; import com.thoughtworks.qdox.ant.AbstractQdoxTask; import com.thoughtworks.qdox.model.DocletTag; import com.thoughtworks.qdox.model.JavaClass; import org.apache.avalon.fortress.util.dag.CyclicDependencyException; import org.apache.avalon.fortress.util.dag.DirectedAcyclicGraphVerifier; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; /** * ANT task to collect all the meta information for the components. * * @author <a href="mailto:dev@avalon.apache.org">The Avalon Team</a> * @version CVS $Revision: 1.1 $ $Date: 2004/04/02 08:29:44 $ */ public final class ComponentMetaInfoCollector extends AbstractQdoxTask { /** * The services to write the meta info for. */ private final Map m_services = new HashMap(); /** * The destination directory for metadata files. */ private File m_destDir; /** * The service list destination. */ private File m_serviceFile; private static final String TAG_COMPONENT = "avalon.component"; /** * Set the destination directory for the meta information. * * @param destDir The destination directory */ public void setDestDir( final File destDir ) { m_destDir = destDir; } /** * Execute generator task. * * @throws BuildException if there was a problem collecting the info */ public void execute() throws BuildException { validate(); log( "Writing Info descriptors as property files (.meta)." ); super.execute(); try { collectInfoMetaData(); writeComponents(); writeServiceList( m_services.values().iterator() ); log( "Collecting service information." ); writeServices(); } catch ( final Exception e ) { throw new BuildException( e.toString(), e ); } finally { Component.m_repository.clear(); } } /** * Write the component meta information to the associated files. * * @throws IOException if there is a problem. */ private void writeComponents() throws IOException, CyclicDependencyException { final List dagVerifyList = new ArrayList( Component.m_repository.size() ); final Iterator it = Component.m_repository.iterator(); while ( it.hasNext() ) { final Component comp = (Component) it.next(); comp.serialize( m_destDir ); dagVerifyList.add( comp.getVertex() ); } DirectedAcyclicGraphVerifier.verify( dagVerifyList ); } /** * Write the service list to the "/service.list" file. * * @param it The iterator for the services * @throws IOException if there is a problem writing the file */ public void writeServiceList( final Iterator it ) throws IOException { final PrintWriter writer = new PrintWriter( new FileWriter( m_serviceFile ) ); int numServices = 0; while ( it.hasNext() ) { writer.println( ( (Service) it.next() ).getType() ); numServices++; } writer.close(); if ( numServices == 0 ) { m_serviceFile.delete(); } } /** * Validate that the parameters are valid. */ private void validate() { if ( null == m_destDir ) { final String message = "DestDir (" + m_destDir + ") not specified"; throw new BuildException( message ); } if ( !m_destDir.isDirectory() ) { final String message = "DestDir (" + m_destDir + ") is not a directory."; throw new BuildException( message ); } if ( !m_destDir.exists() && !m_destDir.mkdirs() ) { final String message = "DestDir (" + m_destDir + ") could not be created."; throw new BuildException( message ); } m_serviceFile = new File( m_destDir, "services.list" ); } /** * Output the metadata files. */ private void collectInfoMetaData() { final Iterator it = allClasses.iterator(); while ( it.hasNext() ) { final JavaClass javaClass = (JavaClass) it.next(); final DocletTag tag = javaClass.getTagByName( TAG_COMPONENT ); if ( null != tag ) { final Component comp = new Component( javaClass ); Iterator sit = comp.getServiceNames(); while ( sit.hasNext() ) { String servName = (String) sit.next(); Service service = getService( servName ); service.addComponent( comp ); } Iterator dit = comp.getDependencyNames(); while ( dit.hasNext() ) { String depName = (String) dit.next(); Service service = getService( depName ); comp.addDependency( service ); } } } } /** * Get the unique Service object for the specified type. * * @param type The service type name * @return the Service object */ protected Service getService( final String type ) { Service service = (Service) m_services.get( type ); if ( null == service ) { service = new Service( type ); m_services.put( service.getType(), service ); } return service; } /** * Collect all the services and write out the implementations. */ private void writeServices() { final File baseDir = new File( m_destDir, "META-INF/services/" ); baseDir.mkdirs(); final Iterator services = m_services.values().iterator(); while ( services.hasNext() ) { final Service service = (Service) services.next(); log( "Processing service " + service.getType(), Project.MSG_VERBOSE ); try { service.serialize( m_destDir ); } catch ( Exception e ) { log( "Could not save information for service " + service.getType(), Project.MSG_WARN ); } } } } 1.1 avalon-excalibur/fortress/meta/src/java/org/apache/avalon/fortress/tools/Service.java Index: Service.java =================================================================== /* * 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. */ package org.apache.avalon.fortress.tools; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.HashSet; import java.util.Iterator; import java.util.Set; /** * Encapsulate the Service information, and encapsulate all the * logic to serialize the service. * * @author <a href="mailto:dev@avalon.apache.org">The Avalon Team</a> * @version CVS $Revision: 1.1 $ $Date: 2004/04/02 08:29:44 $ */ final class Service { private final Set m_components; private final String m_type; /** * Initialize a service with the type name. * * @param type */ public Service( final String type ) { if ( type == null ) throw new NullPointerException( "type" ); m_type = type; m_components = new HashSet(); } /** * Get the service type name. * * @return the type name */ public String getType() { return m_type; } /** * Add a component to the service. * * @param type the type name for the component */ public void addComponent( final Component type ) { if ( type == null ) throw new NullPointerException( "type" ); m_components.add( type ); } public Iterator getComponents() { return m_components.iterator(); } /** * Output the service info. * * @param rootDir * @throws IOException */ public void serialize( final File rootDir ) throws IOException { if ( m_components.isEmpty() ) return; final File serviceFile = new File( rootDir, "META-INF/services/" + getType() ); PrintWriter writer = null; try { writer = new PrintWriter( new FileWriter( serviceFile ) ); final Iterator it = m_components.iterator(); while ( it.hasNext() ) { final Component comp = (Component) it.next(); writer.println( comp.getType() ); } } finally { if ( null != writer ) { writer.close(); } } } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]