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    
023    import net.dpml.library.Resource;
024    import net.dpml.library.info.Scope;
025    
026    import net.dpml.tools.Context;
027    
028    import org.apache.tools.ant.BuildException;
029    import org.apache.tools.ant.Project;
030    import org.apache.tools.ant.taskdefs.Copy;
031    import org.apache.tools.ant.taskdefs.Javac;
032    import org.apache.tools.ant.taskdefs.Mkdir;
033    import org.apache.tools.ant.taskdefs.MatchingTask;
034    import org.apache.tools.ant.types.FileSet;
035    import org.apache.tools.ant.types.Path;
036    
037    /**
038     * Compile sources located in ${project.target}/main to java class file under
039     * the ${project.target}/classes directory.  Properties influencing the compilation
040     * include:
041     * <ul>
042     *  <li>project.javac.debug : boolean true (default) or false</li>
043     *  <li>project.javac.fork: boolean true or false (default) </li>
044     *  <li>project.javac.deprecation: boolean true (default) or false</li>
045     * </ul>
046     * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
047     * @version 1.2.0
048     */
049    public class JavacTask extends MatchingTask
050    {
051       /**
052        * Constant debug key.
053        */ 
054        public static final String VERBOSE_KEY = "project.javac.verbose";
055    
056       /**
057        * Constant debug key.
058        */ 
059        public static final String DEBUG_KEY = "project.javac.debug";
060    
061       /**
062        * Constant fork key.
063        */ 
064        public static final String FORK_KEY = "project.javac.fork";
065    
066       /**
067        * Constant deprecation warning key.
068        */ 
069        public static final String DEPRECATION_KEY = "project.javac.deprecation";
070    
071       /**
072        * Constant src directory key.
073        */ 
074        public static final String SOURCE_KEY = "project.javac.source";
075    
076       /**
077        * Constant classes target directory key.
078        */ 
079        public static final String TARGET_KEY = "project.javac.target";
080    
081        private static final boolean DEBUG_VALUE = true;
082        private static final boolean FORK_VALUE = false;
083        private static final boolean DEPRECATION_VALUE = true;
084        private static final String SOURCE_VALUE = "1.4";
085        private static final String TARGET_VALUE = "1.4";
086    
087        private final Context m_context;
088        
089        private String m_classPathRef;
090        private Path m_classPath;
091        private File m_destination;
092        private File m_source;
093       
094       /**
095        * Creation of a new JavacTask.
096        * @param context the project context
097        */
098        public JavacTask( Context context )
099        {
100            super();
101            m_context = context;
102            try
103            {
104                Resource resource = context.getResource();
105                setProject( context.getProject() );
106                setTaskName( "javac" );
107                setSrc( context.getTargetBuildMainDirectory() );
108                setDest( context.getTargetClassesMainDirectory() );
109                context.getPath( Scope.RUNTIME );
110                setClasspathRef( "project.compile.path" );
111            }
112            catch( Exception e )
113            {
114                throw new BuildException( e );
115            }
116        }
117        
118       /**
119        * Set the compilation classpath.
120        * @param path the classpath
121        */
122        public void setClasspath( Path path ) 
123        {
124            m_classPath = path;
125        }
126        
127       /**
128        * Set the id of the compilation classpath.
129        * @param id the classpath reference
130        */
131        public void setClasspathRef( String id ) 
132        {
133            m_classPathRef = id;
134        }
135        
136       /**
137        * Set the destination directory.
138        * @param destination the destination directory
139        */
140        public void setDest( File destination )
141        {
142            m_destination = destination;
143        }
144        
145       /**
146        * Set the src directory.
147        * @param source the src directory
148        */
149        public void setSrc( File source )
150        {
151            m_source = source;
152        }
153        
154       /**
155        * Task execution.
156        */
157        public void execute()
158        {
159            if( null == m_destination )
160            {
161                final String error = 
162                  "Missing 'dest' attribute.";
163                throw new BuildException( error, getLocation() );
164            }
165            if( null == m_source )
166            {
167                final String error = 
168                  "Missing 'src' attribute.";
169                throw new BuildException( error, getLocation() );
170            }
171            
172            if( !m_source.exists() )
173            {
174                return;
175            }
176            
177            final Path classpath = getClasspath();
178            final Project project = getProject();
179            mkDir( m_destination );
180            final Javac javac = (Javac) getProject().createTask( "javac" );
181            javac.setTaskName( getTaskName() );
182            javac.setIncludeantruntime( false );
183            String lint = getProperty( "project.javac.lint", null );
184            if( null != lint )
185            {
186                javac.createCompilerArg().setValue( "-Xlint:" + lint );
187            }
188            
189            String verbose = getProperty( "project.javac.verbose", "false" );
190            if( "true".equals( verbose ) )
191            {
192                javac.setVerbose( true );
193            }
194            
195            final Path srcDirPath = new Path( project );
196            srcDirPath.createPathElement().setLocation( m_source );
197            javac.setSrcdir( srcDirPath );
198            
199            final Path srcPath = new Path( project );
200            FileSet fileset = super.getImplicitFileSet();
201            fileset.setDir( m_source );
202            javac.setSourcepath( srcPath );
203            
204            javac.setDestdir( m_destination );
205            javac.setDeprecation( getDeprecationProperty() );
206            javac.setDebug( getDebugProperty() );
207            javac.setFork( getForkProperty() );
208            javac.setSource( getSourceProperty() );
209            javac.setTarget( getTargetProperty() );
210            javac.setClasspath( classpath );
211            javac.init();
212            javac.execute();
213            
214            copy( m_source, m_destination, false, "**/*.*", "**/*.java,**/package.html" );
215    
216        }
217        
218        private Path getClasspath()
219        {
220            if( null != m_classPath )
221            {
222                return m_classPath;
223            }
224            else if( null != m_classPathRef )
225            {
226                return (Path) getProject().getReference( m_classPathRef );
227            }
228            else
229            {
230                final String error = 
231                  "Missing 'classpathRef' or 'classpath' attribute.";
232                throw new BuildException( error, getLocation() );
233            }
234        }
235        
236        private boolean getDebugProperty()
237        {
238            return getBooleanProperty( DEBUG_KEY, DEBUG_VALUE );
239        }
240    
241        private boolean getDeprecationProperty()
242        {
243            return getBooleanProperty( DEPRECATION_KEY, DEPRECATION_VALUE );
244        }
245    
246        private boolean getForkProperty()
247        {
248            return getBooleanProperty( FORK_KEY, FORK_VALUE );
249        }
250    
251        private String getSourceProperty()
252        {
253            return getProperty( SOURCE_KEY, SOURCE_VALUE );
254        }
255    
256        private String getTargetProperty()
257        {
258            return getProperty( TARGET_KEY, TARGET_VALUE );
259        }
260    
261        private boolean getBooleanProperty( final String key, final boolean fallback )
262        {
263            String value = getContext().getProperty( key );
264            if( null == value )
265            {
266                return fallback;
267            }
268            else
269            {
270                return Project.toBoolean( value );
271            }
272        }
273        
274        private String getProperty( final String key, final String fallback )
275        {
276            String value = getContext().getProperty( key );
277            if( null == value )
278            {
279                return fallback;
280            }
281            else
282            {
283                return value;
284            }
285        }
286    
287        void mkDir( final File dir )
288        {
289            final Mkdir mkdir = (Mkdir) getProject().createTask( "mkdir" );
290            mkdir.setTaskName( getTaskName() );
291            mkdir.setDir( dir );
292            mkdir.init();
293            mkdir.execute();
294        }
295    
296        void copy(
297           final File src, final File destination, final boolean filtering, final String includes, final String excludes )
298        {
299            mkDir( destination );
300            final Copy copy = (Copy) getProject().createTask( "copy" );
301            copy.setTaskName( getTaskName() );
302            copy.setTodir( destination );
303            copy.setFiltering( filtering );
304            copy.setOverwrite( false );
305            copy.setPreserveLastModified( true );
306            final FileSet fileset = new FileSet();
307            fileset.setDir( src );
308            fileset.setIncludes( includes );
309            fileset.setExcludes( excludes );
310            copy.addFileset( fileset );
311            copy.init();
312            copy.execute();
313        }
314    
315       /**
316        * Get the project definition.
317        * @return the build context
318        */
319        protected Context getContext()
320        {
321            Context context = (Context) getProject().getReference( "project.context" );
322            if( null == context )
323            {
324                final String error = 
325                  "Missing project context reference.";
326                throw new BuildException( error );
327            }
328            return context;
329        }
330    
331    }