001 /*
002 * Copyright (c) 2005 Stephen J. McConnell
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
013 * implied.
014 *
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package net.dpml.metro.tools;
020
021 import java.io.File;
022 import java.io.FileFilter;
023 import java.io.FileWriter;
024 import java.io.IOException;
025 import java.net.URI;
026 import java.util.List;
027 import java.util.ArrayList;
028 import java.util.LinkedList;
029 import java.util.Hashtable;
030 import java.util.Arrays;
031 import java.util.Map;
032
033 import net.dpml.metro.info.EntryDescriptor;
034 import net.dpml.metro.info.Type;
035 import net.dpml.metro.info.ContextDescriptor;
036 import net.dpml.metro.info.ServiceDescriptor;
037
038 import net.dpml.metro.builder.ComponentTypeDecoder;
039
040 import net.dpml.transit.Transit;
041
042 import net.dpml.util.Resolver;
043 import net.dpml.util.SimpleResolver;
044
045 import org.apache.tools.ant.Task;
046 import org.apache.tools.ant.BuildException;
047 import org.apache.tools.ant.Project;
048 import org.apache.tools.ant.DirectoryScanner;
049 import org.apache.tools.ant.taskdefs.Copy;
050 import org.apache.tools.ant.types.FileSet;
051
052 /**
053 * Create a set of html reports about component types.
054 *
055 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
056 * @version 1.1.3
057 */
058 public class CatalogTask extends Task
059 {
060 private static final ComponentTypeDecoder COMPONENT_TYPE_DECODER =
061 new ComponentTypeDecoder();
062
063 private File m_work;
064 private File m_destination;
065 private String m_style;
066 private String m_title;
067 private List m_filesets = new LinkedList();
068 private Map m_packages = new Hashtable();
069
070 /**
071 * Set the final destination directory for generated HTML content.
072 * @param destination the destination directory
073 */
074 public void setDest( File destination )
075 {
076 m_destination = destination;
077 }
078
079 /**
080 * Optional override of the XSL stylesheet used to transform type descriptors.
081 * @param style the XSL transformation to use
082 */
083 public void setStyle( String style )
084 {
085 m_style = style;
086 }
087
088 /**
089 * Optional override of the index page title.
090 * @param title the index page title
091 */
092 public void setTitle( String title )
093 {
094 m_title = title;
095 }
096
097 /**
098 * Add a fileset to the set of filesets definted within the catalog generation. If no
099 * filesets are added the default behaviour will be resolve against component types
100 * declared under the current projects ${basedir}/target/classes directory.
101 *
102 * @param set the fileset to add
103 */
104 public void addFileset( FileSet set )
105 {
106 m_filesets.add( set );
107 }
108
109 /**
110 * Task initialization.
111 */
112 public void init()
113 {
114 String targetDirPath = getProject().getProperty( "project.target.dir" );
115 File target = new File( targetDirPath );
116 File reports = new File( target, "reports" );
117 File types = new File( reports, "catalog" );
118 m_work = types;
119 }
120
121 /**
122 * Task execution during which all component types declared in the current project or referenced
123 * by nested filesets will be used as the source defintions fro the generation of a Type catalog.
124 */
125 public void execute()
126 {
127 log( "building catalog index" );
128 Project proj = getProject();
129 File[] types = getTypes();
130 log( "Catalog type count: " + types.length );
131 if( types.length == 0 )
132 {
133 return;
134 }
135 else
136 {
137 File reports = getWorkingDirectory();
138 //File html = new File( reports, "html" );
139 File html = reports;
140 html.mkdirs();
141
142 File css = new File( Transit.DPML_PREFS, "dpml/metro/csss/type.css" );
143 File stylesheet = new File( html, "stylesheet.css" );
144 final Copy copy = (Copy) getProject().createTask( "copy" );
145 copy.setFile( css );
146 copy.setTofile( stylesheet );
147 copy.execute();
148
149 for( int i=0; i < types.length; i++ )
150 {
151 File type = types[i];
152 processType( reports, type );
153 }
154
155 createCatalog( html );
156 }
157 }
158
159 /**
160 * A side effect of type processing is the population of the m_packages map. The
161 * map keys are package names and the map values are list of types within the
162 * respective package. The keys constitute the package list and for each package
163 * we construct an index of types within that package.
164 *
165 * @param root the root html directory
166 */
167 private void createCatalog( File root )
168 {
169 createIndex( root );
170 createPackagesIndex( root );
171 createTypesIndex( root );
172 createOverviewPage( root );
173 }
174
175 /**
176 * Create the list of all types.
177 * @param root the root html directory
178 */
179 private void createTypesIndex( File root )
180 {
181 File index = new File( root, "types.html" );
182 try
183 {
184 FileWriter writer = new FileWriter( index );
185 writer.write( "<html>" );
186 writer.write( "\n <head>" );
187 writer.write( "\n <META http-equiv=\"Content-Type\" content=\"text/html; charset=US-ASCII\">" );
188 writer.write( "\n <title>Package Index</title>" );
189 writer.write( "\n <link href=\"stylesheet.css\" type=\"text/css\" rel=\"stylesheet\"/>" );
190 writer.write( "\n </head>" );
191 writer.write( "\n <body>" );
192 writer.write( "\n <p><b>Overview</b></p>" );
193 writer.write( "\n <p><a href=\"packages-overview.html\" target=\"typeFrame\">All Packages</a></p>" );
194 writer.write( "\n <p><b>All Types</b></p>" );
195 writer.write( "\n <table>" );
196
197 List[] lists = (List[]) m_packages.values().toArray( new List[0] );
198 for( int i=0; i < lists.length; i++ )
199 {
200 List list = lists[i];
201 Type[] types = (Type[]) list.toArray( new Type[0] );
202 for( int j=0; j < types.length; j++ )
203 {
204 Type type = types[j];
205 String path = type.getInfo().getClassname().replace( '.', '/' );
206 String classname = getClassName( type );
207 String filename = path + ".html";
208 writer.write( "\n <tr><td><a href=\"" );
209 writer.write( filename );
210 writer.write( "\" target=\"typeFrame\">" );
211 writer.write( classname );
212 writer.write( "</a></td></tr>" );
213 }
214 }
215 writer.write( "\n </table>" );
216 writer.write( "\n </body>" );
217 writer.write( "\n</html>" );
218 writer.close();
219 }
220 catch( Exception e )
221 {
222 final String error =
223 "Internal error while attempting to create packages list.";
224 throw new BuildException( error, e, getLocation() );
225 }
226 }
227
228 private void createOverviewPage( File root )
229 {
230 File overview = new File( root, "packages-overview.html" );
231 try
232 {
233 FileWriter writer = new FileWriter( overview );
234 writer.write( "<html>" );
235 writer.write( "\n <head>" );
236 writer.write( "\n <META http-equiv=\"Content-Type\" content=\"text/html; charset=US-ASCII\">" );
237 writer.write( "\n <title>Type Packages List</title>" );
238 writer.write( "\n <link href=\"stylesheet.css\" type=\"text/css\" rel=\"stylesheet\"/>" );
239 writer.write( "\n </head>" );
240 writer.write( "\n <body>" );
241
242 //
243 // add menu containing packages overview links
244 //
245
246 writer.write( "\n <table class=\"menubar\">" );
247 writer.write( "\n <tr>" );
248 writer.write( "<td class=\"package\"><a class=\"package\" href=\"packages-overview.html\">" );
249 writer.write( "overview" );
250 writer.write( "</a></td>" );
251 writer.write( "\n </tr>" );
252 writer.write( "\n </table>" );
253
254 writer.write( "\n <p class=\"title\">Overview</p>" );
255
256 writer.write( "\n <table>" );
257 writer.write( "\n <tr><th>Package</th><th>Components</th></tr>" );
258
259 boolean flag = true;
260 Object[] keys = m_packages.keySet().toArray();
261 for( int i=0; i < keys.length; i++ )
262 {
263 String name = (String) keys[i];
264 createPackageOverview( root, name );
265 List list = getPackageList( name );
266 if( flag )
267 {
268 writer.write( "\n <tr class=\"p-even\">" );
269 }
270 else
271 {
272 writer.write( "\n <tr class=\"p-odd\">" );
273 }
274 flag = !flag;
275
276 writer.write( "<td><a href=\"" );
277 String path = name.replace( '.', '/' );
278 writer.write( path + "/overview.html\" target=\"typeFrame\">" );
279 writer.write( name );
280 writer.write( "</a></td>" );
281 writer.write( "<td>" );
282 Type[] types = (Type[]) list.toArray( new Type[0] );
283 for( int j=0; j < types.length; j++ )
284 {
285 Type type = types[j];
286 String classname = getClassName( type );
287 String filename = type.getInfo().getClassname().replace( '.', '/' ) + ".html";
288 if( j > 0 )
289 {
290 writer.write( ", " );
291 }
292 writer.write( "<a href=\"" );
293 writer.write( filename );
294 writer.write( "\" target=\"typeFrame\">" );
295 writer.write( classname );
296 writer.write( "</a>" );
297 }
298 writer.write( "</td>" );
299 writer.write( "</tr>" );
300 }
301
302 writer.write( "\n </table>" );
303 writer.write( "\n </body>" );
304 writer.write( "\n</html>" );
305 writer.close();
306 }
307 catch( Exception e )
308 {
309 final String error =
310 "Internal error while attempting to create packages overview.";
311 throw new BuildException( error, e, getLocation() );
312 }
313 }
314
315 private void createPackagesIndex( File root )
316 {
317 File packages = new File( root, "packages.html" );
318 try
319 {
320 FileWriter writer = new FileWriter( packages );
321 writer.write( "<html>" );
322 writer.write( "\n <head>" );
323 writer.write( "\n <META http-equiv=\"Content-Type\" content=\"text/html; charset=US-ASCII\">" );
324 writer.write( "\n <title>Type Packages List</title>" );
325 writer.write( "\n <link href=\"stylesheet.css\" type=\"text/css\" rel=\"stylesheet\">" );
326 writer.write( "\n </head>" );
327 writer.write( "\n <body>" );
328
329 String title = getTitle();
330
331 writer.write( "\n <table>" );
332 writer.write( "\n <tr><td class=\"title\">" + title + "</td></tr>" );
333 writer.write( "\n </table>" );
334
335 writer.write( "\n <p><a href=\"types.html\" target=\"typeListFrame\">All Types</a></p>" );
336 writer.write( "\n <p><b>Packages</b></p>" );
337 writer.write( "\n <table>" );
338
339 Object[] keys = m_packages.keySet().toArray();
340 for( int i=0; i < keys.length; i++ )
341 {
342 String name = (String) keys[i];
343 writer.write( "\n <tr><td><a href=\"" );
344 String path = name.replace( '.', '/' );
345 writer.write( path + "/package-index.html\" target=\"typeListFrame\">" );
346 writer.write( name );
347 writer.write( "</a></td></tr>" );
348 createPackageIndex( root, name );
349 }
350
351 writer.write( "\n </table>" );
352 writer.write( "\n </body>" );
353 writer.write( "\n</html>" );
354 writer.close();
355 }
356 catch( Exception e )
357 {
358 final String error =
359 "Internal error while attempting to create packages list.";
360 throw new BuildException( error, e, getLocation() );
361 }
362 }
363
364 private void createPackageIndex( File root, String name )
365 {
366 String path = name.replace( '.', '/' );
367 File dir = new File( root, path );
368 dir.mkdirs();
369 File index = new File( dir, "package-index.html" );
370 String offset = getOffset( name );
371 try
372 {
373 FileWriter writer = new FileWriter( index );
374 writer.write( "<html>" );
375 writer.write( "\n <head>" );
376 writer.write( "\n <META http-equiv=\"Content-Type\" content=\"text/html; charset=US-ASCII\">" );
377 writer.write( "\n <title>Package Index</title>" );
378 writer.write( "\n <link href=\"" + offset + "/stylesheet.css\" type=\"text/css\" rel=\"stylesheet\"/>" );
379 writer.write( "\n </head>" );
380 writer.write( "\n <body>" );
381 writer.write( "\n <p><b>Overview</b></p>" );
382 writer.write( "\n <p><a href=\"overview.html\" target=\"typeFrame\">" + name + "</a></p>" );
383 writer.write( "\n <p><b>Types</b></p>" );
384 writer.write( "\n <table>" );
385
386 List list = getPackageList( name );
387 Type[] types = (Type[]) list.toArray( new Type[0] );
388 for( int i=0; i < types.length; i++ )
389 {
390 Type type = types[i];
391 String classname = getClassName( type );
392 String filename = classname + ".html";
393 writer.write( "\n <tr><td><a href=\"" );
394 writer.write( filename );
395 writer.write( "\" target=\"typeFrame\">" );
396 writer.write( classname );
397 writer.write( "</a></td></tr>" );
398 }
399 writer.write( "\n </table>" );
400 writer.write( "\n </body>" );
401 writer.write( "\n</html>" );
402 writer.close();
403 }
404 catch( Exception e )
405 {
406 final String error =
407 "Internal error while attempting to create packages list.";
408 throw new BuildException( error, e, getLocation() );
409 }
410 }
411
412 private void createPackageOverview( File root, String name )
413 {
414 String path = name.replace( '.', '/' );
415 File dir = new File( root, path );
416 dir.mkdirs();
417 File index = new File( dir, "overview.html" );
418 String offset = getOffset( name );
419 try
420 {
421 FileWriter writer = new FileWriter( index );
422 writer.write( "<html>" );
423 writer.write( "\n <head>" );
424 writer.write( "\n <META http-equiv=\"Content-Type\" content=\"text/html; charset=US-ASCII\">" );
425 writer.write( "\n <title>Package Overview: " + name + "</title>" );
426 writer.write( "\n <link href=\"" + offset + "/stylesheet.css\" type=\"text/css\" rel=\"stylesheet\"/>" );
427 writer.write( "\n </head>" );
428 writer.write( "\n <body>" );
429
430 //
431 // add the menubar containing the link to the all packages overview
432 //
433
434 writer.write( "\n <table class=\"menubar\">" );
435 writer.write( "\n <tr>" );
436 writer.write( "<td class=\"package\"><a class=\"package\" href=\"" + offset + "/packages-overview.html\">" );
437 writer.write( "overview" );
438 writer.write( "</a></td>" );
439 writer.write( "<td class=\"package-selected\"><a class=\"package-selected\" href=\"overview.html\">" );
440 writer.write( name );
441 writer.write( "</a></td>" );
442 writer.write( "\n </tr>" );
443 writer.write( "\n </table>" );
444
445 //
446 // add the package name
447 //
448
449 writer.write( "\n <table>" );
450 writer.write( "\n <tr><td class=\"title\">" + name + "</td></tr>" );
451 writer.write( "\n </table>" );
452
453 writer.write( "\n <table width=\"100%\">" );
454 writer.write( "\n <tr><th>Type</th><th>Name</th><th>Lifestyle</th></tr>" );
455
456 //
457 // list all component types in the package
458 //
459
460 boolean flag = true;
461 List list = getPackageList( name );
462 Type[] types = (Type[]) list.toArray( new Type[0] );
463 for( int i=0; i < types.length; i++ )
464 {
465 Type type = types[i];
466 if( flag )
467 {
468 writer.write( "\n <tr class=\"p-even\">" );
469 }
470 else
471 {
472 writer.write( "\n <tr class=\"p-odd\">" );
473 }
474 flag = !flag;
475
476 String classname = getClassName( type );
477 String filename = classname + ".html";
478 writer.write( "\n <td><a href=\"" );
479 writer.write( filename );
480 writer.write( "\" target=\"typeFrame\">" );
481 writer.write( classname );
482 writer.write( "</a>" );
483 writer.write( "\n </td>" );
484
485 writer.write( "\n <td>" );
486 writer.write( type.getInfo().getName() );
487 writer.write( "\n </td>" );
488
489 writer.write( "\n <td>" );
490 writer.write( type.getInfo().getLifestylePolicy().getName() );
491 writer.write( "\n </td>" );
492
493 writer.write( "\n </tr>" );
494 }
495 writer.write( "\n </table>" );
496 writer.write( "\n </body>" );
497 writer.write( "\n</html>" );
498 writer.close();
499 }
500 catch( Exception e )
501 {
502 final String error =
503 "Internal error while attempting to create packages list.";
504 throw new BuildException( error, e, getLocation() );
505 }
506 }
507
508 private void createTypePage( File root, Type type )
509 {
510 File html = getReportDestination( root, type, "html" );
511 html.getParentFile().mkdirs();
512 String classname = type.getInfo().getClassname();
513 String cname = getClassName( type );
514 String packagename = getPackageName( type );
515 String offset = getOffset( packagename );
516 List packageList = getPackageList( packagename );
517 packageList.add( type );
518 try
519 {
520 FileWriter writer = new FileWriter( html );
521 writer.write( "<html>" );
522 writer.write( "\n <head>" );
523 writer.write( "\n <META http-equiv=\"Content-Type\" content=\"text/html; charset=US-ASCII\">" );
524 writer.write( "\n <title>Component Type: " + classname + "</title>" );
525 writer.write( "\n <link href=\"" + offset + "/stylesheet.css\" type=\"text/css\" rel=\"stylesheet\"/>" );
526 writer.write( "\n </head>" );
527 writer.write( "\n <body>" );
528
529 //
530 // add menu containing packages and package overview links
531 //
532
533 writer.write( "\n <table class=\"menubar\">" );
534 writer.write( "\n <tr>" );
535 writer.write( "<td class=\"package\"><a class=\"package\" href=\""
536 + offset + "/packages-overview.html\">" );
537 writer.write( "overview" );
538 writer.write( "</a></td>" );
539 writer.write( "<td class=\"package\"><a class=\"package\" href=\"overview.html\">" );
540 writer.write( packagename );
541 writer.write( "</a></td>" );
542 writer.write( "<td class=\"package-selected\">" + cname + "</td>" );
543 writer.write( "\n </tr>" );
544 writer.write( "\n </table>" );
545
546 //
547 // add component type classname as title
548 //
549
550 writer.write( "\n <table>" );
551 writer.write( "\n <tr><td class=\"type\">" + cname + "</td></tr>" );
552 writer.write( "\n </table>" );
553
554 //
555 // write out the InfoDescriptor features
556 //
557
558 writer.write( "\n <table>" );
559 writer.write( "\n <tr><td class=\"feature\">Version:</td><td>"
560 + type.getInfo().getVersion() + "</td></tr>" );
561 writer.write( "\n <tr><td class=\"feature\">Name:</td><td>"
562 + type.getInfo().getName() + "</td></tr>" );
563 writer.write( "\n <tr><td class=\"feature\">Lifestyle:</td><td>"
564 + type.getInfo().getLifestylePolicy().getName() + "</td></tr>" );
565 writer.write( "\n <tr><td class=\"feature\">Thread-Safe:</td><td>"
566 + type.getInfo().getThreadSafePolicy() + "</td></tr>" );
567 writer.write( "\n <tr><td class=\"feature\">Collection:</td><td>"
568 + type.getInfo().getCollectionPolicy().getName() + "</td></tr>" );
569 writer.write( "\n </table>" );
570
571 //
572 // write out the exported services that the component provides
573 //
574
575 ServiceDescriptor[] services = type.getServiceDescriptors();
576 writeServiceDescriptors( writer, services );
577
578 //
579 // write out the context model
580 //
581
582 boolean flag = true;
583 ContextDescriptor context = type.getContextDescriptor();
584 EntryDescriptor[] entries = context.getEntryDescriptors();
585 if( entries.length > 0 )
586 {
587 Arrays.sort( entries );
588 writer.write( "\n <p class=\"category\">Context</p>" );
589 writer.write( "\n <table width=\"100%\">" );
590 for( int j=0; j<entries.length; j++ )
591 {
592 EntryDescriptor entry = entries[j];
593 String key = entry.getKey();
594 String entryClassname = entry.getClassname();
595 String entryDisplayClassname = getDisplayClassname( entryClassname );
596 boolean optional = entry.isOptional();
597
598 if( flag )
599 {
600 writer.write( "<tr class=\"c-even\">" );
601 }
602 else
603 {
604 writer.write( "<tr class=\"c-odd\">" );
605 }
606 writer.write( "<td>" + key + "</td>" );
607 if( optional )
608 {
609 writer.write( "<td>optional</td>" );
610 }
611 else
612 {
613 writer.write( "<td>required</td>" );
614 }
615 writer.write( "<td>" + entryDisplayClassname + "</td>" );
616 writer.write( "</tr>" );
617 flag = !flag;
618 }
619 writer.write( "\n </table>" );
620 }
621
622 writer.write( "\n </body>" );
623 writer.write( "\n</html>" );
624 writer.close();
625 }
626 catch( Exception e )
627 {
628 final String error =
629 "Internal error while attempting to create type page.";
630 throw new BuildException( error, e, getLocation() );
631 }
632 }
633
634 private String getDisplayClassname( String classname )
635 {
636 if( classname.startsWith( "[L" ) )
637 {
638 if( classname.endsWith( ";" ) )
639 {
640 int n = classname.length();
641 return classname.substring( 2, n-1 ) + "[]";
642 }
643 else
644 {
645 return classname.substring( 2 ) + "[]";
646 }
647 }
648 else
649 {
650 return classname;
651 }
652 }
653
654 private void writeServiceDescriptors( FileWriter writer, ServiceDescriptor[] services ) throws IOException
655 {
656 boolean flag = true;
657 if( services.length > 0 )
658 {
659 writer.write( "\n <p class=\"category\">Services</p>" );
660 writer.write( "\n <table width=\"100%\">" );
661 for( int j=0; j < services.length; j++ )
662 {
663 String service = services[j].getClassname();
664 if( flag )
665 {
666 writer.write( "<tr class=\"even\"><td>" + service + "</td></tr>" );
667 }
668 else
669 {
670 writer.write( "<tr class=\"odd\"><td>" + service + "</td></tr>" );
671 }
672 flag = !flag;
673 }
674 writer.write( "\n </table>" );
675 }
676 }
677
678 private List getPackageList( String name )
679 {
680 List list = (List) m_packages.get( name );
681 if( null == list )
682 {
683 list = new ArrayList();
684 m_packages.put( name, list );
685 }
686 return list;
687 }
688
689 private void processType( File reports, File source )
690 {
691 log( source.toString() );
692 File htmls = reports;
693 try
694 {
695 URI uri = source.toURI();
696 Resolver resolver = new SimpleResolver();
697 Type type = COMPONENT_TYPE_DECODER.loadType( uri, resolver );
698 createTypePage( htmls, type );
699 }
700 catch( Exception e )
701 {
702 throw new BuildException( e.getMessage(), e, getLocation() );
703 }
704 }
705
706 private File getReportDestination( File dir, Type type, String suffix )
707 {
708 final String classname = type.getInfo().getClassname();
709 String path = classname.replace( '.', '/' );
710 String filename = path + "." + suffix;
711 return new File( dir, filename );
712 }
713
714 private String getClassName( Type type )
715 {
716 String path = type.getInfo().getClassname();
717 int n = path.lastIndexOf( "." );
718 if( n > -1 )
719 {
720 return path.substring( n + 1 );
721 }
722 else
723 {
724 return path;
725 }
726 }
727
728 private String getPackageName( Type type )
729 {
730 String path = type.getInfo().getClassname();
731 int n = path.lastIndexOf( "." );
732 if( n > -1 )
733 {
734 return path.substring( 0, n );
735 }
736 else
737 {
738 return "";
739 }
740 }
741
742 private String getBasePath( Type type )
743 {
744 String base = "";
745 String path = type.getInfo().getClassname();
746 while( path.indexOf( "." ) > 0 )
747 {
748 path = path.substring( path.indexOf( "." ) + 1 );
749 if( base.equals( "" ) )
750 {
751 base = "..";
752 }
753 else
754 {
755 base = base + "/..";
756 }
757 }
758 return base;
759 }
760
761 private String getOffset( String packagename )
762 {
763 String base = "..";
764 String path = packagename;
765 while( path.indexOf( "." ) > 0 )
766 {
767 path = path.substring( path.indexOf( "." ) + 1 );
768 base = base + "/..";
769 }
770 return base;
771 }
772
773 private String getStyle()
774 {
775 if( null == m_style )
776 {
777 return new File( Transit.DPML_PREFS, "metro/style/type-formatter.xsl" ).toString();
778 }
779 else
780 {
781 return m_style;
782 }
783 }
784
785 private String getTitle()
786 {
787 if( null == m_title )
788 {
789 return "DPML Metro Catalog";
790 }
791 else
792 {
793 return m_title;
794 }
795 }
796
797 private File getWorkingDirectory()
798 {
799 if( null == m_destination )
800 {
801 return m_work;
802 }
803 else
804 {
805 return m_destination;
806 }
807 }
808
809 private File[] getTypes()
810 {
811 if( m_filesets.size() == 0 )
812 {
813 String classesDirPath = getProject().getProperty( "project.target.classes.main.dir" );
814 File classes = new File( classesDirPath );
815 return getTypes( classes );
816 }
817 else
818 {
819 ArrayList list = new ArrayList();
820 Project project = getProject();
821 FileSet[] filesets = (FileSet[]) m_filesets.toArray( new FileSet[0] );
822 for( int i=0; i < filesets.length; i++ )
823 {
824 FileSet fileset = filesets[i];
825 File basedir = fileset.getDir( project );
826 DirectoryScanner ds = fileset.getDirectoryScanner( project );
827 String[] files = ds.getIncludedFiles();
828 for( int j=0; j < files.length; j++ )
829 {
830 String path = files[j];
831 File file = new File( basedir, path );
832 list.add( file );
833 }
834 }
835 return (File[]) list.toArray( new File[0] );
836 }
837 }
838
839 private File[] getTypes( File dir )
840 {
841 ArrayList list = new ArrayList();
842 getTypes( list, dir );
843 return (File[]) list.toArray( new File[0] );
844 }
845
846 private void getTypes( List list, File dir )
847 {
848 File[] types = dir.listFiles( new TypeFileFilter() );
849 for( int i=0; i<types.length; i++ )
850 {
851 list.add( types[i] );
852 }
853 File[] dirs = dir.listFiles( new DirectoryFilter() );
854 for( int i=0; i<dirs.length; i++ )
855 {
856 getTypes( list, dirs[i] );
857 }
858 }
859
860 /**
861 * Type file filter impl.
862 */
863 private static class TypeFileFilter implements FileFilter
864 {
865 /**
866 * Return true if the file is a type.
867 * @param file the file to test
868 * @return true if the file is a type
869 */
870 public boolean accept( File file )
871 {
872 return file.getName().endsWith( ".type" );
873 }
874 }
875
876 /**
877 * Directory filer impl.
878 */
879 private static class DirectoryFilter implements FileFilter
880 {
881 /**
882 * Return true if the file is a directory.
883 * @param file the file to test
884 * @return true if the file is a directory
885 */
886 public boolean accept( File file )
887 {
888 return file.isDirectory();
889 }
890 }
891
892 private void createIndex( File root )
893 {
894 String title = getTitle();
895 File index = new File( root, "index.html" );
896 try
897 {
898 FileWriter writer = new FileWriter( index );
899 writer.write( "<html>" );
900 writer.write( "\n <head>" );
901 writer.write( "\n <META http-equiv=\"Content-Type\" content=\"text/html; charset=US-ASCII\">" );
902 writer.write( "\n <title>" + title + "</title>" );
903 writer.write( "\n <link href=\"stylesheet.css\" type=\"text/css\" rel=\"stylesheet\"/>" );
904 writer.write( "\n </head>" );
905 writer.write( "\n <frameset cols=\"20%,80%\">" );
906 writer.write( "\n <frameset rows=\"30%,70%\">" );
907 writer.write( "\n <frame name=\"packageListFrame\" src=\"packages.html\">" );
908 writer.write( "\n <frame name=\"typeListFrame\" src=\"types.html\">" );
909 writer.write( "\n </frameset>" );
910 writer.write( "\n <frame name=\"typeFrame\" src=\"packages-overview.html\">" );
911 writer.write( "\n </frameset>" );
912 writer.write( "\n</html>" );
913 writer.close();
914 }
915 catch( Exception e )
916 {
917 final String error =
918 "Internal error while attempting to create frameset.";
919 throw new BuildException( error, e, getLocation() );
920 }
921 }
922 }