Как заставить Ant загрузить и проверить ресурс URL в задаче waitfor? - PullRequest
2 голосов
/ 29 января 2010

Я работаю над целью Ant для запуска тестов, и мне нужно, чтобы сервер приложений был запущен и запущен до запуска тестов. Я использую задачу waitFor для проверки связи с URL, пока он не получит ответ. Это работает, за исключением того, что мне нужно не только убедиться, что URL-адрес просто доступен, но и проверить, присутствует ли конкретная строка состояния. Это второе требование простое само по себе, с задачей get или telnet, за которой следует поиск по подстроке. Но задача waitfor не принимает никаких вложенных элементов, кроме стандартных условий Ant, или вещей, которые они могут переносить (вещи, которые возвращают логические значения). Я попытался загрузить URL-адрес как ресурс перед запуском задачи waitfor с условием resourceconatins, но он кэширует ответ и не обновляется с сервера.

Есть ли способ заставить URL-адрес загружаться в каждом цикле? Или каким-то другим способом добиться этого?

Вот что я хочу достичь в псевдокоде:

<waitfor>
    <and>
        <!-- make sure the URL is accessible at all -->
        <http url="theurl.jsp"/>

        <!-- load the URL as a resource and make sure it contains a substring -->
        <!-- moving the "url" task before the waitfor works if all conditions are met the first time through, but does not refresh the URL if it has to loop over again. having it inside like this, fails because waitfor/and don't support nexted "url" tasks -->
        <url id="url.resource" url="url.jsp"/>
        <resourcecontains refid="url.resource" substring="status"/>
    </and>
    <!-- else, keep on trying until timeout -->
</waitfor>
<!-- continue on to the tests to be run -->

Ответы [ 2 ]

1 голос
/ 30 марта 2010

Использование:

   <typedef
      name="httpcontains"
      classname="HttpContains"
   />

  <waitfor maxwait="10" maxwaitunit="minute" checkevery="500">
    <httpcontains contains="Running" url="http://myurl"/>
  </waitfor>

Код ниже позволяет:

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.ProjectComponent;
import org.apache.tools.ant.taskdefs.condition.Condition;

/**
 * Condition to wait for a HTTP request to succeed. Its attribute(s) are:
 *   url - the URL of the request.
 *   errorsBeginAt - number at which errors begin at; default=400.
 * @since Ant 1.5
 */
public class HttpContains extends ProjectComponent implements Condition {
    private String spec = null;
    private String contains = null;
    /**
     * Set the url attribute
     *
     * @param url the url of the request
     */
    public void setUrl(String url) {
        spec = url;
    }

    public void setContains(String s){
       contains = s;
    }

    private int errorsBeginAt = 400;

    /**
     * Set the errorsBeginAt attribute
     *
     * @param errorsBeginAt number at which errors begin at, default is
     *                      400
     */
    public void setErrorsBeginAt(int errorsBeginAt) {
        this.errorsBeginAt = errorsBeginAt;
    }

    /**
     * @return true if the HTTP request succeeds
     * @exception BuildException if an error occurs
     */
    public boolean eval() throws BuildException {
        if (spec == null) {
            throw new BuildException("No url specified in http condition");
        }
        log("Checking for " + spec, Project.MSG_VERBOSE);
        try {
            URL url = new URL(spec);
            try {
                URLConnection conn = url.openConnection();
                if (conn instanceof HttpURLConnection) {
                    HttpURLConnection http = (HttpURLConnection) conn;
                    int code = http.getResponseCode();
                    log("Result code for " + spec + " was " + code,
                        Project.MSG_VERBOSE);
                    if (code > 0 && code < errorsBeginAt) 
                    {
                       if ( evalContents(url) )
                          return true;
                       else
                          return false;

                    } else {
                        return false;
                    }
                }
            } catch (java.io.IOException e) {
                return false;
            }
        } catch (MalformedURLException e) {
            throw new BuildException("Badly formed URL: " + spec, e);
        }
        return true;
    }

    public boolean evalContents(URL mUrl )
    {
       try
       {

          String contents;

          StringBuffer buffer = new StringBuffer();
          byte[] buf = new byte[1024];
          int amount = 0;
          InputStream input = mUrl.openStream();

          while ((amount = input.read(buf)) > 0) 
          {   
             buffer.append(new String(buf, 0, amount));
          }
          input.close();
          contents = buffer.toString();

          log("Result code for " + contents,
                Project.MSG_VERBOSE);

          if ( contents.indexOf(contains) > -1 )
          {

             log("Result code for " + contents.indexOf(contains),
                   Project.MSG_VERBOSE);
             return true;

          }






          return false;
       }
       catch ( Exception e )
       {
          e.printStackTrace();
          log("Result code for " + e.toString(),
                Project.MSG_VERBOSE);

          return false;
       }
    }
}
1 голос
/ 29 января 2010

Вы можете достичь этого, используя цель, вызванную из элемента scriptcondition в waitfor. Вот пример.

Чтобы использовать его, необходимо установить свойства theurl и content.matches для рассматриваемого ресурса и строку для сопоставления соответственно. При необходимости измените настройки «maxwait».

Свойство theurl.fail установлено на тайм-аут.

<target name="lr">
    <local name="local.data" />
    <loadresource property="local.data">
        <url url="${theurl}" />
    </loadresource>
    <condition property="theurl.matches">
       <matches pattern="${content.matches}" string="${local.data}"/>
    </condition>
</target>

<waitfor maxwait="10" maxwaitunit="second" timeoutproperty="theurl.fail">
    <scriptcondition language="javascript" value="false">
    <![CDATA[
        project.getTargets().get( "lr" ).execute( );
        if ( project.getProperty( "theurl.matches" ) )
            self.setValue( true );
    ]]>
    </scriptcondition>
</waitfor>

Для этого используется задача Ant local, которая была новой в v1.8. Цель lr извлекает URL и ищет совпадение, если найдено, установлено свойство theurl.matches. scriptcondition выполняет цель, встроенную в waitfor, до успеха или тайм-аута.

Я проверил это по Времени мастерства Военно-морской обсерватории США и различным коротким временным цепочкам, казалось, работало хорошо.

...