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:[EMAIL PROTECTED]">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:[EMAIL PROTECTED]">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:[EMAIL PROTECTED]">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]