001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.tools.ant.taskdefs;
020:
021: import java.util.Vector;
022:
023: import org.apache.tools.ant.BuildException;
024: import org.apache.tools.ant.Task;
025: import org.apache.tools.ant.input.DefaultInputHandler;
026: import org.apache.tools.ant.input.GreedyInputHandler;
027: import org.apache.tools.ant.input.InputHandler;
028: import org.apache.tools.ant.input.InputRequest;
029: import org.apache.tools.ant.input.MultipleChoiceInputRequest;
030: import org.apache.tools.ant.input.PropertyFileInputHandler;
031: import org.apache.tools.ant.types.EnumeratedAttribute;
032: import org.apache.tools.ant.util.ClasspathUtils;
033: import org.apache.tools.ant.util.StringUtils;
034:
035: /**
036: * Reads an input line from the console.
037: *
038: * @since Ant 1.5
039: *
040: * @ant.task category="control"
041: */
042: public class Input extends Task {
043:
044: /**
045: * Represents an InputHandler.
046: */
047: public class Handler extends DefBase {
048:
049: private String refid = null;
050: private HandlerType type = null;
051: private String classname = null;
052:
053: /**
054: * Specify that the handler is a reference on the project;
055: * this allows the use of a custom inputhandler.
056: * @param refid the String refid.
057: */
058: public void setRefid(String refid) {
059: this .refid = refid;
060: }
061:
062: /**
063: * Get the refid of this Handler.
064: * @return String refid.
065: */
066: public String getRefid() {
067: return refid;
068: }
069:
070: /**
071: * Set the InputHandler classname.
072: * @param classname the String classname.
073: */
074: public void setClassname(String classname) {
075: this .classname = classname;
076: }
077:
078: /**
079: * Get the classname of the InputHandler.
080: * @return String classname.
081: */
082: public String getClassname() {
083: return classname;
084: }
085:
086: /**
087: * Set the handler type.
088: * @param type a HandlerType.
089: */
090: public void setType(HandlerType type) {
091: this .type = type;
092: }
093:
094: /**
095: * Get the handler type.
096: * @return a HandlerType object.
097: */
098: public HandlerType getType() {
099: return type;
100: }
101:
102: private InputHandler getInputHandler() {
103: if (type != null) {
104: return type.getInputHandler();
105: }
106: if (refid != null) {
107: try {
108: return (InputHandler) (getProject()
109: .getReference(refid));
110: } catch (ClassCastException e) {
111: throw new BuildException(refid
112: + " does not denote an InputHandler", e);
113: }
114: }
115: if (classname != null) {
116: return (InputHandler) (ClasspathUtils.newInstance(
117: classname, createLoader(), InputHandler.class));
118: }
119: throw new BuildException(
120: "Must specify refid, classname or type");
121: }
122: }
123:
124: /**
125: * EnumeratedAttribute representing the built-in input handler types:
126: * "default", "propertyfile", "greedy".
127: */
128: public static class HandlerType extends EnumeratedAttribute {
129: private static final String[] VALUES = { "default",
130: "propertyfile", "greedy" };
131:
132: private static final InputHandler[] HANDLERS = {
133: new DefaultInputHandler(),
134: new PropertyFileInputHandler(),
135: new GreedyInputHandler() };
136:
137: /** {@inheritDoc} */
138: public String[] getValues() {
139: return VALUES;
140: }
141:
142: private InputHandler getInputHandler() {
143: return HANDLERS[getIndex()];
144: }
145: }
146:
147: private String validargs = null;
148: private String message = "";
149: private String addproperty = null;
150: private String defaultvalue = null;
151: private Handler handler = null;
152: private boolean messageAttribute;
153:
154: /**
155: * Defines valid input parameters as comma separated strings. If set, input
156: * task will reject any input not defined as accepted and requires the user
157: * to reenter it. Validargs are case sensitive. If you want 'a' and 'A' to
158: * be accepted you need to define both values as accepted arguments.
159: *
160: * @param validargs A comma separated String defining valid input args.
161: */
162: public void setValidargs(String validargs) {
163: this .validargs = validargs;
164: }
165:
166: /**
167: * Defines the name of a property to be created from input. Behaviour is
168: * according to property task which means that existing properties
169: * cannot be overridden.
170: *
171: * @param addproperty Name for the property to be created from input
172: */
173: public void setAddproperty(String addproperty) {
174: this .addproperty = addproperty;
175: }
176:
177: /**
178: * Sets the Message which gets displayed to the user during the build run.
179: * @param message The message to be displayed.
180: */
181: public void setMessage(String message) {
182: this .message = message;
183: messageAttribute = true;
184: }
185:
186: /**
187: * Defines the default value of the property to be created from input.
188: * Property value will be set to default if not input is received.
189: *
190: * @param defaultvalue Default value for the property if no input
191: * is received
192: */
193: public void setDefaultvalue(String defaultvalue) {
194: this .defaultvalue = defaultvalue;
195: }
196:
197: /**
198: * Set a multiline message.
199: * @param msg The message to be displayed.
200: */
201: public void addText(String msg) {
202: if (messageAttribute && "".equals(msg.trim())) {
203: return;
204: }
205: message += getProject().replaceProperties(msg);
206: }
207:
208: /**
209: * No arg constructor.
210: */
211: public Input() {
212: }
213:
214: /**
215: * Actual method executed by ant.
216: * @throws BuildException on error
217: */
218: public void execute() throws BuildException {
219: if (addproperty != null
220: && getProject().getProperty(addproperty) != null) {
221: log("skipping " + getTaskName() + " as property "
222: + addproperty + " has already been set.");
223: return;
224: }
225:
226: InputRequest request = null;
227: if (validargs != null) {
228: Vector accept = StringUtils.split(validargs, ',');
229: request = new MultipleChoiceInputRequest(message, accept);
230: } else {
231: request = new InputRequest(message);
232: }
233: request.setDefaultValue(defaultvalue);
234:
235: InputHandler h = handler == null ? getProject()
236: .getInputHandler() : handler.getInputHandler();
237:
238: h.handleInput(request);
239:
240: String value = request.getInput();
241: if ((value == null || value.trim().length() == 0)
242: && defaultvalue != null) {
243: value = defaultvalue;
244: }
245: if (addproperty != null && value != null) {
246: getProject().setNewProperty(addproperty, value);
247: }
248: }
249:
250: /**
251: * Create a nested handler element.
252: * @return a Handler for this Input task.
253: */
254: public Handler createHandler() {
255: if (handler != null) {
256: throw new BuildException(
257: "Cannot define > 1 nested input handler");
258: }
259: handler = new Handler();
260: return handler;
261: }
262:
263: }
|