root/trunk/classes/phing/UnknownElement.php

Revision 307, 7.5 kB (checked in by hans, 1 year ago)

Refs #188 - Adding work-in-progress (still-broken!) namespace support.

  • Property svn:keywords set to author date id revision
Line 
1 <?php
2 /*
3  *  $Id$
4  *
5  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
8  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
9  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
10  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
11  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
12  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
13  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
15  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16  *
17  * This software consists of voluntary contributions made by many individuals
18  * and is licensed under the LGPL. For more information please see
19  * <http://phing.info>.
20  */
21
22 namespace phing;
23
24
25 /**
26  * Wrapper class that holds all information necessary to create a task
27  * that did not exist when Phing started.
28  *
29  * <em> This has something to do with phing encountering an task XML element
30  * it is not aware of at start time. This is a situation where special steps
31  * need to be taken so that the element is then known.</em>
32  *
33  * @author    Andreas Aderhold <andi@binarycloud.com>
34  * @author    Hans Lellelid <hans@xmpl.org>
35  * @version   $Revision: 1.9 $
36  * @package   phing
37  */
38 class UnknownElement extends Task {
39
40     private $elementName;
41     private $realThing;
42     private $children = array();
43
44     /**
45      * Constructs a UnknownElement object
46      *
47      * @param    string  The XML element name that is unknown
48      * @access   public
49      */
50     function __construct($elementName) {
51         $this->elementName = (string) $elementName;
52     }
53
54     /**
55      * Return the XML element name that this <code>UnnownElement</code>
56      * handles.
57      *
58      * @return  string  The XML element name that is unknown
59      */
60     public function getTag() {
61         return (string) $this->elementName;
62     }
63
64     /**
65      * Tries to configure the unknown element
66      *
67      * @throws  BuildException if the element can not be configured
68      */
69     public function maybeConfigure() {
70     
71         $this->realThing = $this->makeObject($this, $this->wrapper);
72         $this->wrapper->setProxy($this->realThing);
73         if ($this->realThing instanceof Task) {
74             $this->realThing->setRuntimeConfigurableWrapper($this->wrapper);
75         }
76     
77         $this->handleChildren($this->realThing, $this->wrapper);
78         $this->wrapper->maybeConfigure($this->getProject());
79                                     
80     }
81
82     /**
83      * Called when the real task has been configured for the first time.
84      *
85      * @throws  BuildException if the task can not be created
86      */
87     public function main() {
88     
89         if ($this->realThing === null) {
90             // plain impossible to get here, maybeConfigure should
91             // have thrown an exception.
92             throw new BuildException("Should not be executing UnknownElement::main() -- task/type: {$this->elementName}");
93         }
94         
95         if ($this->realThing instanceof Task) {
96             $this->realThing->main();
97         }
98         
99     }
100
101     /**
102      * Add a child element to the unknown element
103      *
104      * @param   object  The object representing the child element
105      */
106     public function addChild(UnknownElement $child) {
107         $this->children[] = $child;
108     }
109
110     /**
111      *  Handle child elemets of the unknown element, if any.
112      *
113      *  @param ProjectComponent The parent object the unkown element belongs to
114      *  @param object The parent wrapper object
115      */
116     function handleChildren(ProjectComponent $parent, $parentWrapper) {
117
118         if ($parent instanceof TaskAdapter) {
119             $parent = $parent->getProxy();
120         }
121
122         $parentClass = get_class($parent);
123         $ih = IntrospectionHelper::getHelper($parentClass);
124
125         for ($i=0, $childrenCount=count($this->children); $i < $childrenCount; $i++) {
126
127             $childWrapper = $parentWrapper->getChild($i);
128             $child = $this->children[$i];
129             $realChild = null;
130             if ($parent instanceof TaskContainer) {
131                 $realChild = $this->makeTask($child, $childWrapper, false);
132                 $parent->addTask($realChild);
133             } else {
134                 $project = $this->project === null ? $parent->project : $this->project;
135                 $realChild = $ih->createElement($project, $parent, $child->getTag());
136             }
137
138             $childWrapper->setProxy($realChild);
139             if ($realChild instanceof Task) {
140                 $realChild->setRuntimeConfigurableWrapper($childWrapper);
141             }
142             
143             if ($realChild instanceof ProjectComponent) {
144                 $child->handleChildren($realChild, $childWrapper);
145             }
146             
147             if ($realChild instanceof Task) {
148                 $realChild->maybeConfigure();
149             }
150         }
151     }
152
153     /**
154      * Creates a named task or data type. If the real object is a task,
155      * it is configured up to the init() stage.
156      *
157      * @param UnknownElement $ue The unknown element to create the real object for.
158      *           Must not be <code>null</code>.
159      * @param RuntimeConfigurable $w  Ignored in this implementation.
160      * @return object The Task or DataType represented by the given unknown element.
161      */
162     protected function makeObject(UnknownElement $ue, RuntimeConfigurable $w) {
163         $o = $this->makeTask($ue, $w, true);
164         if ($o === null) {
165             $o = $this->project->createDataType($ue->getTag());
166         }
167         if ($o === null) {
168             throw new BuildException("Could not create task/type: '".$ue->getTag()."'. Make sure that this class has been declared using taskdef / typedef.");
169         }
170         return $o;
171     }
172     
173     /**
174      *  Create a named task and configure it up to the init() stage.
175      *
176      * @param UnknownElement $ue The unknwon element to create a task from
177      * @param RuntimeConfigurable $w The wrapper object
178      * @param boolean $onTopLevel Whether to treat this task as if it is top-level.
179      * @return Task The freshly created task
180      */
181     protected function makeTask(UnknownElement $ue, RuntimeConfigurable $w, $onTopLevel = false) {
182
183         $task = $this->project->createTask($ue->getTag());
184
185         if ($task === null) {
186             if (!$onTopLevel) {
187                 throw new BuildException("Could not create task of type: '".$this->elementName."'. Make sure that this class has been declared using taskdef.");
188             }
189             return null;           
190         }
191
192         // used to set the location within the xmlfile so that exceptions can
193         // give detailed messages
194
195         $task->setLocation($this->getLocation());
196         $attrs = $w->getAttributes();
197         if (isset($attrs['id'])) {
198             $this->project->addReference($attrs['id'], $task);
199         }
200
201         // UnknownElement always has an associated target
202         $task->setOwningTarget($this->target);
203
204         $task->init();
205         return $task;
206     }
207
208     /**
209      *  Get the name of the task to use in logging messages.
210      *
211      *  @return  string  The task's name
212      */
213     function getTaskName() {
214         return $this->realThing === null ? parent::getTaskName() : $this->realThing->getTaskName();
215     }
216 }
217
Note: See TracBrowser for help on using the browser.