首页

关于htmlunit源码包中的UrlUtils资源地址工具类进行加密、转换解析等相关处理

标签:htmlunit,UrlUtils,资源地址工具类     发布时间:2018-06-09   

一、前言

关于htmlunit源码包中的com.gargoylesoftware.htmlunit.util.UrlUtils资源工具类,进行字符串转为URL对象toUrlSafe、对url地址解密处理encodeUrl、解密处理decode、根据协议及主机/端口等获取URL对象地址getUrlWithNewHost/getUrlWithNewPort/getUrlWithNewPath/getUrlWithNewRef等操作。

二、源码说明

1.UrlUtils类(其中StringUtils参见其他文章)

package com.gargoylesoftware.htmlunit.util;@b@@b@import com.gargoylesoftware.htmlunit.WebAssert;@b@import java.io.UnsupportedEncodingException;@b@import java.net.MalformedURLException;@b@import java.net.URL;@b@import java.util.BitSet;@b@import org.apache.commons.codec.DecoderException;@b@import org.apache.commons.codec.net.URLCodec;@b@@b@public final class UrlUtils@b@{@b@  private static final BitSet PATH_ALLOWED_CHARS = new BitSet(256);@b@  private static final BitSet QUERY_ALLOWED_CHARS = new BitSet(256);@b@  private static final BitSet ANCHOR_ALLOWED_CHARS = new BitSet(256);@b@  private static final URLCreator URL_CREATOR = URLCreator.getCreator();@b@@b@  public static URL toUrlSafe(String url)@b@  {@b@    try@b@    {@b@      return toUrlUnsafe(url);@b@    }@b@    catch (MalformedURLException e)@b@    {@b@      throw new RuntimeException(e);@b@    }@b@  }@b@@b@  public static URL toUrlUnsafe(String url)@b@    throws MalformedURLException@b@  {@b@    WebAssert.notNull("url", url);@b@    return URL_CREATOR.toUrlUnsafeClassic(url);@b@  }@b@@b@  public static URL encodeUrl(URL url, boolean minimalQueryEncoding)@b@  {@b@    String p = url.getProtocol();@b@    if (("javascript".equalsIgnoreCase(p)) || ("about".equalsIgnoreCase(p)) || ("data".equalsIgnoreCase(p)))@b@    {@b@      return url;@b@    }@b@    try {@b@      String path = url.getPath();@b@      if (path != null)@b@        path = encode(path, PATH_ALLOWED_CHARS, "utf-8");@b@@b@      String query = url.getQuery();@b@      if (query != null)@b@        if (minimalQueryEncoding) {@b@          query = org.apache.commons.lang.StringUtils.replace(query, " ", "%20");@b@        }@b@        else@b@          query = encode(query, QUERY_ALLOWED_CHARS, "windows-1252");@b@@b@@b@      String anchor = url.getRef();@b@      if (anchor != null)@b@        anchor = encode(anchor, ANCHOR_ALLOWED_CHARS, "utf-8");@b@@b@      return createNewUrl(url.getProtocol(), url.getHost(), url.getPort(), path, anchor, query);@b@    }@b@    catch (MalformedURLException e)@b@    {@b@      throw new RuntimeException(e);@b@    }@b@  }@b@@b@  public static String encodeAnchor(String anchor)@b@  {@b@    if (anchor != null)@b@      anchor = encode(anchor, ANCHOR_ALLOWED_CHARS, "utf-8");@b@@b@    return anchor;@b@  }@b@@b@  public static String decode(String escaped)@b@  {@b@    byte[] bytes;@b@    try@b@    {@b@      bytes = escaped.getBytes("US-ASCII");@b@      byte[] bytes2 = URLCodec.decodeUrl(bytes);@b@      return new String(bytes2, "UTF-8");@b@    }@b@    catch (UnsupportedEncodingException e)@b@    {@b@      throw new RuntimeException(e);@b@    }@b@    catch (DecoderException e)@b@    {@b@      throw new RuntimeException(e);@b@    }@b@  }@b@@b@  private static String encode(String unescaped, BitSet allowed, String charset)@b@  {@b@    byte[] bytes;@b@    try@b@    {@b@      bytes = unescaped.getBytes(charset);@b@      byte[] bytes2 = URLCodec.encodeUrl(allowed, bytes);@b@      return new String(bytes2, "US-ASCII");@b@    }@b@    catch (UnsupportedEncodingException e)@b@    {@b@      throw new RuntimeException(e);@b@    }@b@  }@b@@b@  public static URL getUrlWithNewProtocol(URL u, String newProtocol)@b@    throws MalformedURLException@b@  {@b@    return createNewUrl(newProtocol, u.getHost(), u.getPort(), u.getPath(), u.getRef(), u.getQuery());@b@  }@b@@b@  public static URL getUrlWithNewHost(URL u, String newHost)@b@    throws MalformedURLException@b@  {@b@    return createNewUrl(u.getProtocol(), newHost, u.getPort(), u.getPath(), u.getRef(), u.getQuery());@b@  }@b@@b@  public static URL getUrlWithNewPort(URL u, int newPort)@b@    throws MalformedURLException@b@  {@b@    return createNewUrl(u.getProtocol(), u.getHost(), newPort, u.getPath(), u.getRef(), u.getQuery());@b@  }@b@@b@  public static URL getUrlWithNewPath(URL u, String newPath)@b@    throws MalformedURLException@b@  {@b@    return createNewUrl(u.getProtocol(), u.getHost(), u.getPort(), newPath, u.getRef(), u.getQuery());@b@  }@b@@b@  public static URL getUrlWithNewRef(URL u, String newRef)@b@    throws MalformedURLException@b@  {@b@    return createNewUrl(u.getProtocol(), u.getHost(), u.getPort(), u.getPath(), newRef, u.getQuery());@b@  }@b@@b@  public static URL getUrlWithNewQuery(URL u, String newQuery)@b@    throws MalformedURLException@b@  {@b@    return createNewUrl(u.getProtocol(), u.getHost(), u.getPort(), u.getPath(), u.getRef(), newQuery);@b@  }@b@@b@  private static URL createNewUrl(String protocol, String host, int port, String path, String ref, String query)@b@    throws MalformedURLException@b@  {@b@    StringBuilder s = new StringBuilder();@b@    s.append(protocol);@b@    s.append("://");@b@    s.append(host);@b@    if (port != -1)@b@      s.append(":").append(port);@b@@b@    if ((path != null) && (path.length() > 0)) {@b@      if ('/' != path.charAt(0))@b@        s.append("/");@b@@b@      s.append(path);@b@    }@b@    if (query != null)@b@      s.append("?").append(query);@b@@b@    if (ref != null) {@b@      if ((ref.length() <= 0) || ('#' != ref.charAt(0)))@b@        s.append("#");@b@@b@      s.append(ref);@b@    }@b@    URL url = new URL(s.toString());@b@    return url;@b@  }@b@@b@  public static String resolveUrl(String baseUrl, String relativeUrl)@b@  {@b@    if (baseUrl == null)@b@      throw new IllegalArgumentException("Base URL must not be null");@b@@b@    if (relativeUrl == null)@b@      throw new IllegalArgumentException("Relative URL must not be null");@b@@b@    Url url = resolveUrl(parseUrl(baseUrl.trim()), relativeUrl.trim());@b@@b@    return url.toString();@b@  }@b@@b@  public static String resolveUrl(URL baseUrl, String relativeUrl)@b@  {@b@    if (baseUrl == null)@b@      throw new IllegalArgumentException("Base URL must not be null");@b@@b@    return resolveUrl(baseUrl.toExternalForm(), relativeUrl);@b@  }@b@@b@  private static Url parseUrl(String spec)@b@  {@b@    int locationStartIndex;@b@    int locationEndIndex;@b@    Url url = new Url();@b@    int startIndex = 0;@b@    int endIndex = spec.length();@b@@b@    int crosshatchIndex = StringUtils.indexOf(spec, '#', startIndex, endIndex);@b@@b@    if (crosshatchIndex >= 0) {@b@      Url.access$002(url, spec.substring(crosshatchIndex + 1, endIndex));@b@      endIndex = crosshatchIndex;@b@    }@b@@b@    int colonIndex = StringUtils.indexOf(spec, ':', startIndex, endIndex);@b@@b@    if (colonIndex > 0) {@b@      String scheme = spec.substring(startIndex, colonIndex);@b@      if (isValidScheme(scheme)) {@b@        Url.access$102(url, scheme);@b@        startIndex = colonIndex + 1;@b@      }@b@@b@    }@b@@b@    if (spec.startsWith("//", startIndex)) {@b@      locationStartIndex = startIndex + 2;@b@      locationEndIndex = StringUtils.indexOf(spec, '/', locationStartIndex, endIndex);@b@      if (locationEndIndex >= 0)@b@        startIndex = locationEndIndex;@b@    }@b@    else@b@    {@b@      locationStartIndex = -1;@b@      locationEndIndex = -1;@b@    }@b@@b@    int questionMarkIndex = StringUtils.indexOf(spec, '?', startIndex, endIndex);@b@@b@    if (questionMarkIndex >= 0) {@b@      if ((locationStartIndex >= 0) && (locationEndIndex < 0))@b@      {@b@        locationEndIndex = questionMarkIndex;@b@        startIndex = questionMarkIndex;@b@      }@b@      Url.access$202(url, spec.substring(questionMarkIndex + 1, endIndex));@b@      endIndex = questionMarkIndex;@b@    }@b@@b@    int semicolonIndex = StringUtils.indexOf(spec, ';', startIndex, endIndex);@b@@b@    if (semicolonIndex >= 0) {@b@      if ((locationStartIndex >= 0) && (locationEndIndex < 0))@b@      {@b@        locationEndIndex = semicolonIndex;@b@        startIndex = semicolonIndex;@b@      }@b@      Url.access$302(url, spec.substring(semicolonIndex + 1, endIndex));@b@      endIndex = semicolonIndex;@b@    }@b@@b@    if ((locationStartIndex >= 0) && (locationEndIndex < 0))@b@    {@b@      locationEndIndex = endIndex;@b@    }@b@    else if (startIndex < endIndex) {@b@      Url.access$402(url, spec.substring(startIndex, endIndex));@b@    }@b@@b@    if ((locationStartIndex >= 0) && (locationEndIndex >= 0))@b@      Url.access$502(url, spec.substring(locationStartIndex, locationEndIndex));@b@@b@    return url;@b@  }@b@@b@  private static boolean isValidScheme(String scheme)@b@  {@b@    int length = scheme.length();@b@    if (length < 1)@b@      return false;@b@@b@    char c = scheme.charAt(0);@b@    if (!(Character.isLetter(c)))@b@      return false;@b@@b@    for (int i = 1; i < length; ++i) {@b@      c = scheme.charAt(i);@b@      if ((!(Character.isLetterOrDigit(c))) && (c != '.') && (c != '+') && (c != '-'))@b@        return false;@b@    }@b@@b@    return true;@b@  }@b@@b@  private static Url resolveUrl(Url baseUrl, String relativeUrl)@b@  {@b@    int pathSegmentIndex;@b@    String pathSegment;@b@    int slashIndex;@b@    Url url = parseUrl(relativeUrl);@b@@b@    if (baseUrl == null) {@b@      return url;@b@    }@b@@b@    if (relativeUrl.length() == 0) {@b@      return new Url(baseUrl);@b@    }@b@@b@    if (Url.access$100(url) != null) {@b@      return url;@b@    }@b@@b@    Url.access$102(url, Url.access$100(baseUrl));@b@@b@    if (Url.access$500(url) != null)@b@      return url;@b@@b@    Url.access$502(url, Url.access$500(baseUrl));@b@@b@    if ((Url.access$400(url) != null) && (Url.access$400(url).length() > 0) && ('/' == Url.access$400(url).charAt(0))) {@b@      Url.access$402(url, removeLeadingSlashPoints(Url.access$400(url)));@b@      return url;@b@    }@b@@b@    if (Url.access$400(url) == null) {@b@      Url.access$402(url, Url.access$400(baseUrl));@b@@b@      if (Url.access$300(url) != null)@b@        return url;@b@@b@      Url.access$302(url, Url.access$300(baseUrl));@b@@b@      if (Url.access$200(url) != null)@b@        return url;@b@@b@      Url.access$202(url, Url.access$200(baseUrl));@b@      return url;@b@    }@b@@b@    String basePath = Url.access$400(baseUrl);@b@    String path = "";@b@@b@    if (basePath != null) {@b@      int lastSlashIndex = basePath.lastIndexOf(47);@b@@b@      if (lastSlashIndex >= 0)@b@        path = basePath.substring(0, lastSlashIndex + 1);@b@    }@b@    else@b@    {@b@      path = "/";@b@    }@b@    path = path.concat(Url.access$400(url));@b@@b@    while ((pathSegmentIndex = path.indexOf("/./")) >= 0) {@b@      path = path.substring(0, pathSegmentIndex + 1).concat(path.substring(pathSegmentIndex + 3));@b@    }@b@@b@    if (path.endsWith("/.")) {@b@      path = path.substring(0, path.length() - 1);@b@    }@b@@b@    while (true)@b@    {@b@      while (true)@b@      {@b@        if ((pathSegmentIndex = path.indexOf("/../")) <= 0) break label363;@b@        pathSegment = path.substring(0, pathSegmentIndex);@b@        slashIndex = pathSegment.lastIndexOf(47);@b@@b@        if (slashIndex >= 0)@b@          break;@b@      }@b@      if (!("..".equals(pathSegment.substring(slashIndex)))) {@b@        path = path.substring(0, slashIndex + 1).concat(path.substring(pathSegmentIndex + 4));@b@      }@b@@b@    }@b@@b@    if (path.endsWith("/..")) {@b@      label363: pathSegment = path.substring(0, path.length() - 3);@b@      slashIndex = pathSegment.lastIndexOf(47);@b@@b@      if (slashIndex >= 0)@b@        path = path.substring(0, slashIndex + 1);@b@@b@    }@b@@b@    path = removeLeadingSlashPoints(path);@b@@b@    Url.access$402(url, path);@b@@b@    return url;@b@  }@b@@b@  private static String removeLeadingSlashPoints(String path)@b@  {@b@    while (path.startsWith("/..")) {@b@      path = path.substring(3);@b@    }@b@@b@    return path;@b@  }@b@@b@  static@b@  {@b@    BitSet reserved = new BitSet(256);@b@    reserved.set(59);@b@    reserved.set(47);@b@    reserved.set(63);@b@    reserved.set(58);@b@    reserved.set(64);@b@    reserved.set(38);@b@    reserved.set(61);@b@    reserved.set(43);@b@    reserved.set(36);@b@    reserved.set(44);@b@@b@    BitSet mark = new BitSet(256);@b@    mark.set(45);@b@    mark.set(95);@b@    mark.set(46);@b@    mark.set(33);@b@    mark.set(126);@b@    mark.set(42);@b@    mark.set(39);@b@    mark.set(40);@b@    mark.set(41);@b@@b@    BitSet alpha = new BitSet(256);@b@    for (int i = 97; i <= 122; ++i)@b@      alpha.set(i);@b@@b@    for (i = 65; i <= 90; ++i) {@b@      alpha.set(i);@b@    }@b@@b@    BitSet digit = new BitSet(256);@b@    for (int i = 48; i <= 57; ++i) {@b@      digit.set(i);@b@    }@b@@b@    BitSet alphanumeric = new BitSet(256);@b@    alphanumeric.or(alpha);@b@    alphanumeric.or(digit);@b@@b@    BitSet unreserved = new BitSet(256);@b@    unreserved.or(alphanumeric);@b@    unreserved.or(mark);@b@@b@    BitSet hex = new BitSet(256);@b@    hex.or(digit);@b@    for (int i = 97; i <= 102; ++i)@b@      hex.set(i);@b@@b@    for (i = 65; i <= 70; ++i) {@b@      hex.set(i);@b@    }@b@@b@    BitSet escaped = new BitSet(256);@b@    escaped.set(37);@b@    escaped.or(hex);@b@@b@    BitSet uric = new BitSet(256);@b@    uric.or(reserved);@b@    uric.or(unreserved);@b@    uric.or(escaped);@b@@b@    BitSet pchar = new BitSet(256);@b@    pchar.or(unreserved);@b@    pchar.or(escaped);@b@    pchar.set(58);@b@    pchar.set(64);@b@    pchar.set(38);@b@    pchar.set(61);@b@    pchar.set(43);@b@    pchar.set(36);@b@    pchar.set(44);@b@@b@    BitSet param = pchar;@b@@b@    BitSet segment = new BitSet(256);@b@    segment.or(pchar);@b@    segment.set(59);@b@    segment.or(param);@b@@b@    BitSet pathSegments = new BitSet(256);@b@    pathSegments.set(47);@b@    pathSegments.or(segment);@b@@b@    BitSet absPath = new BitSet(256);@b@    absPath.set(47);@b@    absPath.or(pathSegments);@b@@b@    BitSet allowedAbsPath = new BitSet(256);@b@    allowedAbsPath.or(absPath);@b@@b@    BitSet allowedFragment = new BitSet(256);@b@    allowedFragment.or(uric);@b@@b@    BitSet allowedQuery = new BitSet(256);@b@    allowedQuery.or(uric);@b@@b@    PATH_ALLOWED_CHARS.or(allowedAbsPath);@b@    QUERY_ALLOWED_CHARS.or(allowedQuery);@b@    ANCHOR_ALLOWED_CHARS.or(allowedFragment);@b@  }@b@@b@  private static class Url@b@  {@b@    private String scheme_;@b@    private String location_;@b@    private String path_;@b@    private String parameters_;@b@    private String query_;@b@    private String fragment_;@b@@b@    public Url()@b@    {@b@    }@b@@b@    public Url(Url url)@b@    {@b@      this.scheme_ = url.scheme_;@b@      this.location_ = url.location_;@b@      this.path_ = url.path_;@b@      this.parameters_ = url.parameters_;@b@      this.query_ = url.query_;@b@      this.fragment_ = url.fragment_;@b@    }@b@@b@    public String toString()@b@    {@b@      StringBuilder sb = new StringBuilder();@b@@b@      if (this.scheme_ != null) {@b@        sb.append(this.scheme_);@b@        sb.append(':');@b@      }@b@      if (this.location_ != null) {@b@        sb.append("//");@b@        sb.append(this.location_);@b@      }@b@      if (this.path_ != null)@b@        sb.append(this.path_);@b@@b@      if (this.parameters_ != null) {@b@        sb.append(';');@b@        sb.append(this.parameters_);@b@      }@b@      if (this.query_ != null) {@b@        sb.append('?');@b@        sb.append(this.query_);@b@      }@b@      if (this.fragment_ != null) {@b@        sb.append('#');@b@        sb.append(this.fragment_);@b@      }@b@      return sb.toString();@b@    }@b@  }@b@}

