ant-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ivan Ivanov <rambiusparkisan...@yahoo.com>
Subject Re: AW: Creating custom InputHandler
Date Wed, 14 Jul 2004 07:09:14 GMT
Hello Jan,
I implemnted carefully your ideas and here are the
results which I received and some more questions. I am
using ant1.6.2beta1 sources and the new input handler
which I created is called
org.apache.tools.ant.PropertyExpandInputHandler (shown
below). You recommended me to create a task
SetProjectRefrerenceOnInputHanlder, which will call
setProject(Project) method of
PropertyExpandInputHandler. It turned that this task
is not needed, because Ant "magically" sets the
project reference of the input handler. More
precilsely
this is done in org.apache.tools.ant.Project by
setProjectReference() method:

public final void setProjectReference(final Object
obj) {
    if (obj instanceof ProjectComponent) {
        ((ProjectComponent) obj).setProject(this);
        return;
    }
    try {
        Method method =
            obj.getClass().getMethod(
                "setProject", new Class[]
{Project.class});
        if (method != null) {
            method.invoke(obj, new Object[] {this});
        }
    } catch (Throwable e) {
        // ignore this if the object does not have
        // a set project method or the method
        // is private/protected.
    }
},
called on the object paramameters of the build file.
This method shows that it is not necessary to make
PropertyExpandInputHandler extend ProjectComponent,
because it will call its setProject(Project)
via reflection. However, I made it ProjectComponent
for clarity.

Here is the actual code of PropertyExpandInputHandler
and the question it arises.

package org.apache.tools.ant.input;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.ProjectComponent;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.util.KeepAliveInputStream;

public class PropertyExpandInputHandler extends
ProjectComponent implements InputHandler {

    /**
     * The project this input handler is used in.
     * This reference is needed when we resolve the
properties.
     */
    private Project project;

    /**
     * Empty no-arg constructor
     */
    public PropertyExpandInputHandler() {
    }

    /**
     * Prompts and requests input.  When the input is
received
     * the properties in it are expanded to their
values set in
     * the current project.
     * May loop until a valid input has been entered.
     * @param request the request to handle
     * @throws BuildException if not possible to read
from console
     */
    public void handleInput(InputRequest request)
throws BuildException {
        String prompt = getPrompt(request);
        DataInputStream in = null;
        try {
            in =
                new DataInputStream(new
KeepAliveInputStream(getInputStream()));
            do {
                System.err.println(prompt);
                System.err.flush();
                try {
                    String input = in.readLine();
                    input =
project.replaceProperties(input);
                    request.setInput(input);
                } catch (IOException e) {
                    throw new BuildException("Failed
to read input from"
                                             + "
Console.", e);
                }
            } while (!request.isInputValid());
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    throw new BuildException("Failed
to close input.", e);
                }
            }
        }
    }

    /**
     * Constructs user prompt from a request.
     *
     * <p>This implementation adds
(choice1,choice2,choice3,...) to the
     * prompt for
<code>MultipleChoiceInputRequest</code>s.</p>
     *
     * @param request the request to construct the
prompt for.
     *                Must not be <code>null</code>.
     * @return the prompt to ask the user
     */
    protected String getPrompt(InputRequest request) {
        String prompt = request.getPrompt();
        if (request instanceof
MultipleChoiceInputRequest) {
            StringBuffer sb = new
StringBuffer(prompt);
            sb.append("(");
            Enumeration e =
                ((MultipleChoiceInputRequest)
request).getChoices().elements();
            boolean first = true;
            while (e.hasMoreElements()) {
                if (!first) {
                    sb.append(",");
                }
                sb.append(e.nextElement());
                first = false;
            }
            sb.append(")");
            prompt = sb.toString();
        }
        return prompt;
    }

    /**
     * Returns the input stream from which the user
input should be read.
     * @return the input stream from which the user
input should be read.
     */
    protected InputStream getInputStream() {
        return System.in;
    }

    /**
     * Sets the project to which this input handler
belongs to.
     *
     * param project the project in which this input
handler is used.
     */
    public void setProject(Project project) {
        this.project = project;
    }

    public Project getProject() {
        return project;
    }
}

The issue here is that PropertyExpandInputHandler
simply duplicates DefaultInputHandler with the single
difference in the line 
input = project.replaceProperties(input);
I thought that PropertyExpandInputHandler can extend
DefaultInputHandler but then it cannot extend
ProjectComponent. Do you think, I will lose
something if I extend DefaultInputHandler and let ant
call setProject via refelection? I would ask you also
to point me any weaknesses of the above code since it
is my first extesion of Ant :)).

Thank you very much for your help.

Ivan

--- Jan.Materne@rzf.fin-nrw.de wrote:
> Indeed, seems to be a problem.
> 
> The initialization procedure for InputHandlers
> doesnt store a project
> reference (and 
> couldnt do it, because the IH-Interface doesnt
> requires a
> setProject(Project) method).
> 
> So only a workaround comes into my mind:
> - your InputHandler has to provide the setProject
> method
> - set the reference for yourself before using the
> handler by using a Task:
>   (code not tested - even compiled):
>   public class SetProjectReferenceOnInputHandler
> extends Task {
>       public void execute() {
>           InputHandler ih =
> getProject().getInputHandler();
>           if (ih instanceof MyInputHandler) {
>              
> ((MyInputHandler)ih).setProject(getProject());
>           }
>       }
>   }
>   
> 
> Maybe we should check if the InputHandler is a
> ProjectComponent and set the
> project
> reference then ... 
> 
> 
> Jan



	
		
__________________________________
Do you Yahoo!?
New and Improved Yahoo! Mail - 100MB free storage!
http://promotions.yahoo.com/new_mail 

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@ant.apache.org
For additional commands, e-mail: user-help@ant.apache.org


Mime
View raw message