View Javadoc
1 /* 2 * $Header: /home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/ant/AntTagSupport.java,v 1.4 2002/06/25 20:43:30 werken Exp $ 3 * $Revision: 1.4 $ 4 * $Date: 2002/06/25 20:43:30 $ 5 * 6 * ==================================================================== 7 * 8 * The Apache Software License, Version 1.1 9 * 10 * Copyright (c) 1999-2002 The Apache Software Foundation. All rights 11 * reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in 22 * the documentation and/or other materials provided with the 23 * distribution. 24 * 25 * 3. The end-user documentation included with the redistribution, if 26 * any, must include the following acknowlegement: 27 * "This product includes software developed by the 28 * Apache Software Foundation (http://www.apache.org/)." 29 * Alternately, this acknowlegement may appear in the software itself, 30 * if and wherever such third-party acknowlegements normally appear. 31 * 32 * 4. The names "The Jakarta Project", "Commons", and "Apache Software 33 * Foundation" must not be used to endorse or promote products derived 34 * from this software without prior written permission. For written 35 * permission, please contact apache@apache.org. 36 * 37 * 5. Products derived from this software may not be called "Apache" 38 * nor may "Apache" appear in their names without prior written 39 * permission of the Apache Group. 40 * 41 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 42 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 43 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 44 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 45 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 46 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 47 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 48 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 49 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 50 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 51 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 52 * SUCH DAMAGE. 53 * ==================================================================== 54 * 55 * This software consists of voluntary contributions made by many 56 * individuals on behalf of the Apache Software Foundation. For more 57 * information on the Apache Software Foundation, please see 58 * <http://www.apache.org/>;. 59 * 60 * $Id: AntTagSupport.java,v 1.4 2002/06/25 20:43:30 werken Exp $ 61 */ 62 63 package org.apache.commons.jelly.tags.ant; 64 65 import java.lang.reflect.Constructor; 66 import java.lang.reflect.Method; 67 import java.util.Iterator; 68 import java.util.Map; 69 70 import org.apache.commons.beanutils.BeanUtils; 71 import org.apache.commons.beanutils.MethodUtils; 72 import org.apache.commons.beanutils.PropertyUtils; 73 import org.apache.commons.grant.DefaultPropsHandler; 74 import org.apache.commons.grant.GrantProject; 75 import org.apache.commons.grant.PropsHandler; 76 import org.apache.commons.jelly.MapTagSupport; 77 import org.apache.commons.jelly.Tag; 78 import org.apache.commons.jelly.XMLOutput; 79 import org.apache.commons.jelly.impl.BeanSource; 80 import org.apache.commons.jelly.impl.StaticTag; 81 import org.apache.commons.logging.Log; 82 import org.apache.commons.logging.LogFactory; 83 import org.apache.tools.ant.IntrospectionHelper; 84 import org.apache.tools.ant.Project; 85 import org.apache.tools.ant.Task; 86 import org.apache.tools.ant.TaskAdapter; 87 import org.apache.tools.ant.types.DataType; 88 89 /*** 90 * Tag supporting ant's Tasks as well as 91 * dynamic runtime behaviour for 'unknown' tags. 92 * 93 * @author <a href="mailto:bob@eng.werken.com">bob mcwhirter</a> 94 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a> 95 */ 96 public class AntTag extends MapTagSupport implements TaskSource { 97 98 /*** The Log to which logging calls will be made. */ 99 private static final Log log = LogFactory.getLog(AntTag.class); 100 101 private static final Class[] addTaskParamTypes = { String.class }; 102 103 /*** store the name of the manifest tag for special handling */ 104 private static final String ANT_MANIFEST_TAG = "manifest"; 105 106 /*** The name of this tag. */ 107 protected String tagName; 108 109 /*** The general object underlying this tag. */ 110 protected Object object; 111 112 /*** Task, if this tag represents a task. */ 113 protected Task task; 114 115 /*** Construct with a project and tag name. 116 * 117 * @param project The Ant project. 118 * @param tagName The name on the tag. 119 */ 120 public AntTag(String tagName) { 121 this.tagName = tagName; 122 } 123 124 public String toString() { 125 return "[AntTag: name=" + getTagName() + "]"; 126 } 127 128 // Tag interface 129 //------------------------------------------------------------------------- 130 public void doTag(XMLOutput output) throws Exception { 131 132 Project project = getAntProject(); 133 String tagName = getTagName(); 134 Object parentObject = null; 135 136 // must be a datatype. 137 TaskSource ancestor = (TaskSource) findAncestorWithClass( TaskSource.class ); 138 if ( ancestor != null ) { 139 parentObject = ancestor.getTaskObject(); 140 } 141 142 // lets assume that Task instances are not nested inside other Task instances 143 // for example <manifest> inside a <jar> should be a nested object, where as 144 // if the parent is not a Task the <manifest> should create a ManifestTask 145 146 if ( ! ( parentObject instanceof Task ) && 147 project.getTaskDefinitions().containsKey( tagName ) ) { 148 149 if ( log.isDebugEnabled() ) { 150 log.debug( "Creating an ant Task for name: " + tagName ); 151 } 152 // the following algorithm follows the lifetime of a tag 153 // http://jakarta.apache.org/ant/manual/develop.html#writingowntask 154 // kindly recommended by Stefan Bodewig 155 156 // create and set its project reference 157 task = createTask( tagName ); 158 if ( task instanceof TaskAdapter ) { 159 setObject( ((TaskAdapter)task).getProxy() ); 160 } 161 else { 162 setObject( task ); 163 } 164 165 // set the task ID if one is given 166 Object id = getAttributes().remove( "id" ); 167 if ( id != null ) { 168 project.addReference( (String) id, task ); 169 } 170 171 // ### we might want to spoof a Target setting here 172 173 // now lets initialize 174 task.init(); 175 176 // now lets invoke the body to call all the createXXX() or addXXX() methods 177 String body = getBodyText(); 178 179 // now lets set any attributes of this tag... 180 setBeanProperties(); 181 182 // now lets set the addText() of the body content, if its applicaable 183 Method method = MethodUtils.getAccessibleMethod( task.getClass(), 184 "addText", 185 addTaskParamTypes ); 186 if (method != null) { 187 String text = getBodyText(); 188 189 Object[] args = { text }; 190 method.invoke(this.task, args); 191 } 192 193 // now lets set all the attributes of the child elements 194 // XXXX: to do! 195 196 // now we're ready to invoke the task 197 // XXX: should we call execute() or perform()? 198 task.perform(); 199 } 200 else { 201 202 if ( log.isDebugEnabled() ) { 203 log.debug( "Creating a nested object name: " + tagName ); 204 } 205 206 if ( parentObject == null ) { 207 parentObject = findBeanAncestor(); 208 } 209 210 Object nested = createNestedObject( parentObject, tagName ); 211 212 if ( nested == null ) { 213 nested = createDataType( tagName ); 214 } 215 216 if ( nested != null ) { 217 setObject( nested ); 218 219 // set the task ID if one is given 220 Object id = getAttributes().remove( "id" ); 221 if ( id != null ) { 222 project.addReference( (String) id, nested ); 223 } 224 225 try{ 226 PropertyUtils.setProperty( nested, "name", tagName ); 227 } 228 catch (Exception e) { 229 } 230 231 // now lets invoke the body 232 String body = getBodyText(); 233 234 // now lets set any attributes of this tag... 235 setBeanProperties(); 236 237 // now lets add it to its parent 238 if ( parentObject != null ) { 239 IntrospectionHelper ih = IntrospectionHelper.getHelper( parentObject.getClass() ); 240 try { 241 ih.storeElement( project, parentObject, nested, tagName ); 242 } 243 catch (Exception e) { 244 //log.warn( "Caught exception setting nested: " + tagName, e ); 245 } 246 } 247 } 248 else { 249 // lets treat this tag as static XML... 250 StaticTag tag = new StaticTag("", tagName, tagName); 251 tag.setParent( getParent() ); 252 tag.setBody( getBody() ); 253 254 tag.setContext(context); 255 256 for (Iterator iter = getAttributes().entrySet().iterator(); iter.hasNext();) { 257 Map.Entry entry = (Map.Entry) iter.next(); 258 String name = (String) entry.getKey(); 259 Object value = entry.getValue(); 260 261 tag.setAttribute(name, value); 262 } 263 264 tag.doTag(output); 265 } 266 } 267 } 268 269 270 // Properties 271 //------------------------------------------------------------------------- 272 public String getTagName() { 273 return this.tagName; 274 } 275 276 /*** Retrieve the general object underlying this tag. 277 * 278 * @return The object underlying this tag. 279 */ 280 public Object getTaskObject() { 281 return this.object; 282 } 283 284 /*** Set the object underlying this tag. 285 * 286 * @param object The object. 287 */ 288 public void setObject(Object object) { 289 this.object = object; 290 } 291 292 public Project getAntProject() { 293 return AntTagLibrary.getProject(context); 294 } 295 296 // Implementation methods 297 //------------------------------------------------------------------------- 298 299 /*** 300 * Sets the properties on the Ant task 301 */ 302 public void setBeanProperties() throws Exception { 303 Object object = getTaskObject(); 304 if ( object != null ) { 305 Map map = getAttributes(); 306 for ( Iterator iter = map.entrySet().iterator(); iter.hasNext(); ) { 307 Map.Entry entry = (Map.Entry) iter.next(); 308 String name = (String) entry.getKey(); 309 Object value = entry.getValue(); 310 setBeanProperty( object, name, value ); 311 } 312 } 313 } 314 315 public void setAttribute(String name, 316 Object value) 317 { 318 super.setAttribute( name, 319 value.toString() ); 320 321 } 322 323 public void setBeanProperty(Object object, String name, Object value) throws Exception { 324 if ( log.isDebugEnabled() ) { 325 log.debug( "Setting bean property on: "+ object + " name: " + name + " value: " + value ); 326 } 327 328 IntrospectionHelper ih = IntrospectionHelper.getHelper( object.getClass() ); 329 330 if ( value instanceof String ) { 331 try { 332 ih.setAttribute( getAntProject(), object, name.toLowerCase(), (String) value ); 333 return; 334 } 335 catch (Exception e) { 336 // ignore: not a valid property 337 } 338 } 339 340 try { 341 342 ih.storeElement( getAntProject(), object, value, name ); 343 } 344 catch (Exception e) { 345 346 // let any exceptions bubble up from here 347 BeanUtils.setProperty( object, name, value ); 348 } 349 } 350 351 352 /*** 353 * Creates a nested object of the given object with the specified name 354 */ 355 public Object createNestedObject(Object object, String name) throws Exception { 356 Object dataType = null; 357 if ( object != null ) { 358 IntrospectionHelper ih = IntrospectionHelper.getHelper( object.getClass() ); 359 360 if ( ih != null ) { 361 try { 362 dataType = ih.createElement( getAntProject(), object, name ); 363 } 364 catch (Exception e) { 365 log.error(e); 366 } 367 } 368 } 369 370 if ( dataType == null ) { 371 dataType = createDataType( name ); 372 } 373 374 return dataType; 375 } 376 377 public Object createDataType(String name) throws Exception { 378 379 Object dataType = null; 380 381 Class type = (Class) getAntProject().getDataTypeDefinitions().get(name); 382 383 if ( type != null ) { 384 385 try { 386 Constructor ctor = null; 387 boolean noArg = false; 388 389 // DataType can have a "no arg" constructor or take a single 390 // Project argument. 391 try { 392 ctor = type.getConstructor(new Class[0]); 393 noArg = true; 394 } 395 catch (NoSuchMethodException nse) { 396 ctor = type.getConstructor(new Class[] { Project.class }); 397 noArg = false; 398 } 399 400 if (noArg) { 401 dataType = (DataType) ctor.newInstance(new Object[0]); 402 } 403 else { 404 dataType = (DataType) ctor.newInstance(new Object[] { getAntProject() }); 405 } 406 ((DataType)dataType).setProject( getAntProject() ); 407 408 } 409 catch (Throwable t) { 410 // ignore 411 log.error(t); 412 } 413 } 414 415 return dataType; 416 } 417 418 public Task createTask(String taskName) throws Exception { 419 return createTask( taskName, 420 (Class) getAntProject().getTaskDefinitions().get( taskName ) ); 421 } 422 423 public Task createTask(String taskName, 424 Class taskType) throws Exception { 425 426 if (taskType == null) { 427 return null; 428 } 429 430 Object o = taskType.newInstance(); 431 Task task = null; 432 if ( o instanceof Task ) { 433 task = (Task) o; 434 } 435 else { 436 TaskAdapter taskA=new TaskAdapter(); 437 taskA.setProxy( o ); 438 task=taskA; 439 } 440 441 task.setProject(getAntProject()); 442 task.setTaskName(taskName); 443 444 return task; 445 } 446 447 /*** 448 * Attempts to look up in the parent hierarchy for a tag that implements the BeanSource interface 449 * which creates a dynamic bean, or will return the parent tag, which is also a bean. 450 */ 451 protected Object findBeanAncestor() throws Exception { 452 Tag tag = getParent(); 453 if (tag != null) { 454 if (tag instanceof BeanSource) { 455 BeanSource beanSource = (BeanSource) tag; 456 return beanSource.getBean(); 457 } 458 } 459 return tag; 460 } 461 }

This page was automatically generated by Maven