KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > avalon > meta > info > ant > MetaTask


1 /*
2
3  ============================================================================
4                    The Apache Software License, Version 1.1
5  ============================================================================
6
7  Copyright (C) 2002-2003 The Apache Software Foundation. All rights reserved.
8
9  Redistribution and use in source and binary forms, with or without modifica-
10  tion, are permitted provided that the following conditions are met:
11
12  1. Redistributions of source code must retain the above copyright notice,
13     this list of conditions and the following disclaimer.
14
15  2. Redistributions in binary form must reproduce the above copyright notice,
16     this list of conditions and the following disclaimer in the documentation
17     and/or other materials provided with the distribution.
18
19  3. The end-user documentation included with the redistribution, if any, must
20     include the following acknowledgment: "This product includes software
21     developed by the Apache Software Foundation (http://www.apache.org/)."
22     Alternately, this acknowledgment may appear in the software itself, if
23     and wherever such third-party acknowledgments normally appear.
24
25  4. The names "Jakarta", "Apache Avalon", "Avalon Framework" and
26     "Apache Software Foundation" must not be used to endorse or promote
27     products derived from this software without prior written
28     permission. For written permission, please contact apache@apache.org.
29
30  5. Products derived from this software may not be called "Apache", nor may
31     "Apache" appear in their name, without prior written permission of the
32     Apache Software Foundation.
33
34  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
35  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
36  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
37  APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
38  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
39  DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
40  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
41  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
43  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44
45  This software consists of voluntary contributions made by many individuals
46  on behalf of the Apache Software Foundation. For more information on the
47  Apache Software Foundation, please see <http://www.apache.org/>.
48 */

49
50 package org.apache.avalon.meta.info.ant;
51
52 import java.io.File JavaDoc;
53 import java.io.FileOutputStream JavaDoc;
54 import java.io.IOException JavaDoc;
55 import java.io.OutputStream JavaDoc;
56
57 import org.apache.avalon.meta.info.Service;
58 import org.apache.avalon.meta.info.Type;
59 import org.apache.avalon.meta.info.writer.SerializedServiceWriter;
60 import org.apache.avalon.meta.info.writer.SerializedTypeWriter;
61 import org.apache.avalon.meta.info.writer.ServiceWriter;
62 import org.apache.avalon.meta.info.writer.TypeWriter;
63 import org.apache.avalon.meta.info.writer.XMLServiceWriter;
64 import org.apache.avalon.meta.info.writer.XMLTypeWriter;
65 import org.apache.avalon.meta.info.builder.tags.TypeTag;
66 import org.apache.avalon.meta.info.builder.tags.ServiceTag;
67
68 import org.apache.tools.ant.BuildException;
69
70
71 import com.thoughtworks.qdox.ant.AbstractQdoxTask;
72 import com.thoughtworks.qdox.model.JavaClass;
73
74 /**
75  * Generate a meta info model from javadoc tags.
76  *
77  * @author <a HREF="mailto:dev@avalon.apache.org">Avalon Development Team</a>
78  * @version $Revision: 1.9 $ $Date: 2003/09/09 22:00:43 $
79  */

