1 17 18 package org.apache.avalon.fortress.tools; 19 20 import com.thoughtworks.qdox.model.*; 21 import org.apache.avalon.fortress.MetaInfoEntry; 22 import org.apache.avalon.fortress.util.dag.Vertex; 23 import org.apache.tools.ant.BuildException; 24 25 import java.io.File ; 26 import java.io.FileOutputStream ; 27 import java.io.IOException ; 28 import java.util.*; 29 30 36 final class Component 37 { 38 private static final String SINGLE_THREADED = "org.apache.avalon.framework.thread.SingleThreaded"; 39 private static final String THREAD_SAFE = "org.apache.avalon.framework.thread.ThreadSafe"; 40 private static final String POOLABLE = "org.apache.avalon.excalibur.pool.Poolable"; 41 private static final String RECYCLABLE = "org.apache.avalon.excalibur.pool.Recyclable"; 42 private static final String SERVICE_MANAGER = "org.apache.avalon.framework.service.ServiceManager"; 43 44 static final String ATTR_TYPE = "type"; 45 static final String ATTR_NAME = "name"; 46 47 private static final String TAG_SERVICE = "avalon.service"; 48 private static final String TAG_DEPENDENCY = "avalon.dependency"; 49 private static final String TAG_LIFESTYLE = "x-avalon.lifestyle"; 50 private static final String TAG_HANDLER = "fortress.handler"; 51 private static final String TAG_INFO = "x-avalon.info"; 52 private static final String TAG_NAME = "fortress.name"; 53 54 private static final String META_NAME = "x-avalon.name"; 55 56 private static final String METH_SERVICE = "service"; 57 58 59 static final Set m_repository = new HashSet(); 60 61 private final JavaClass m_javaClass; 62 private final Properties m_attributes; 63 private final List m_dependencies; 64 private final Vertex m_vertex; 65 private final List m_dependencyNames; 66 private final List m_serviceNames; 67 68 73 public Component( final JavaClass javaClass ) 74 { 75 if ( javaClass == null ) throw new NullPointerException ( "javaClass" ); 76 77 m_javaClass = javaClass; 78 m_attributes = new Properties(); 79 m_dependencies = new ArrayList( 10 ); 80 m_vertex = new Vertex( this ); 81 m_dependencyNames = new ArrayList( 10 ); 82 m_serviceNames = new ArrayList( 10 ); 83 84 final DocletTag[] tags = javaClass.getTagsByName( TAG_SERVICE ); 85 for ( int t = 0; t < tags.length; t++ ) 86 { 87 if ( tags[t].getNamedParameter( Component.ATTR_TYPE ) == null ) 88 { 89 throw new BuildException( "The \"type\" tag is missing from the " 90 + "\"@" + TAG_SERVICE + "\" meta tag in " 91 + javaClass.getName() ); 92 } 93 94 final String serviceName = resolveClassName( m_javaClass.getParentSource(), 95 tags[t].getNamedParameter( Component.ATTR_TYPE ) ); 96 m_serviceNames.add( serviceName ); 97 } 98 99 discoverLifecycleType(); 100 discoverNameInfo(); 101 discoverDependencies(); 102 103 m_repository.add( this ); 104 } 105 106 110 private void discoverDependencies() 111 { 112 JavaClass currClass = m_javaClass; 113 114 while ( currClass != null && discoverDependencies( currClass ) ) 115 { 116 currClass = currClass.getSuperJavaClass(); 117 } 118 } 119 120 125 private boolean discoverDependencies( final JavaClass fromClass ) 126 { 127 boolean isSuccessful = true; 128 129 JavaMethod[] methods = fromClass.getMethods(); 130 for ( int i = 0; i < methods.length; i++ ) 131 { 132 if ( methods[i].getName().equals( METH_SERVICE ) ) 133 { 134 if ( methods[i].getParameters().length == 1 && methods[i].getParameters()[0].getType().getValue().equals( SERVICE_MANAGER ) ) 135 { 136 DocletTag[] dependencies = methods[i].getTagsByName( TAG_DEPENDENCY ); 137 for ( int d = 0; d < dependencies.length; d++ ) 138 { 139 if ( dependencies[d].getNamedParameter( ATTR_TYPE ) == null ) 140 { 141 throw new BuildException( "The \"type\" tag is missing from a " 142 + "\"@" + TAG_DEPENDENCY + "\" meta tag of the " + METH_SERVICE 143 + " method in " + fromClass.getName() ); 144 } 145 146 String type = resolveClassName( fromClass.getParentSource(), 147 dependencies[d].getNamedParameter( ATTR_TYPE ) ); 148 150 if ( null == type ) 151 { 152 isSuccessful = false; 153 } 154 else 155 { 156 m_dependencyNames.add( type ); 157 } 158 } 159 } 160 } 161 } 162 163 return isSuccessful; 164 } 165 166 private void discoverNameInfo() 167 { 168 DocletTag avalonConfigName = m_javaClass.getTagByName( TAG_INFO ); 169 if ( null == avalonConfigName ) avalonConfigName = m_javaClass.getTagByName( TAG_NAME ); 170 171 String name = MetaInfoEntry.createShortName(m_javaClass.getName()); 172 173 if ( avalonConfigName != null ) 174 { 175 name = avalonConfigName.getNamedParameter( ATTR_NAME ); 176 } 177 178 setAttribute( META_NAME, name ); 179 } 180 181 private void discoverLifecycleType() 182 { 183 final DocletTag avalonLifecycle = m_javaClass.getTagByName( TAG_LIFESTYLE ); 184 final DocletTag fortressHandler = m_javaClass.getTagByName( TAG_HANDLER ); 185 String lifecycle = null; 186 String handler = null; 187 188 if ( avalonLifecycle == null && fortressHandler == null ) 189 { 190 final Type[] interfaces = m_javaClass.getImplements(); 191 for ( int i = 0; i < interfaces.length && handler != null; i++ ) 192 { 193 if ( interfaces[i].getClass().getName().equals( THREAD_SAFE ) ) 194 { 195 handler = MetaInfoEntry.THREADSAFE_HANDLER; 196 } 197 else if ( interfaces[i].getClass().getName().equals( POOLABLE ) || 198 interfaces[i].getClass().getName().equals( RECYCLABLE ) ) 199 { 200 handler = MetaInfoEntry.POOLABLE_HANDLER; 201 } 202 else if ( interfaces[i].getClass().getName().equals( SINGLE_THREADED ) ) 203 { 204 handler = MetaInfoEntry.FACTORY_HANDLER; 205 } 206 } 207 } 208 209 if ( null != avalonLifecycle ) { 211 lifecycle = stripQuotes( avalonLifecycle.getNamedParameter( ATTR_TYPE ) ); 212 } 213 else if ( null != fortressHandler ) { 215 handler = stripQuotes( fortressHandler.getNamedParameter( ATTR_TYPE ) ); 216 } 217 else { 219 handler = MetaInfoEntry.PER_THREAD_HANDLER; 220 } 221 222 if ( null != lifecycle ) setAttribute( TAG_LIFESTYLE, lifecycle ); 223 if ( null != handler ) setAttribute( TAG_HANDLER, handler ); 224 } 225 226 231 public String getType() 232 { 233 return m_javaClass.getFullyQualifiedName(); 234 } 235 236 public Iterator getDependencyNames() 237 { 238 return m_dependencyNames.iterator(); 239 } 240 241 public Iterator getServiceNames() 242 { 243 return m_serviceNames.iterator(); 244 } 245 246 251 public void addDependency( Service service ) 252 { 253 if ( !m_dependencies.contains( service ) ) 254 { 255 m_dependencies.add( service ); 256 } 257 } 258 259 public Vertex getVertex() 260 { 261 if ( m_vertex.getDependencies().size() != 0 ) 262 { 263 Iterator it = m_dependencies.iterator(); 264 while ( it.hasNext() ) 265 { 266 Service service = (Service) it.next(); 267 268 Iterator cit = service.getComponents(); 269 while ( cit.hasNext() ) 270 { 271 Component component = (Component) cit.next(); 272 m_vertex.addDependency( component.getVertex() ); 273 } 274 } 275 } 276 return m_vertex; 277 } 278 279 285 public void setAttribute( final String name, final String value ) 286 { 287 m_attributes.setProperty( name, value ); 288 } 289 290 296 public void serialize( final File rootDir ) throws IOException 297 { 298 final String fileName = getType().replace( '.', '/' ).concat( ".meta" ); 299 final String depsName = getType().replace( '.', '/' ).concat( ".deps" ); 300 File output = new File ( rootDir, fileName ); 301 FileOutputStream writer = null; 302 303 try 304 { 305 writer = new FileOutputStream ( output ); 306 m_attributes.store( writer, "Meta information for " + getType() ); 307 308 if ( m_dependencies.size() > 0 ) 309 { 310 writer.close(); 311 output = new File ( rootDir, depsName ); 312 writer = new FileOutputStream ( output ); 313 314 Iterator it = m_dependencies.iterator(); 315 while ( it.hasNext() ) 316 { 317 Service service = (Service) it.next(); 318 String name = service.getType() + "\n"; 319 writer.write( name.getBytes() ); 320 } 321 } 322 } 323 finally 324 { 325 if ( null != writer ) 326 { 327 writer.close(); 328 } 329 } 330 } 331 332 private String stripQuotes( final String value ) 333 { 334 if ( null == value ) return null; 335 if ( value.length() < 2 ) return value; 336 337 String retVal = value.trim(); 338 339 if ( retVal.startsWith( "\"" ) && retVal.endsWith( "\"" ) ) 340 { 341 retVal = retVal.substring( 1, retVal.length() - 1 ); 342 } 343 344 return retVal; 345 } 346 347 353 protected String resolveClassName( final JavaSource sourceCode, final String serviceName ) 354 { 355 if ( null == sourceCode ) 356 { 357 return null; 358 } 359 if ( null == serviceName ) 360 { 361 throw new IllegalStateException ( "The serviceName parameter was null." ); 364 } 365 366 final String className = stripQuotes( serviceName ); 367 368 if ( className != null || className.length() > 0 ) 369 { 370 if ( className.indexOf( '.' ) < 0 ) 371 { 372 String checkName = checkPackage(sourceCode, sourceCode.getPackage(), className); 373 if ( ! checkName.equals(className) ) return checkName; 374 375 String [] imports = sourceCode.getImports(); 376 for ( int t = 0; t < imports.length; t++ ) 377 { 378 checkName = checkImport( sourceCode, imports[t], className); 379 if ( ! checkName.equals( className ) ) return checkName; 380 } 381 } 382 } 383 384 return className; 385 } 386 387 private String checkImport ( final JavaSource sourceCode, final String type, final String className) 388 { 389 final String tail = type.substring( type.lastIndexOf( '.' ) + 1 ); 390 391 if ( tail.equals( className ) ) 392 { 393 return type; 394 } 395 else if ( tail.equals( "*" ) ) 396 { 397 final String pack = type.substring( 0, type.lastIndexOf( '.' ) ); 398 399 String checkName = checkPackage( sourceCode, pack, className ); 400 if ( !checkName.equals( className ) ) return checkName; 401 } 402 403 return className; 404 } 405 406 private String checkPackage( final JavaSource sourceCode, final String pack, final String serviceName ) 407 { 408 String className = serviceName; 409 final JavaClass klass = sourceCode.getClassLibrary().getClassByName( pack + "." + serviceName ); 410 if ( null != klass ) 411 className = klass.getFullyQualifiedName(); 412 return className; 413 } 414 } 415 | Popular Tags |