001 /*
002 * Copyright 2004-2005 Stephen 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.tools.tasks;
020
021 import java.io.File;
022 import java.util.ArrayList;
023 import java.util.List;
024
025 import net.dpml.library.info.Scope;
026 import net.dpml.library.Resource;
027
028 import org.apache.tools.ant.BuildException;
029 import org.apache.tools.ant.Project;
030 import org.apache.tools.ant.taskdefs.Javadoc;
031 import org.apache.tools.ant.taskdefs.Javadoc.AccessType;
032 import org.apache.tools.ant.types.DirSet;
033 import org.apache.tools.ant.types.Path;
034
035 /**
036 * Build the javadoc for a project.
037 *
038 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
039 * @version 1.1.3
040 */
041 public class JavadocTask extends ResourceTask
042 {
043 //-----------------------------------------------------------------------
044 // static
045 //-----------------------------------------------------------------------
046
047 private static final String JAVADOC_TASK_NAME = "javadoc";
048
049 /**
050 * Property key for declaration of an overriding access level.
051 */
052 public static final String JAVADOC_ACCESS_KEY = "project.javadoc.access";
053
054 /**
055 * Property key for declaration of the linksource option.
056 */
057 public static final String JAVADOC_LINK_SOURCE_KEY = "project.javadoc.linksource";
058
059 //-----------------------------------------------------------------------
060 // state
061 //-----------------------------------------------------------------------
062
063 private String m_title;
064 private List m_links = new ArrayList();
065 private List m_groups = new ArrayList();
066 private File m_overview;
067 private AccessType m_access;
068 private File m_dest;
069
070 //-----------------------------------------------------------------------
071 // JavadocTask
072 //-----------------------------------------------------------------------
073
074 /**
075 * Task initialization.
076 */
077 public void init()
078 {
079 if( !isInitialized() )
080 {
081 super.init();
082 getContext().getPath( Scope.RUNTIME );
083 }
084 }
085
086 /**
087 * Set the javadoc title.
088 * @param title the title
089 */
090 public void setTitle( final String title )
091 {
092 m_title = title;
093 }
094
095 /**
096 * Set the javadoc overview file.
097 * @param overview the overview file
098 */
099 public void setOverview( final File overview )
100 {
101 m_overview = overview;
102 }
103
104 /**
105 * Override the default destination.
106 * @param dir the destination directory
107 */
108 public void setDest( final File dir )
109 {
110 m_dest = dir;
111 }
112
113 /**
114 * Create and add a new link to the javadoc run.
115 * @return the new link
116 */
117 public Link createLink()
118 {
119 final Link link = new Link();
120 m_links.add( link );
121 return link;
122 }
123
124 /**
125 * Create and add a new group to the javadoc defintion.
126 * @return the new group
127 */
128 public Group createGroup()
129 {
130 final Group group = new Group();
131 m_groups.add( group );
132 return group;
133 }
134
135 /**
136 * Set the documentation access level.
137 * @param access the access level
138 */
139 public void setAccess( AccessType access )
140 {
141 m_access = access;
142 }
143
144 //-----------------------------------------------------------------------
145 // Task
146 //-----------------------------------------------------------------------
147
148 /**
149 * Task execution.
150 * @exception BuildException if a build error occurs
151 */
152 public void execute() throws BuildException
153 {
154 final Resource resource = getResource();
155
156 log( "Generating javadoc for project: " + resource, Project.MSG_VERBOSE );
157
158 File api = getDestination();
159 mkDir( api );
160
161 //
162 // construct the classpath by getting all of the classpaths for
163 // all of the projects within the module
164 //
165
166 Resource[] providers = resource.getClasspathProviders( Scope.RUNTIME );
167 final Path classpath = getContext().createPath( providers, true, true );
168 process( resource, classpath, api );
169 }
170
171 private File getDestination()
172 {
173 if( null == m_dest )
174 {
175 return getContext().getTargetReportsJavadocDirectory();
176 }
177 else
178 {
179 return m_dest;
180 }
181 }
182
183 //-----------------------------------------------------------------------
184 // internal
185 //-----------------------------------------------------------------------
186
187 private Group[] getGroups()
188 {
189 return (Group[]) m_groups.toArray( new Group[0] );
190 }
191
192 private void process(
193 final Resource resource, final Path classpath, final File root )
194 {
195 log( "Preparing javadoc for output to: " + root );
196
197 final Javadoc javadoc = (Javadoc) getProject().createTask( JAVADOC_TASK_NAME );
198 javadoc.setTaskName( getTaskName() );
199 javadoc.init();
200 javadoc.setDestdir( root );
201 javadoc.setUse( true );
202 javadoc.createClasspath().add( classpath );
203
204 final Path source = javadoc.createSourcepath();
205 addSourcePath( resource, javadoc, source );
206
207 if( null == m_access )
208 {
209 String access = getContext().getProperty( JAVADOC_ACCESS_KEY, "protected" );
210 AccessType type = new AccessType();
211 type.setValue( access );
212 javadoc.setAccess( type );
213 }
214 else
215 {
216 javadoc.setAccess( m_access );
217 }
218
219 if( "true".equals( getContext().getProperty( JAVADOC_LINK_SOURCE_KEY, "false" ) ) )
220 {
221 javadoc.setLinksource( true );
222 }
223
224 aggregateLinks( javadoc, resource );
225 Link[] links = (Link[]) m_links.toArray( new Link[0] );
226 for( int i=0; i<links.length; i++ )
227 {
228 Link link = links[i];
229 Javadoc.LinkArgument arg = javadoc.createLink();
230 String href = link.getHref();
231 log( "Adding link: " + href );
232 arg.setHref( href );
233 }
234
235 if( null == m_title )
236 {
237 final String title = resource.getName() + " API";
238 javadoc.setDoctitle( title );
239 }
240 else
241 {
242 javadoc.setDoctitle( m_title );
243 }
244
245 if( null != m_overview )
246 {
247 javadoc.setOverview( m_overview );
248 }
249
250 Group[] groups = getGroups();
251 for( int i=0; i < groups.length; i++ )
252 {
253 Group group = groups[i];
254 Javadoc.GroupArgument jgroup = javadoc.createGroup();
255 jgroup.setTitle( group.getTitle() );
256 Group.Package[] packages = group.getPackages();
257 for( int j=0; j < packages.length; j++ )
258 {
259 Javadoc.PackageName name = new Javadoc.PackageName();
260 name.setName( packages[j].getName() );
261 jgroup.addPackage( name );
262 }
263 }
264
265 log( "Generating: " + resource.getName() + " API" );
266 javadoc.execute();
267 }
268
269 private void aggregateLinks( Javadoc task, Resource resource )
270 {
271 String path = resource.getResourcePath();
272 ArrayList list = new ArrayList();
273 Resource[] providers = resource.getAggregatedProviders( Scope.RUNTIME, true, false );
274 for( int i=0; i<providers.length; i++ )
275 {
276 Resource provider = providers[i];
277 if( !provider.getResourcePath().startsWith( path ) )
278 {
279 String source = provider.getProperty( "project.api.root" );
280 if( null != source )
281 {
282 log( "Adding provider link: " + source + " from " + provider );
283 Javadoc.LinkArgument arg = task.createLink();
284 arg.setHref( source );
285 }
286 }
287 }
288 }
289
290 private void addSourcePath( Resource resource, Javadoc javadoc, Path source )
291 {
292 //
293 // check for a classic src directory
294 //
295
296 if( null != resource.getBaseDir() )
297 {
298 File src = new File( resource.getBaseDir(), "target/build/main" );
299 if( src.exists() )
300 {
301 log( "Adding src path: " + src );
302 source.createPathElement().setLocation( src );
303 final DirSet packages = new DirSet();
304 packages.setDir( src );
305 packages.setIncludes( "**/*" );
306 javadoc.addPackageset( packages );
307 }
308 }
309
310 String path = resource.getResourcePath();
311 Resource[] providers = resource.getAggregatedProviders( Scope.RUNTIME, true, false );
312 for( int i=0; i<providers.length; i++ )
313 {
314 Resource provider = providers[i];
315 if( provider.getResourcePath().startsWith( path ) )
316 {
317 String flag = provider.getProperty( "project.javadoc.exclude", "false" );
318 if( "false".equals( flag ) )
319 {
320 File basedir = provider.getBaseDir();
321 if( null != basedir )
322 {
323 File src = new File( basedir, "target/build/main" );
324 if( src.exists() )
325 {
326 log( "Adding src path: " + src );
327 source.createPathElement().setLocation( src );
328 final DirSet packages = new DirSet();
329 packages.setDir( src );
330 packages.setIncludes( "**/**" );
331 javadoc.addPackageset( packages );
332 }
333 }
334 }
335 }
336 }
337 }
338
339 //-----------------------------------------------------------------------
340 // static classes
341 //-----------------------------------------------------------------------
342
343 /**
344 * Delcaration of a link.
345 */
346 public class Link
347 {
348 private String m_href;
349
350 /**
351 * Creation of a new link instance.
352 */
353 public Link()
354 {
355 m_href = null;
356 }
357
358 /**
359 * Set the href attrbute for the api packagelist base.
360 * @param href the href to the packacke list base
361 */
362 public void setHref( final String href )
363 {
364 m_href = href;
365 }
366
367 /**
368 * Get the href attribute.
369 * @return the href attriute value
370 */
371 public String getHref()
372 {
373 if( null != m_href )
374 {
375 return m_href;
376 }
377 else
378 {
379 final String error =
380 "Link element must contain an 'href' attribute.";
381 throw new BuildException( error, getLocation() );
382 }
383 }
384 }
385
386 /**
387 * Defintion of a package group.
388 */
389 public static class Group
390 {
391 private String m_title;
392 private ArrayList m_packages = new ArrayList();
393
394 /**
395 * Set the package group title.
396 * @param title the package group title
397 */
398 public void setTitle( String title )
399 {
400 m_title = title;
401 }
402
403 /**
404 * Return the package group title.
405 * @return the title
406 */
407 public String getTitle()
408 {
409 if( null == m_title )
410 {
411 final String error =
412 "Required 'title' attribute on group element undefined.";
413 throw new BuildException( error );
414 }
415 else
416 {
417 return m_title;
418 }
419 }
420
421 /**
422 * Return the packages within the group.
423 * @return the array of packages
424 */
425 public Group.Package[] getPackages()
426 {
427 return (Group.Package[]) m_packages.toArray( new Group.Package[0] );
428 }
429
430 /**
431 * Create and add a new package.
432 * @return the new package
433 */
434 public Group.Package createPackage()
435 {
436 final Package pkg = new Package();
437 m_packages.add( pkg );
438 return pkg;
439 }
440
441 /**
442 * Defintionof a package.
443 */
444 public static class Package
445 {
446 private String m_name;
447
448 /**
449 * Set the package name.
450 * @param name the package name
451 */
452 public void setName( String name )
453 {
454 m_name = name;
455 }
456
457 /**
458 * Return the package name.
459 * @return the name
460 */
461 public String getName()
462 {
463 if( null == m_name )
464 {
465 final String error =
466 "Required 'name' attribute on package element undefined.";
467 throw new BuildException( error );
468 }
469 else
470 {
471 return m_name;
472 }
473 }
474 }
475 }
476 }