2.WebAssert类

 package com.gargoylesoftware.htmlunit;@b@@b@import com.gargoylesoftware.htmlunit.html.HtmlAnchor;@b@import com.gargoylesoftware.htmlunit.html.HtmlElement;@b@import com.gargoylesoftware.htmlunit.html.HtmlInput;@b@import com.gargoylesoftware.htmlunit.html.HtmlPage;@b@import java.util.ArrayList;@b@import java.util.Arrays;@b@import java.util.List;@b@@b@public final class WebAssert@b@{@b@  public static void assertTitleEquals(HtmlPage page, String title)@b@  {@b@    String s = page.getTitleText();@b@    if (!(s.equals(title))) {@b@      String msg = "Actual page title '" + s + "' does not match expected page title '" + title + "'.";@b@      throw new AssertionError(msg);@b@    }@b@  }@b@@b@  public static void assertTitleContains(HtmlPage page, String titlePortion)@b@  {@b@    String s = page.getTitleText();@b@    if (s.indexOf(titlePortion) == -1) {@b@      String msg = "Page title '" + s + "' does not contain the substring '" + titlePortion + "'.";@b@      throw new AssertionError(msg);@b@    }@b@  }@b@@b@  public static void assertTitleMatches(HtmlPage page, String regex)@b@  {@b@    String s = page.getTitleText();@b@    if (!(s.matches(regex))) {@b@      String msg = "Page title '" + s + "' does not match the regular expression '" + regex + "'.";@b@      throw new AssertionError(msg);@b@    }@b@  }@b@@b@  public static void assertElementPresent(HtmlPage page, String id)@b@  {@b@    try@b@    {@b@      page.getHtmlElementById(id);@b@    }@b@    catch (ElementNotFoundException e) {@b@      String msg = "The page does not contain an element with ID '" + id + "'.";@b@      throw new AssertionError(msg);@b@    }@b@  }@b@@b@  public static void assertElementPresentByXPath(HtmlPage page, String xpath)@b@  {@b@    List elements = page.getByXPath(xpath);@b@    if (elements.isEmpty()) {@b@      String msg = "The page does not contain any elements matching the XPath expression '" + xpath + "'.";@b@@b@      throw new AssertionError(msg);@b@    }@b@  }@b@@b@  public static void assertElementNotPresent(HtmlPage page, String id)@b@  {@b@    try@b@    {@b@      page.getHtmlElementById(id);@b@    }@b@    catch (ElementNotFoundException e) {@b@      return;@b@    }@b@    String msg = "The page contains an element with ID '" + id + "'.";@b@    throw new AssertionError(msg);@b@  }@b@@b@  public static void assertElementNotPresentByXPath(HtmlPage page, String xpath)@b@  {@b@    List elements = page.getByXPath(xpath);@b@    if (!(elements.isEmpty())) {@b@      String msg = "The page does not contain any elements matching the XPath expression '" + xpath + "'.";@b@@b@      throw new AssertionError(msg);@b@    }@b@  }@b@@b@  public static void assertTextPresent(HtmlPage page, String text)@b@  {@b@    if (page.asText().indexOf(text) == -1) {@b@      String msg = "The page does not contain the text '" + text + "'.";@b@      throw new AssertionError(msg);@b@    }@b@  }@b@@b@  public static void assertTextPresentInElement(HtmlPage page, String text, String id)@b@  {@b@    HtmlElement element;@b@    String msg;@b@    try@b@    {@b@      element = page.getHtmlElementById(id);@b@      if (element.asText().indexOf(text) == -1) {@b@        msg = "The element with ID '" + id + "' does not contain the text '" + text + "'.";@b@        throw new AssertionError(msg);@b@      }@b@    }@b@    catch (ElementNotFoundException e) {@b@      msg = "Unable to verify that the element with ID '" + id + "' contains the text '" + text + "' because the specified element does not exist.";@b@@b@      throw new AssertionError(msg);@b@    }@b@  }@b@@b@  public static void assertTextNotPresent(HtmlPage page, String text)@b@  {@b@    if (page.asText().contains(text)) {@b@      String msg = "The page contains the text '" + text + "'.";@b@      throw new AssertionError(msg);@b@    }@b@  }@b@@b@  public static void assertTextNotPresentInElement(HtmlPage page, String text, String id)@b@  {@b@    HtmlElement element;@b@    String msg;@b@    try@b@    {@b@      element = page.getHtmlElementById(id);@b@      if (element.asText().contains(text)) {@b@        msg = "The element with ID '" + id + "' contains the text '" + text + "'.";@b@        throw new AssertionError(msg);@b@      }@b@    }@b@    catch (ElementNotFoundException e) {@b@      msg = "Unable to verify that the element with ID '" + id + "' does not contain the text '" + text + "' because the specified element does not exist.";@b@@b@      throw new AssertionError(msg);@b@    }@b@  }@b@@b@  public static void assertLinkPresent(HtmlPage page, String id)@b@  {@b@    try@b@    {@b@      page.getDocumentElement().getOneHtmlElementByAttribute("a", "id", id);@b@    }@b@    catch (ElementNotFoundException e) {@b@      String msg = "The page does not contain a link with ID '" + id + "'.";@b@      throw new AssertionError(msg);@b@    }@b@  }@b@@b@  public static void assertLinkNotPresent(HtmlPage page, String id)@b@  {@b@    try@b@    {@b@      page.getDocumentElement().getOneHtmlElementByAttribute("a", "id", id);@b@@b@      String msg = "The page contains a link with ID '" + id + "'.";@b@      throw new AssertionError(msg);@b@    }@b@    catch (ElementNotFoundException e)@b@    {@b@    }@b@  }@b@@b@  public static void assertLinkPresentWithText(HtmlPage page, String text)@b@  {@b@    boolean found = false;@b@    for (HtmlAnchor a : page.getAnchors())@b@      if (a.asText().contains(text)) {@b@        found = true;@b@        break;@b@      }@b@@b@    if (!(found)) {@b@      String msg = "The page does not contain a link with text '" + text + "'.";@b@      throw new AssertionError(msg);@b@    }@b@  }@b@@b@  public static void assertLinkNotPresentWithText(HtmlPage page, String text)@b@  {@b@    boolean found = false;@b@    for (HtmlAnchor a : page.getAnchors())@b@      if (a.asText().contains(text)) {@b@        found = true;@b@        break;@b@      }@b@@b@    if (found) {@b@      String msg = "The page contains a link with text '" + text + "'.";@b@      throw new AssertionError(msg);@b@    }@b@  }@b@@b@  public static void assertFormPresent(HtmlPage page, String name)@b@  {@b@    try@b@    {@b@      page.getFormByName(name);@b@    }@b@    catch (ElementNotFoundException e) {@b@      String msg = "The page does not contain a form named '" + name + "'.";@b@      throw new AssertionError(msg);@b@    }@b@  }@b@@b@  public static void assertFormNotPresent(HtmlPage page, String name)@b@  {@b@    try@b@    {@b@      page.getFormByName(name);@b@    }@b@    catch (ElementNotFoundException e) {@b@      return;@b@    }@b@    String msg = "The page contains a form named '" + name + "'.";@b@    throw new AssertionError(msg);@b@  }@b@@b@  public static void assertInputPresent(HtmlPage page, String name)@b@  {@b@    String xpath = "//input[@name='" + name + "']";@b@    List list = page.getByXPath(xpath);@b@    if (list.isEmpty())@b@      throw new AssertionError("Unable to find an input element named '" + name + "'.");@b@  }@b@@b@  public static void assertInputNotPresent(HtmlPage page, String name)@b@  {@b@    String xpath = "//input[@name='" + name + "']";@b@    List list = page.getByXPath(xpath);@b@    if (!(list.isEmpty()))@b@      throw new AssertionError("Unable to find an input element named '" + name + "'.");@b@  }@b@@b@  public static void assertInputContainsValue(HtmlPage page, String name, String value)@b@  {@b@    String xpath = "//input[@name='" + name + "']";@b@    List list = page.getByXPath(xpath);@b@    if (list.isEmpty())@b@      throw new AssertionError("Unable to find an input element named '" + name + "'.");@b@@b@    HtmlInput input = (HtmlInput)list.get(0);@b@    String s = input.getValueAttribute();@b@    if (!(s.equals(value)))@b@      throw new AssertionError("The input element named '" + name + "' contains the value '" + s + "', not the expected value '" + value + "'.");@b@  }@b@@b@  public static void assertInputDoesNotContainValue(HtmlPage page, String name, String value)@b@  {@b@    String xpath = "//input[@name='" + name + "']";@b@    List list = page.getByXPath(xpath);@b@    if (list.isEmpty())@b@      throw new AssertionError("Unable to find an input element named '" + name + "'.");@b@@b@    HtmlInput input = (HtmlInput)list.get(0);@b@    String s = input.getValueAttribute();@b@    if (s.equals(value))@b@      throw new AssertionError("The input element named '" + name + "' contains the value '" + s + "', not the expected value '" + value + "'.");@b@  }@b@@b@  public static void assertAllTabIndexAttributesSet(HtmlPage page)@b@  {@b@    List tags = Arrays.asList(new String[] { "a", "area", "button", "input", "object", "select", "textarea" });@b@@b@    for (HtmlElement element : page.getDocumentElement().getHtmlElementsByTagNames(tags)) {@b@      Short tabIndex = element.getTabIndex();@b@      if ((tabIndex == null) || (tabIndex == HtmlElement.TAB_INDEX_OUT_OF_BOUNDS)) {@b@        String s = element.getAttribute("tabindex");@b@        throw new AssertionError("Illegal value for tab index: '" + s + "'.");@b@      }@b@    }@b@  }@b@@b@  public static void assertAllAccessKeyAttributesUnique(HtmlPage page)@b@  {@b@    List list = new ArrayList();@b@    for (HtmlElement element : page.getHtmlElementDescendants()) {@b@      String key = element.getAttribute("accesskey");@b@      if ((key != null) && (key.length() != 0)) {@b@        if (list.contains(key))@b@          throw new AssertionError("The access key '" + key + "' is not unique.");@b@@b@        list.add(key);@b@      }@b@    }@b@  }@b@@b@  public static void assertAllIdAttributesUnique(HtmlPage page)@b@  {@b@    List list = new ArrayList();@b@    for (HtmlElement element : page.getHtmlElementDescendants()) {@b@      String id = element.getAttribute("id");@b@      if ((id != null) && (id.length() != 0)) {@b@        if (list.contains(id))@b@          throw new AssertionError("The element ID '" + id + "' is not unique.");@b@@b@        list.add(id);@b@      }@b@    }@b@  }@b@@b@  public static void notNull(String description, Object object)@b@  {@b@    if (object == null)@b@      throw new NullPointerException(description);@b@  }@b@}