3

我正在 GWT 模块上编写 GWTTestCase,其中包括一个外部 Javascript 文件,该文件在变量名称 (d3.js) 中包含非 ASCII 字符。

我得到这个错误:

SEVERE: error: message=[illegal character] sourceName=[http://d3js.org/d3.v3.js] line=[2098] lineSource=[    var λ00, Ï00, λ0, cosÏ0, sinÏ0;] lineOffset=[10]

这是第 2098 行的代码行:

var λ00, φ00, λ0, cosφ0, sinφ0;

根据 HtmlUnit,这些字符(λ 和 φ)是有效的 Javascript 标识符字符(参见源代码),浏览器解析它没有问题。不幸的是,HtmlUnit 似乎使用 ISO-8859-1 编码读取文件(正如您在错误消息中看到的那样),而它是 UTF-8 编码的。

如何强制 HtmlUnit 使用 UTF-8 编码来解析 Javascript 文件?

我尝试在 Eclipse 和 Maven 配置中添加选项 -Dfile.encoding=UTF8 ,但没有帮助。有没有办法通过覆盖 GWTTestCase 中的某些方法来配置 HtmlUnit ?

谢谢你的帮助。

4

2 回答 2

2

尝试通过 addRequestHeader(String, String)方法设置Accept-CharsetWebClient 的 HTTP 请求。utf-8

于 2013-05-22T14:59:37.087 回答
1

RunStyleHtmlUnit我终于找到了一种通过扩展和覆盖一些方法和内部类来配置 HtmlUnit 的解决方法。

这真的很令人兴奋,但它确实有效......

package com.google.gwt.junit;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import org.w3c.css.sac.CSSParseException;
import org.w3c.css.sac.ErrorHandler;

import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.ScriptException;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.javascript.JavaScriptErrorListener;
import com.google.gwt.core.ext.TreeLogger;

public class RunStyleUtf8HtmlUnit extends RunStyleHtmlUnit {

  private boolean developmentMode;

  public RunStyleUtf8HtmlUnit(JUnitShell shell) {
    super(shell);
  }

  protected static class Utf8HtmlUnitThread extends HtmlUnitThread {
    private final BrowserVersion browser;
    private final TreeLogger treeLogger;
    private final String url;

    public Utf8HtmlUnitThread(BrowserVersion browser, String url,
        TreeLogger treeLogger, boolean developmentMode) {
      super(browser, url, treeLogger, developmentMode);

      this.browser = browser;
      this.treeLogger = treeLogger;
      this.url = url;
    }

    @Override
    public void run() {
      WebClient webClient = new WebClient(browser);
      webClient.setAlertHandler(this);
      // Adding a handler that ignores errors to work-around
      // https://sourceforge.net/tracker/?func=detail&aid=3090806&group_id=47038&atid=448266
      webClient.setCssErrorHandler(new ErrorHandler() {

        public void error(CSSParseException exception) {
          // ignore
        }

        public void fatalError(CSSParseException exception) {
          treeLogger.log(TreeLogger.WARN,
              "CSS fatal error: " + exception.getURI() + " ["
                  + exception.getLineNumber() + ":"
                  + exception.getColumnNumber() + "] "
                  + exception.getMessage());
        }

        public void warning(CSSParseException exception) {
          // ignore
        }
      });
      webClient.setIncorrectnessListener(this);
      webClient.setThrowExceptionOnFailingStatusCode(false);
      webClient.setThrowExceptionOnScriptError(true);
      webClient.setOnbeforeunloadHandler(this);
      webClient.setJavaScriptErrorListener(new JavaScriptErrorListener() {

        @Override
        public void loadScriptError(HtmlPage htmlPage, URL scriptUrl,
            Exception exception) {
          treeLogger.log(TreeLogger.ERROR, "Load Script Error: "
              + exception, exception);
        }

        @Override
        public void malformedScriptURL(HtmlPage htmlPage, String url,
            MalformedURLException malformedURLException) {
          treeLogger.log(TreeLogger.ERROR, "Malformed Script URL: "
              + malformedURLException.getLocalizedMessage());
        }

        @Override
        public void scriptException(HtmlPage htmlPage,
            ScriptException scriptException) {
          treeLogger.log(TreeLogger.DEBUG, "Script Exception: "
              + scriptException.getLocalizedMessage() + ", line "
              + scriptException.getFailingLine());
        }

        @Override
        public void timeoutError(HtmlPage htmlPage, long allowedTime,
            long executionTime) {
          treeLogger.log(TreeLogger.ERROR, "Script Timeout Error "
              + executionTime + " > " + allowedTime);
        }
      });
      setupWebClient(webClient);
      try {
        WebRequest webRequest = new WebRequest(new URL(url));
        webRequest.setCharset("utf-8");
        Page page = webClient.getPage(webRequest);
        webClient.waitForBackgroundJavaScriptStartingBefore(2000);
        if (treeLogger.isLoggable(TreeLogger.SPAM)) {
          treeLogger.log(TreeLogger.SPAM, "getPage returned "
              + ((HtmlPage) page).asXml());
        }
        // TODO(amitmanjhi): call webClient.closeAllWindows()
      } catch (FailingHttpStatusCodeException e) {
        treeLogger.log(TreeLogger.ERROR, "HTTP request failed", e);
        return;
      } catch (MalformedURLException e) {
        treeLogger.log(TreeLogger.ERROR, "Bad URL", e);
        return;
      } catch (IOException e) {
        treeLogger.log(TreeLogger.ERROR, "I/O error on HTTP request", e);
        return;
      }
    }
  }

  @Override
  public boolean setupMode(TreeLogger logger, boolean developmentMode) {
    this.developmentMode = developmentMode;
    return true;
  }

  @Override
  protected HtmlUnitThread createHtmlUnitThread(BrowserVersion browser,
      String url) {
    return new Utf8HtmlUnitThread(browser, url, shell.getTopLogger()
        .branch(TreeLogger.SPAM, "logging for HtmlUnit thread"),
        developmentMode);
  }
}

它主要是一堆原始代码的复制/粘贴。重要的东西在这里(第 103 到 105 行):

WebRequest webRequest = new WebRequest(new URL(url));
webRequest.setCharset("utf-8");
Page page = webClient.getPage(webRequest);

这种运行方式必须通过配置 gwt 参数来激活。就我而言,我在命令行上添加了这个:

-Dgwt.args="-runStyle Utf8HtmlUnit"

恕我直言,GWT 应该提供一种配置WebClient和 的方法WebRequest,或者至少支持xml 模块文件charset中标记的属性。script

我就此向 GWT 团队提交了一个错误:问题 8171

于 2013-05-28T20:54:33.483 回答