001    /*
002     * Copyright 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.tools.tasks;
020    
021    import java.io.File;
022    
023    
024    import net.dpml.tools.Context;
025    import net.dpml.tools.impl.DefaultContext;
026    
027    import net.dpml.library.Library;
028    import net.dpml.library.Resource;
029    import net.dpml.library.ResourceNotFoundException;
030    
031    import org.apache.tools.ant.BuildException;
032    import org.apache.tools.ant.Project;
033    import org.apache.tools.ant.Task;
034    import org.apache.tools.ant.types.FileSet;
035    import org.apache.tools.ant.taskdefs.Mkdir;
036    import org.apache.tools.ant.taskdefs.Copy;
037    import org.apache.tools.ant.taskdefs.Delete;
038    import org.apache.tools.ant.taskdefs.Checksum;
039    import org.apache.tools.ant.taskdefs.ExecTask;
040    
041    
042    /**
043     * Prepare the target build directory based on content presented under the
044     * ${basedir}/src and ${basedir}/etc directories.
045     *
046     * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
047     * @version 1.1.3
048     */
049    public class GenericTask extends Task
050    {   
051       /**
052        * Constant key for the GPG exe name.
053        */
054        public static final String GPG_EXE_KEY = "project.gpg.exe";
055    
056       /**
057        * MD5 file type.
058        */
059        public static final String MD5_EXT = "md5";
060    
061       /**
062        * ASC file type.
063        */
064        public static final String ASC_EXT = "asc";
065    
066        private boolean m_init = false;
067        
068       /**
069        * Initialize the task.
070        */
071        public void init()
072        {
073            if( !m_init )
074            {
075                super.init();
076                m_init = true;
077            }
078        }
079        
080       /**
081        * Return the initialized state of the task.
082        * @return true if initialized
083        */
084        protected boolean isInitialized()
085        {
086            return m_init;
087        }
088        
089       /**
090        * Get the project definition.
091        * @return the resource
092        */
093        protected Resource getResource()
094        {
095            return getContext().getResource();
096        }
097        
098       /**
099        * Get the library.
100        * @return the library
101        */
102        protected Library getLibrary()
103        {
104            return getContext().getLibrary();
105        }
106        
107       /**
108        * Get the project context.
109        * @return the project context
110        */
111        public Context getContext()
112        {
113            Project project = getProject();
114            Object object = project.getReference( "project.context" );
115            if( object != null )
116            {
117                if( object instanceof Context )
118                {
119                    return (Context) object;
120                }
121                else
122                {
123                    //System.out.println( 
124                    //  net.dpml.lang.StandardClassLoader.toString( 
125                    //    object.getClass().getClassLoader(),
126                    //    Context.class.getClassLoader() ) );
127                    
128                    final String error = 
129                      "Object assigned under the 'project.context' key is not assignable to a context instance."
130                      + "\nObject: " + object.getClass().getName()
131                      + "\nExpecting: " + Context.class.getName();
132                    throw new IllegalStateException( error );
133                }
134            }
135            else
136            {
137                // this is an Ant initiated bootstrapping of Depot (i.e. we are 
138                // not using a project established via the default builder) as such
139                // we need to declare the build signature argument and construct the
140                // project context
141                
142                String signature = project.getProperty( "build.signature" );
143                if( null != signature )
144                {
145                    System.setProperty( "build.signature", signature );
146                }
147                
148                try
149                {
150                    return new DefaultContext( project );
151                }
152                catch( ResourceNotFoundException e )
153                {
154                    final String message = e.getMessage();
155                    final String error = "Resource not found: " + message;
156                    throw new BuildException( error, e, getLocation() );
157                }
158                catch( BuildException e )
159                {
160                    throw e;
161                }
162                catch( Exception e )
163                {
164                    final String error = 
165                      "Unexpected error while attempting to construct project context.";
166                    throw new RuntimeException( error, e );
167                }
168            }
169        }
170        
171       /**
172        * Utility operation to create a new directory if it does not exist.
173        * @param dir the directory to create
174        */
175        protected void mkDir( final File dir )
176        {
177            final Mkdir mkdir = (Mkdir) getProject().createTask( "mkdir" );
178            mkdir.setTaskName( getTaskName() );
179            mkdir.setDir( dir );
180            mkdir.init();
181            mkdir.execute();
182        }
183        
184       /**
185        * Utility operation to copy a file from a source to a destination.
186        * @param src the src file
187        * @param destination the destination file
188        * @param filtering if true apply filtering during the copy
189        * @param includes the includes specification
190        * @param excludes the excludes specification
191        */
192        protected void copy(
193           final File src, final File destination, final boolean filtering, 
194           final String includes, final String excludes )
195        {
196            mkDir( destination );
197            final Copy copy = (Copy) getProject().createTask( "copy" );
198            copy.setTaskName( getTaskName() );
199            copy.setTodir( destination );
200            copy.setFiltering( filtering );
201            copy.setOverwrite( false );
202            copy.setPreserveLastModified( true );
203            final FileSet fileset = new FileSet();
204            fileset.setDir( src );
205            fileset.setIncludes( includes );
206            fileset.setExcludes( excludes );
207            copy.addFileset( fileset );
208            copy.init();
209            copy.execute();
210        }
211        
212       /**
213        * Utility operation to delete a directory .
214        * @param dir the directory to delete
215        */
216        protected void deleteDir( final File dir )
217        {
218            final Delete task = (Delete) getProject().createTask( "delete" );
219            task.setTaskName( getTaskName() );
220            task.setDir( dir );
221            task.init();
222            task.execute();
223        }
224        
225       /**
226        * Create an MD5 checksum file relative to the supplied file.
227        * If an [filename].md5 file exists it will be deleted and a new
228        * MD5 created.
229        *
230        * @param file the file from which a checksum signature will be generated
231        */
232        public void checksum( final File file )
233        {
234            log( "Creating md5 checksum" );
235    
236            final File md5 = new File( file.toString() + "." + MD5_EXT );
237            if( md5.exists() )
238            {
239                md5.delete();
240            }
241    
242            final Checksum checksum = (Checksum) getProject().createTask( "checksum" );
243            checksum.setTaskName( getTaskName() );
244            checksum.setFile( file );
245            checksum.setFileext( "." + MD5_EXT );
246            checksum.init();
247            checksum.execute();
248        }
249    
250       /**
251        * Creation of an ASC signature relative to a supplied file.  If a [filename].asc
252        * exists it will be deleted and recreated relative to the supplied file content.
253        *
254        * @param file the file to sign
255        */
256        public void asc( final File file )
257        {
258            final String path = Project.translatePath( file.toString() );
259            final File asc = new File( file.toString() + "." + ASC_EXT );
260            if( asc.exists() )
261            {
262                asc.delete();
263            }
264    
265            String gpg = getProject().getProperty( GPG_EXE_KEY );
266            if( ( null != gpg ) && !"".equals( gpg ) )
267            {
268                log( "Creating asc signature using '" + gpg + "'." );
269                final ExecTask execute = (ExecTask) getProject().createTask( "exec" );
270    
271                execute.setExecutable( gpg );
272    
273                execute.createArg().setValue( "-a" );
274                execute.createArg().setValue( "-b" );
275                execute.createArg().setValue( "-o" );
276                execute.createArg().setValue( path + "." + ASC_EXT );
277                execute.createArg().setValue( path );
278    
279                execute.setDir( getProject().getBaseDir() );
280                execute.setSpawn( false );
281                execute.setAppend( false );
282                execute.setTimeout( new Integer( TIMEOUT ) );
283                execute.execute();
284            }
285        }
286    
287        private static final int TIMEOUT = 10000;
288    }