001: /*
002: * ========================================================================
003: *
004: * Copyright 2003 The Apache Software Foundation.
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: *
018: * ========================================================================
019: */
020: package org.apache.cactus.integration.ant.container;
021:
022: import java.util.ArrayList;
023: import java.util.Iterator;
024: import java.util.List;
025:
026: import org.apache.tools.ant.BuildException;
027: import org.apache.tools.ant.Task;
028: import org.apache.tools.ant.TaskContainer;
029: import org.apache.tools.ant.taskdefs.CallTarget;
030:
031: /**
032: * A generic container that can be nested in the
033: * {@link org.apache.cactus.integration.ant.CactusTask} to support complete
034: * customization of the container lifecycle from a build file.
035: *
036: * @version $Id: GenericContainer.java 238811 2004-02-29 10:10:42Z vmassol $
037: */
038: public final class GenericContainer extends AbstractContainer {
039:
040: // Inner Classes -----------------------------------------------------------
041:
042: /**
043: * Class that represents the nested 'startup' and 'shutdown' elements. It
044: * supports either an Ant target to delegate to, or a list of nested tasks
045: * that are to be executed in order to perform the operation.
046: */
047: public final class Hook implements TaskContainer {
048:
049: // Instance Variables --------------------------------------------------
050:
051: /**
052: * The target to call when the hook is executed.
053: */
054: private String target;
055:
056: /**
057: * Ordered list of the contained tasks that should be invoked when the
058: * hook is executed.
059: */
060: private List tasks = new ArrayList();
061:
062: // Public Methods ------------------------------------------------------
063:
064: /**
065: * Sets the target to call.
066: *
067: * @param theTarget The name of the target
068: */
069: public void setTarget(String theTarget) {
070: if (!this .tasks.isEmpty()) {
071: throw new BuildException(
072: "The generic element supports either "
073: + "a [target] attribute or nested tasks, but not both");
074: }
075: this .target = theTarget;
076: }
077:
078: /**
079: * @see org.apache.tools.ant.TaskContainer#addTask
080: */
081: public void addTask(Task theTask) throws BuildException {
082: if (this .target != null) {
083: throw new BuildException(
084: "The generic element supports either "
085: + "a [target] attribute or nested tasks, but not both");
086: }
087: this .tasks.add(theTask);
088: }
089:
090: /**
091: * Executes the hook by either calling the specified target, or invoking
092: * all nested tasks.
093: *
094: * @throws BuildException If thrown by the called target or one of the
095: * nested tasks
096: */
097: public void execute() throws BuildException {
098: if (this .target != null) {
099: CallTarget antCall = (CallTarget) createAntTask("antcall");
100: antCall.setInheritAll(true);
101: antCall.setInheritRefs(true);
102: antCall.init();
103: antCall.setTarget(this .target);
104: antCall.execute();
105: } else {
106: for (Iterator i = this .tasks.iterator(); i.hasNext();) {
107: Task task = (Task) i.next();
108: task.perform();
109: }
110: }
111: }
112:
113: }
114:
115: // Instance Variables ------------------------------------------------------
116:
117: /**
118: * Name of the container for logging purposes.
119: */
120: private String name = "Unknown Container";
121:
122: /**
123: * The hook that is called when the container should be started.
124: */
125: private Hook startUpHook;
126:
127: /**
128: * The hook that is called when the container should be shut down.
129: */
130: private Hook shutDownHook;
131:
132: /**
133: * The port to which the container should be bound.
134: */
135: private int port = 8080;
136:
137: // Public Methods ----------------------------------------------------------
138:
139: /**
140: * Creates a nested 'startup' element.
141: *
142: * @return The new hook element
143: * @throws BuildException If a startup hook has already been added
144: */
145: public Hook createStartUp() throws BuildException {
146: if (isStartUpSet()) {
147: throw new BuildException(
148: "The container element supports only one"
149: + "nested [startup] element");
150: }
151: this .startUpHook = new Hook();
152: return this .startUpHook;
153: }
154:
155: /**
156: * Creates a nested 'shutdown' element.
157: *
158: * @return The new hook element
159: * @throws BuildException If a shutdown hook has already been added
160: */
161: public Hook createShutDown() throws BuildException {
162: if (isShutDownSet()) {
163: throw new BuildException(
164: "The container element supports only one"
165: + "nested [shutdown] element");
166: }
167: this .shutDownHook = new Hook();
168: return this .shutDownHook;
169: }
170:
171: /**
172: * Returns whether a way to start the container has already been set, either
173: * as a target, or as a nested task container.
174: *
175: * @return <code>true</code> if the shut down procedure has been set
176: */
177: public boolean isShutDownSet() {
178: return (this .shutDownHook != null);
179: }
180:
181: /**
182: * Returns whether a way to stop the container has already been set, either
183: * as a target, or as a nested task container.
184: *
185: * @return <code>true</code> if the start up procedure has been set
186: */
187: public boolean isStartUpSet() {
188: return (this .startUpHook != null);
189: }
190:
191: /**
192: * Sets the name of the container for logging purposes.
193: *
194: * @param theName The container name
195: */
196: public void setName(String theName) {
197: this .name = theName;
198: }
199:
200: /**
201: * Sets the port to which the container should listen.
202: *
203: * @param thePort The port to set
204: */
205: public void setPort(int thePort) {
206: this .port = thePort;
207: }
208:
209: /**
210: * Sets the target to call to start the server.
211: *
212: * @param theStartUpTarget the Ant target to call
213: */
214: public void setStartUpTarget(String theStartUpTarget) {
215: if (isStartUpSet()) {
216: throw new BuildException(
217: "Either specify the [startuptarget] "
218: + "attribute or the nested [startup] element, but not both");
219: }
220: this .startUpHook = new Hook();
221: this .startUpHook.setTarget(theStartUpTarget);
222: }
223:
224: /**
225: * Sets the target to call to stop the server.
226: *
227: * @param theShutDownTarget the Ant target to call
228: */
229: public void setShutDownTarget(String theShutDownTarget) {
230: if (isShutDownSet()) {
231: throw new BuildException(
232: "Either specify the [shutdowntarget] "
233: + "attribute or the nested [shutdown] element, but not both");
234: }
235: this .shutDownHook = new Hook();
236: this .shutDownHook.setTarget(theShutDownTarget);
237: }
238:
239: // AbstractContainer Implementation ----------------------------------------
240:
241: /**
242: * @see org.apache.cactus.integration.ant.container.Container#getName
243: */
244: public String getName() {
245: return this .name;
246: }
247:
248: /**
249: * Returns the port to which the container should listen.
250: *
251: * @return The port
252: */
253: public int getPort() {
254: return this .port;
255: }
256:
257: /**
258: * Starts up the container by delegating to the startup hook.
259: *
260: * @throws BuildException If thrown by the startup hook
261: */
262: public void startUp() throws BuildException {
263: if (this .startUpHook != null) {
264: this .startUpHook.execute();
265: }
266: }
267:
268: /**
269: * Shuts down the container by delegating to the shutdown hook.
270: *
271: * @throws BuildException If thrown by the shutdown hook
272: */
273: public void shutDown() throws BuildException {
274: if (this.shutDownHook != null) {
275: this.shutDownHook.execute();
276: }
277: }
278:
279: }
|