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.2.0 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 }