80 public class MetaTask
81     extends AbstractQdoxTask
82 {
83    /**
84     * XML output type code.
85     */

86     public static final int XML_TYPE = 0;
87
88    /**
89     * Serial output type code.
90     */

91     public static final int SER_TYPE = 1;
92
93     /**
94      * A utility object that writes out info as xml files.
95      */

96     private static final TypeWriter XML_WRITER = new XMLTypeWriter();
97
98     /**
99      * A utility object that writes out info as serialized object files.
100      */

101     private static final TypeWriter SERIAL_WRITER = new SerializedTypeWriter();
102
103     /**
104      * A utility object that writes out a service as xml files.
105      */

106     private static final ServiceWriter XML_SERVICE_WRITER = new XMLServiceWriter();
107
108     /**
109      * A utility object that writes out a service as serialized object files.
110      */

111     private static final ServiceWriter SERIAL_SERVICE_WRITER = new SerializedServiceWriter();
112
113     /**
114      * The destination directory for metadata files.
115      */

116     private File JavaDoc m_destDir;
117
118     /**
119      * Variable that indicates the output type.
120      */

121     private int m_format;
122
123     /**
124      * The preferred postfix value.
125      */

126     private String JavaDoc m_postfix = ".xinfo";
127
128     /**
129      * Variable that indicates whether the output
130      * will be generated only when the source file is
131      * newer than the destination file.
132      */

133     private boolean m_force = true;
134
135     /**
136      * Set the desitation directory to generate output files to.
137      *
138      * @param destDir The destination directory
139      */

140     public void setDestDir( final File JavaDoc destDir )
141     {
142         m_destDir = destDir;
143     }
144
145     /**
146      * Specify the output format. Must be one of xml or serialized.
147      *
148      * @param format the output format
149      */

150     public void setFormat( final FormatEnum format )
151     {
152         m_format = format.getTypeCode();
153     }
154
155     /**
156      * Set force to be true indicating that destination
157      * files should always be regenerated.
158      *
159      * @param force the flag for forcing output
160      */

161     public void setForce( boolean force )
162     {
163         m_force = force;
164     }
165
166     /**
167      * Set the file type to be used for meta info type
168      * documents. May be one of "xinfo" or "xtype".
169      *
170      * @param postfix the postfix value
171      */

172     public void setPostfix( String JavaDoc postfix )
173     {
174         if( postfix.equalsIgnoreCase( "xtype" )
175           || postfix.equalsIgnoreCase( "xinfo" ) )
176         {
177             m_postfix = "." + postfix;
178         }
179         else
180         {
181             final String JavaDoc error =
182               "Illegal postfix value: " + postfix + ". "
183               + "Recognized values include 'xinfo' and 'xtype'.";
184             throw new BuildException( error );
185         }
186     }
187
188     /**
189      * Execute generator task.
190      * @exception BuildException if a build error occurs
191      */

192     public void execute()
193         throws BuildException
194     {
195         validate();
196
197         final String JavaDoc message =
198           "Writing descriptors using '"
199           + getOutputDescription()
200           + "' format.";
201         log( message );
202
203         super.execute();
204
205         try
206         {
207             Counter counter = writeMetaData();
208             final String JavaDoc update =
209               "Processed " + counter.getTypes() + " Types and "
210               + counter.getServices() + " Services from a total of "
211               + counter.getCount() + " classes.";
212             log( update );
213         }
214         catch( final Exception JavaDoc e )
215         {
216             throw new BuildException( e.toString(), e );
217         }
218     }
219
220     /**
221      * Validate that the parameters are valid.
222      */

223     private void validate()
224     {
225         if( null == m_destDir )
226         {
227             final String JavaDoc message =
228                 "DestDir (" + m_destDir + ") not specified";
229             throw new BuildException( message );
230         }
231         if( !m_destDir.isDirectory() )
232         {
233             final String JavaDoc message =
234                 "DestDir (" + m_destDir + ") is not a directory.";
235             throw new BuildException( message );
236         }
237
238         if( !m_destDir.exists() && !m_destDir.mkdirs() )
239         {
240             final String JavaDoc message =
241                 "DestDir (" + m_destDir + ") could not be created.";
242             throw new BuildException( message );
243         }
244     }
245
246     /**
247      * Return a description of output format to print as debug message.
248      *
249      * @return the output formats descriptive name
250      */

251     private String JavaDoc getOutputDescription()
252     {
253         if( SER_TYPE == m_format )
254         {
255             return "serial";
256         }
257         else
258         {
259             return "xml";
260         }
261     }
262
263     /**
264      * Output the metadata files.
265      * @return the count holder
266      * @throws IOException If a problem writing output
267      */

268     private Counter writeMetaData() throws IOException JavaDoc
269     {
270         int services = 0;
271         int types = 0;
272         final int size = allClasses.size();
273         for( int i = 0; i < size; i++ )
274         {
275             final JavaClass javaClass = (JavaClass)allClasses.get( i );
276             if( javaClass.isInterface() )
277             {
278                 Service service = new ServiceTag( javaClass ).getService();
279                 if( service == null )
280                 {
281                     continue;
282                 }
283
284                 services++;
285
286                 //
287
// it is a service so we can fo ahead and build a
288
// a service descriptor
289
//
290

291                 final String JavaDoc classname = javaClass.getFullyQualifiedName();
292                 final File JavaDoc source = javaClass.getParentSource().getFile();
293                 final File JavaDoc dest = getOutputFileForService( classname );
294
295                 if( !m_force )
296                 {
297                     if( dest.exists()
298                       && dest.lastModified() >= source.lastModified() )
299                     {
300                         continue;
301                     }
302                 }
303                 final File JavaDoc parent = dest.getParentFile();
304                 if( null != parent )
305                 {
306                     if( !parent.exists() && !parent.mkdirs() )
307                     {
308                         final String JavaDoc message =
309                             "Failed to create output directory: " + parent;
310                         throw new BuildException( message );
311                     }
312                 }
313                 writeService( service );
314             }
315             else
316             {
317                 Type type = new TypeTag( javaClass ).getType();
318                 if( type == null )
319                 {
320                     continue;
321                 }
322
323                 types++;
324
325                 //
326
// it is a type implementation so we can fo ahead and build a
327
// a type descriptor
328
//
329

330                 final String JavaDoc classname = javaClass.getFullyQualifiedName();
331                 final File JavaDoc source = javaClass.getParentSource().getFile();
332                 final File JavaDoc dest = getOutputFileForClass( classname );
333
334                 if( !m_force )
335                 {
336                     if( dest.exists()
337                       && dest.lastModified() >= source.lastModified() )
338                     {
339                         continue;
340                     }
341                 }
342                 final File JavaDoc parent = dest.getParentFile();
343                 if( null != parent )
344                 {
345                     if( !parent.exists() && !parent.mkdirs() )
346                     {
347                         final String JavaDoc message =
348                             "Failed to create output directory: " + parent;
349                         throw new BuildException( message );
350                     }
351                 }
352                 writeType( type );
353             }
354         }
355         return new Counter( size, services, types );
356     }
357
358     /**
359      * Write Service to a file.
360      *
361      * @param service the Service descriptor
362      * @throws IOException if an error occurs while writing to file
363      */

364     private void writeService( final Service service )
365         throws IOException JavaDoc
366     {
367         final String JavaDoc fqn = service.getReference().getClassname();
368         final File JavaDoc file = getOutputFileForService( fqn );
369         final OutputStream JavaDoc outputStream = new FileOutputStream JavaDoc( file );
370         try
371         {
372             getServiceWriter().writeService( service, outputStream );
373         }
374         catch( final Exception JavaDoc e )
375         {
376             log( "Error writing service to " + file + ". Cause: " + e );
377         }
378         finally
379         {
380             shutdownStream( outputStream );
381         }
382     }
383
384     /**
385      * Write Type to a file.
386      *
387      * @param type the Type descriptor
388      * @throws IOException if unable to write info out
389      */

390     private void writeType( final Type type )
391         throws IOException JavaDoc
392     {
393         final String JavaDoc fqn = type.getInfo().getClassname();
394         final File JavaDoc file = getOutputFileForClass( fqn );
395         final OutputStream JavaDoc outputStream = new FileOutputStream JavaDoc( file );
396         try
397         {
398             getTypeWriter().writeType( type, outputStream );
399         }
400         catch( final Exception JavaDoc e )
401         {
402             log( "Error writing " + file + ". Cause: " + e );
403         }
404         finally
405         {
406             shutdownStream( outputStream );
407         }
408     }
409
410     /**
411      * Return the correct info writer depending on
412      * what format the info will be output as. The
413      * implementation will return either a servialized
414      * wtiter or an xml writer based on the format
415      * established by the client.
416      *
417      * @return the TypeWriter to output info with
418      */

419     private TypeWriter getTypeWriter()
420     {
421         if( SER_TYPE == m_format )
422         {
423             return SERIAL_WRITER;
424         }
425         else
426         {
427             return XML_WRITER;
428         }
429     }
430
431
432     /**
433      * Return the correct service writer depending on
434      * what format the service will be output as. The
435      * implementation will return either a serial
436      * wtiter or an xml writer based on the format
437      * established by the client.
438      *
439      * @return the ServiceWriter to output info with
440      */

441     private ServiceWriter getServiceWriter()
442     {
443         if( SER_TYPE == m_format )
444         {
445             return SERIAL_SERVICE_WRITER;
446         }
447         else
448         {
449             return XML_SERVICE_WRITER;
450         }
451     }
452
453     /**
454      * Determine the file for the {@link Task}.
455      *
456      * @param classname the fully qualified name of file to generate
457      * @return the file for info
458      * @throws IOException if unable to determine base file
459      */

460     private File JavaDoc getOutputFileForClass( final String JavaDoc classname )
461         throws IOException JavaDoc
462     {
463         String JavaDoc filename =
464             classname.replace( '.', File.separatorChar );
465
466         if( SER_TYPE == m_format )
467         {
468             filename += ".stype";
469         }
470         else
471         {
472             filename += m_postfix;
473         }
474         return new File JavaDoc( m_destDir, filename ).getCanonicalFile();
475     }
476
477     /**
478      * Determine the file for specified {@link Service}.
479      *
480      * @param classname the fully qualified name of file to generate
481      * @return the file for the service descriptor
482      * @throws IOException if unable to determine base file
483      */

484     private File JavaDoc getOutputFileForService( final String JavaDoc classname )
485         throws IOException JavaDoc
486     {
487         String JavaDoc filename =
488             classname.replace( '.', File.separatorChar );
489
490         if( SER_TYPE == m_format )
491         {
492             filename += ".sservice";
493         }
494         else
495         {
496             filename += ".xservice";
497         }
498         return new File JavaDoc( m_destDir, filename ).getCanonicalFile();
499     }
500
501
502     /**
503      * Close the specified output stream.
504      *
505      * @param outputStream the output stream
506      */

507     private void shutdownStream( final OutputStream JavaDoc outputStream )
508     {
509         if( null != outputStream )
510         {
511             try
512             {
513                 outputStream.close();
514             }
515             catch( IOException JavaDoc e )
516             {
517                 // ignore
518
}
519         }
520     }
521
522     /**
523      * Return the destination directory in which files are generated.
524      *
525      * @return the destination directory in which files are generated.
526      */

527     protected final File JavaDoc getDestDir()
528     {
529         return m_destDir;
530     }
531
532    /**
533     * Internal utility class that aggregates the number of services, the
534     * number of types, and the total component count.
535     */

536     private class Counter
537     {
538         private int m_services;
539         private int m_types;
540         private int m_count;
541         Counter( int count, int services, int types )
542         {
543             m_count = count;
544             m_services = services;
545             m_types = types;
546         }
547         protected int getServices()
548         {
549             return m_services;
550         }
551         protected int getTypes()
552         {
553             return m_types;
554         }
555         protected int getCount()
556         {
557             return m_count;
558         }
559     }
560 }
561
Popular Tags