Update GWT to 2.7
As pointed out in this thread on GWT-discuss development group [1], gwt-dev is going to be unbundled in 2.7 release. That means that we would have to supply its dependencies explicitly. To start with we need to pass in ASM library. It's unclear though, if we need asm-commons and asm-xml as it compiles without it, but corresponding parent-pom contains it [2]. GWT unit tests were disabled as gwt-test-utils doesn't seem to work yet against upcoming GWT 2.7 release. Issue was filed upstream [3]. As was pointed out in this thread [4], codeserver is now shipped in gwt-dev.jar as well. Stop fetching codeserver.jar in addition and use the bits from gwt-dev.jar. [1] https://groups.google.com/d/topic/google-web-toolkit/LwXXQCG_I_k/discussion [2] http://repo1.maven.org/maven2/org/ow2/asm/asm-parent/5.0.3/asm-parent-5.0.3.pom [3] https://github.com/gwt-test-utils/gwt-test-utils/issues/68 [4] https://groups.google.com/d/topic/google-web-toolkit-contributors/pFYPE7Uoub8/discussion Bug: issue 3008 Bug: issue 3027 Change-Id: Ib8f9ed0c767e9f41f104253fdc8b74a8cbbe38ab
This commit is contained in:

committed by
David Pursehouse

parent
5f5c792ec3
commit
11c56681b0
@@ -12,7 +12,6 @@
|
|||||||
release = //:release
|
release = //:release
|
||||||
safari = //:safari
|
safari = //:safari
|
||||||
withdocs = //:withdocs
|
withdocs = //:withdocs
|
||||||
codeserver = //lib/gwt:codeserver
|
|
||||||
|
|
||||||
[buildfile]
|
[buildfile]
|
||||||
includes = //tools/default.defs
|
includes = //tools/default.defs
|
||||||
|
@@ -52,22 +52,6 @@ Duplicate the existing launch configuration:
|
|||||||
The gerrit_gwt_debug launch configuration uses GWT's
|
The gerrit_gwt_debug launch configuration uses GWT's
|
||||||
link:http://www.gwtproject.org/articles/superdevmode.html[Super Dev Mode].
|
link:http://www.gwtproject.org/articles/superdevmode.html[Super Dev Mode].
|
||||||
|
|
||||||
Due to a problem where the codeserver does not correctly identify the connected
|
|
||||||
user agent (already fixed upstream but not yet released), the used user agent
|
|
||||||
must be explicitly set in `GerritGwtUI.gwt.xml` for SDM to work:
|
|
||||||
|
|
||||||
[source,xml]
|
|
||||||
----
|
|
||||||
<set-property name="user.agent" value="gecko1_8" />
|
|
||||||
----
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
[source,xml]
|
|
||||||
----
|
|
||||||
<set-property name="user.agent" value="safari" />
|
|
||||||
----
|
|
||||||
|
|
||||||
* Select in Eclipse Run -> Debug Configurations `gerrit_gwt_debug.launch`
|
* Select in Eclipse Run -> Debug Configurations `gerrit_gwt_debug.launch`
|
||||||
* Only once: add bookmarks for `Dev Mode On/Off` from codeserver URL:
|
* Only once: add bookmarks for `Dev Mode On/Off` from codeserver URL:
|
||||||
`http://localhost:9876/` to your bookmark bar
|
`http://localhost:9876/` to your bookmark bar
|
||||||
|
@@ -6,7 +6,6 @@ java_library(
|
|||||||
'//gerrit-pgm:util',
|
'//gerrit-pgm:util',
|
||||||
'//gerrit-util-cli:cli',
|
'//gerrit-util-cli:cli',
|
||||||
'//lib/gwt:dev',
|
'//lib/gwt:dev',
|
||||||
'//lib/gwt:codeserver',
|
|
||||||
'//lib/jetty:server',
|
'//lib/jetty:server',
|
||||||
'//lib/jetty:servlet',
|
'//lib/jetty:servlet',
|
||||||
'//lib/jetty:servlets',
|
'//lib/jetty:servlets',
|
||||||
|
@@ -17,12 +17,15 @@
|
|||||||
package com.google.gwt.dev.codeserver;
|
package com.google.gwt.dev.codeserver;
|
||||||
|
|
||||||
import com.google.gwt.core.ext.TreeLogger;
|
import com.google.gwt.core.ext.TreeLogger;
|
||||||
|
import com.google.gwt.core.ext.TreeLogger.Type;
|
||||||
import com.google.gwt.core.ext.UnableToCompleteException;
|
import com.google.gwt.core.ext.UnableToCompleteException;
|
||||||
import com.google.gwt.dev.json.JsonArray;
|
import com.google.gwt.dev.codeserver.CompileDir.PolicyFile;
|
||||||
|
import com.google.gwt.dev.codeserver.Pages.ErrorPage;
|
||||||
import com.google.gwt.dev.json.JsonObject;
|
import com.google.gwt.dev.json.JsonObject;
|
||||||
|
|
||||||
import org.eclipse.jetty.http.MimeTypes;
|
import org.eclipse.jetty.http.MimeTypes;
|
||||||
import org.eclipse.jetty.server.HttpConnection;
|
import org.eclipse.jetty.server.HttpConnection;
|
||||||
|
|
||||||
import org.eclipse.jetty.server.Request;
|
import org.eclipse.jetty.server.Request;
|
||||||
import org.eclipse.jetty.server.Server;
|
import org.eclipse.jetty.server.Server;
|
||||||
import org.eclipse.jetty.server.ServerConnector;
|
import org.eclipse.jetty.server.ServerConnector;
|
||||||
@@ -35,9 +38,10 @@ import java.io.File;
|
|||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.PrintWriter;
|
import java.util.Date;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@@ -82,31 +86,38 @@ public class WebServer {
|
|||||||
static final Pattern SAFE_FILE_PATH =
|
static final Pattern SAFE_FILE_PATH =
|
||||||
Pattern.compile("/(" + SAFE_DIRECTORY + "/)+" + SAFE_FILENAME + "$");
|
Pattern.compile("/(" + SAFE_DIRECTORY + "/)+" + SAFE_FILENAME + "$");
|
||||||
|
|
||||||
private static final Pattern SAFE_CALLBACK =
|
static final Pattern STRONG_NAME = Pattern.compile("[\\dA-F]{32}");
|
||||||
Pattern.compile("([a-zA-Z_][a-zA-Z0-9_]*\\.)*[a-zA-Z_][a-zA-Z0-9_]*");
|
|
||||||
|
private static final Pattern CACHE_JS_FILE = Pattern.compile("/(" + STRONG_NAME + ").cache.js$");
|
||||||
|
|
||||||
private static final MimeTypes MIME_TYPES = new MimeTypes();
|
private static final MimeTypes MIME_TYPES = new MimeTypes();
|
||||||
|
|
||||||
private final SourceHandler handler;
|
private static final String TIME_IN_THE_PAST = "Fri, 01 Jan 1990 00:00:00 GMT";
|
||||||
|
|
||||||
private final Modules modules;
|
private final SourceHandler handler;
|
||||||
|
private final JsonExporter jsonExporter;
|
||||||
|
private final OutboxTable outboxes;
|
||||||
|
private final JobRunner runner;
|
||||||
|
private final JobEventTable eventTable;
|
||||||
|
|
||||||
private final String bindAddress;
|
private final String bindAddress;
|
||||||
private final int port;
|
private final int port;
|
||||||
private final TreeLogger logger;
|
|
||||||
private Server server;
|
private Server server;
|
||||||
|
|
||||||
WebServer(SourceHandler handler, Modules modules, String bindAddress, int port,
|
WebServer(SourceHandler handler, JsonExporter jsonExporter, OutboxTable outboxes,
|
||||||
TreeLogger logger) {
|
JobRunner runner, JobEventTable eventTable, String bindAddress, int port) {
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
this.modules = modules;
|
this.jsonExporter = jsonExporter;
|
||||||
|
this.outboxes = outboxes;
|
||||||
|
this.runner = runner;
|
||||||
|
this.eventTable = eventTable;
|
||||||
this.bindAddress = bindAddress;
|
this.bindAddress = bindAddress;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
this.logger = logger;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public void start() throws UnableToCompleteException {
|
void start(final TreeLogger logger) throws UnableToCompleteException {
|
||||||
|
|
||||||
Server newServer = new Server();
|
Server newServer = new Server();
|
||||||
ServerConnector connector = new ServerConnector(newServer);
|
ServerConnector connector = new ServerConnector(newServer);
|
||||||
@@ -114,19 +125,20 @@ public class WebServer {
|
|||||||
connector.setPort(port);
|
connector.setPort(port);
|
||||||
connector.setReuseAddress(false);
|
connector.setReuseAddress(false);
|
||||||
connector.setSoLingerTime(0);
|
connector.setSoLingerTime(0);
|
||||||
|
|
||||||
newServer.addConnector(connector);
|
newServer.addConnector(connector);
|
||||||
|
|
||||||
ServletContextHandler handler = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
ServletContextHandler newHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||||
handler.setContextPath("/");
|
newHandler.setContextPath("/");
|
||||||
handler.addServlet(new ServletHolder(new HttpServlet() {
|
newHandler.addServlet(new ServletHolder(new HttpServlet() {
|
||||||
@Override
|
@Override
|
||||||
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||||
throws ServletException, IOException {
|
throws ServletException, IOException {
|
||||||
handleRequest(request.getPathInfo(), request, response);
|
handleRequest(request.getPathInfo(), request, response, logger);
|
||||||
}
|
}
|
||||||
}), "/*");
|
}), "/*");
|
||||||
handler.addFilter(GzipFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
|
newHandler.addFilter(GzipFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
|
||||||
newServer.setHandler(handler);
|
newServer.setHandler(newHandler);
|
||||||
try {
|
try {
|
||||||
newServer.start();
|
newServer.start();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -147,55 +159,63 @@ public class WebServer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the location of the compiler output. (Changes after every recompile.)
|
* Returns the location of the compiler output. (Changes after every recompile.)
|
||||||
|
* @param outputModuleName the module name that the GWT compiler used in its output.
|
||||||
*/
|
*/
|
||||||
public File getCurrentWarDir(String moduleName) {
|
public File getCurrentWarDir(String outputModuleName) {
|
||||||
return modules.get(moduleName).getWarDir();
|
return outboxes.findByOutputModuleName(outputModuleName).getWarDir();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleRequest(String target, HttpServletRequest request,
|
private void handleRequest(String target, HttpServletRequest request,
|
||||||
HttpServletResponse response)
|
HttpServletResponse response, TreeLogger parentLogger)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
if (request.getMethod().equalsIgnoreCase("get")) {
|
if (request.getMethod().equalsIgnoreCase("get")) {
|
||||||
doGet(target, request, response);
|
|
||||||
|
TreeLogger logger = parentLogger.branch(Type.TRACE, "GET " + target);
|
||||||
|
|
||||||
|
Response page = doGet(target, request, logger);
|
||||||
|
if (page == null) {
|
||||||
|
logger.log(Type.WARN, "not handled: " + target);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setHandled(request);
|
||||||
|
if (!target.endsWith(".cache.js")) {
|
||||||
|
// Make sure IE9 doesn't cache any pages.
|
||||||
|
// (Nearly all pages may change on server restart.)
|
||||||
|
response.setHeader("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate");
|
||||||
|
response.setHeader("Pragma", "no-cache");
|
||||||
|
response.setHeader("Expires", TIME_IN_THE_PAST);
|
||||||
|
response.setDateHeader("Date", new Date().getTime());
|
||||||
|
}
|
||||||
|
page.send(request, response, logger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doGet(String target, HttpServletRequest request, HttpServletResponse response)
|
/**
|
||||||
|
* Returns the page that should be sent in response to a GET request, or null for no response.
|
||||||
|
*/
|
||||||
|
private Response doGet(String target, HttpServletRequest request, TreeLogger logger)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
if (!target.endsWith(".cache.js")) {
|
|
||||||
// Make sure IE9 doesn't cache any pages.
|
|
||||||
// (Nearly all pages may change on server restart.)
|
|
||||||
PageUtil.setNoCacheHeaders(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target.equals("/")) {
|
if (target.equals("/")) {
|
||||||
setHandled(request);
|
JsonObject json = jsonExporter.exportFrontPageVars();
|
||||||
JsonObject config = makeConfig();
|
return Pages.newHtmlPage("config", json, "frontpage.html");
|
||||||
PageUtil.sendJsonAndHtml("config", config, "frontpage.html", response, logger);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target.equals("/dev_mode_on.js")) {
|
if (target.equals("/dev_mode_on.js")) {
|
||||||
setHandled(request);
|
JsonObject json = jsonExporter.exportDevModeOnVars();
|
||||||
JsonObject config = makeConfig();
|
return Responses.newJavascriptResponse("__gwt_codeserver_config", json,
|
||||||
PageUtil
|
"dev_mode_on.js");
|
||||||
.sendJsonAndJavaScript("__gwt_codeserver_config", config, "dev_mode_on.js", response,
|
|
||||||
logger);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recompile on request from the bookmarklet.
|
// Recompile on request from the bookmarklet.
|
||||||
// This is a GET because a bookmarklet can call it from a different origin (JSONP).
|
// This is a GET because a bookmarklet can call it from a different origin (JSONP).
|
||||||
if (target.startsWith("/recompile/")) {
|
if (target.startsWith("/recompile/")) {
|
||||||
setHandled(request);
|
|
||||||
String moduleName = target.substring("/recompile/".length());
|
String moduleName = target.substring("/recompile/".length());
|
||||||
ModuleState moduleState = modules.get(moduleName);
|
Outbox box = outboxes.findByOutputModuleName(moduleName);
|
||||||
if (moduleState == null) {
|
if (box == null) {
|
||||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
return new ErrorPage("No such module: " + moduleName);
|
||||||
logger.log(TreeLogger.WARN, "not found: " + target);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We are passing properties from an unauthenticated GET request directly to the compiler.
|
// We are passing properties from an unauthenticated GET request directly to the compiler.
|
||||||
@@ -204,251 +224,264 @@ public class WebServer {
|
|||||||
// cause a spurious recompile, resulting in an unexpected permutation being loaded later.
|
// cause a spurious recompile, resulting in an unexpected permutation being loaded later.
|
||||||
//
|
//
|
||||||
// It would be unsafe to allow a configuration property to be changed.
|
// It would be unsafe to allow a configuration property to be changed.
|
||||||
boolean ok = moduleState.recompile(getBindingProperties(request));
|
Job job = box.makeJob(getBindingProperties(request), logger);
|
||||||
|
runner.submit(job);
|
||||||
JsonObject config = makeConfig();
|
Job.Result result = job.waitForResult();
|
||||||
config.put("status", ok ? "ok" : "failed");
|
JsonObject json = jsonExporter.exportRecompileResponse(result);
|
||||||
sendJsonpPage(config, request, response);
|
return Responses.newJsonResponse(json);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target.startsWith("/log/")) {
|
if (target.startsWith("/log/")) {
|
||||||
setHandled(request);
|
|
||||||
String moduleName = target.substring("/log/".length());
|
String moduleName = target.substring("/log/".length());
|
||||||
File file = modules.get(moduleName).getCompileLog();
|
Outbox box = outboxes.findByOutputModuleName(moduleName);
|
||||||
sendLogPage(moduleName, file, response);
|
if (box == null) {
|
||||||
return;
|
return new ErrorPage("No such module: " + moduleName);
|
||||||
|
} else if (box.containsStubCompile()) {
|
||||||
|
return new ErrorPage("This module hasn't been compiled yet.");
|
||||||
|
} else {
|
||||||
|
return makeLogPage(box);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target.equals("/favicon.ico")) {
|
if (target.equals("/favicon.ico")) {
|
||||||
InputStream faviconStream = getClass().getResourceAsStream("favicon.ico");
|
InputStream faviconStream = getClass().getResourceAsStream("favicon.ico");
|
||||||
if (faviconStream != null) {
|
if (faviconStream == null) {
|
||||||
setHandled(request);
|
return new ErrorPage("icon not found");
|
||||||
// IE8 will not load the favicon in an img tag with the default MIME type,
|
|
||||||
// so use "image/x-icon" instead.
|
|
||||||
PageUtil.sendStream("image/x-icon", faviconStream, response);
|
|
||||||
}
|
}
|
||||||
return;
|
// IE8 will not load the favicon in an img tag with the default MIME type,
|
||||||
|
// so use "image/x-icon" instead.
|
||||||
|
return Responses.newBinaryStreamResponse("image/x-icon", faviconStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target.equals("/policies/")) {
|
if (target.equals("/policies/")) {
|
||||||
setHandled(request);
|
return makePolicyIndexPage();
|
||||||
sendPolicyIndex(response);
|
}
|
||||||
return;
|
|
||||||
|
if (target.equals("/progress")) {
|
||||||
|
// TODO: return a list of progress objects here, one for each job.
|
||||||
|
JobEvent event = eventTable.getCompilingJobEvent();
|
||||||
|
|
||||||
|
JsonObject json;
|
||||||
|
if (event == null) {
|
||||||
|
json = new JsonObject();
|
||||||
|
json.put("status", "idle");
|
||||||
|
} else {
|
||||||
|
json = jsonExporter.exportProgressResponse(event);
|
||||||
|
}
|
||||||
|
return Responses.newJsonResponse(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
Matcher matcher = SAFE_MODULE_PATH.matcher(target);
|
Matcher matcher = SAFE_MODULE_PATH.matcher(target);
|
||||||
if (matcher.matches()) {
|
if (matcher.matches()) {
|
||||||
setHandled(request);
|
return makeModulePage(matcher.group(1));
|
||||||
sendModulePage(matcher.group(1), response);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
matcher = SAFE_DIRECTORY_PATH.matcher(target);
|
matcher = SAFE_DIRECTORY_PATH.matcher(target);
|
||||||
if (matcher.matches() && handler.isSourceMapRequest(target)) {
|
if (matcher.matches() && SourceHandler.isSourceMapRequest(target)) {
|
||||||
setHandled(request);
|
return handler.handle(target, request, logger);
|
||||||
handler.handle(target, request, response);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
matcher = SAFE_FILE_PATH.matcher(target);
|
matcher = SAFE_FILE_PATH.matcher(target);
|
||||||
if (matcher.matches()) {
|
if (matcher.matches()) {
|
||||||
setHandled(request);
|
if (SourceHandler.isSourceMapRequest(target)) {
|
||||||
if (handler.isSourceMapRequest(target)) {
|
return handler.handle(target, request, logger);
|
||||||
handler.handle(target, request, response);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (target.startsWith("/policies/")) {
|
if (target.startsWith("/policies/")) {
|
||||||
sendPolicyFile(target, response);
|
return makePolicyFilePage(target);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
sendOutputFile(target, request, response);
|
return makeCompilerOutputPage(target);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.log(TreeLogger.WARN, "ignored get request: " + target);
|
logger.log(TreeLogger.WARN, "ignored get request: " + target);
|
||||||
|
return null; // not handled
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendOutputFile(String target, HttpServletRequest request,
|
/**
|
||||||
HttpServletResponse response) throws IOException {
|
* Returns a file that the compiler wrote to its war directory.
|
||||||
|
*/
|
||||||
|
private Response makeCompilerOutputPage(String target) {
|
||||||
|
|
||||||
int secondSlash = target.indexOf('/', 1);
|
int secondSlash = target.indexOf('/', 1);
|
||||||
String moduleName = target.substring(1, secondSlash);
|
String moduleName = target.substring(1, secondSlash);
|
||||||
ModuleState moduleState = modules.get(moduleName);
|
Outbox box = outboxes.findByOutputModuleName(moduleName);
|
||||||
|
if (box == null) {
|
||||||
|
return new ErrorPage("No such module: " + moduleName);
|
||||||
|
}
|
||||||
|
|
||||||
File file = moduleState.getOutputFile(target);
|
final String contentEncoding;
|
||||||
|
File file = box.getOutputFile(target);
|
||||||
if (!file.isFile()) {
|
if (!file.isFile()) {
|
||||||
// perhaps it's compressed
|
// perhaps it's compressed
|
||||||
file = moduleState.getOutputFile(target + ".gz");
|
file = box.getOutputFile(target + ".gz");
|
||||||
if (!file.isFile()) {
|
if (!file.isFile()) {
|
||||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
return new ErrorPage("not found: " + file.toString());
|
||||||
logger.log(TreeLogger.WARN, "not found: " + file.toString());
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (!request.getHeader("Accept-Encoding").contains("gzip")) {
|
contentEncoding = "gzip";
|
||||||
response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
|
} else {
|
||||||
logger.log(TreeLogger.WARN, "client doesn't accept gzip; bailing");
|
contentEncoding = null;
|
||||||
return;
|
|
||||||
}
|
|
||||||
response.setHeader("Content-Encoding", "gzip");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target.endsWith(".cache.js")) {
|
final String sourceMapUrl;
|
||||||
response.setHeader("X-SourceMap", sourceMapLocationForModule(moduleName));
|
Matcher match = CACHE_JS_FILE.matcher(target);
|
||||||
|
if (match.matches()) {
|
||||||
|
String strongName = match.group(1);
|
||||||
|
String template = SourceHandler.sourceMapLocationTemplate(moduleName);
|
||||||
|
sourceMapUrl = template.replace("__HASH__", strongName);
|
||||||
|
} else {
|
||||||
|
sourceMapUrl = null;
|
||||||
}
|
}
|
||||||
response.setHeader("Access-Control-Allow-Origin", "*");
|
|
||||||
String mimeType = guessMimeType(target);
|
String mimeType = guessMimeType(target);
|
||||||
PageUtil.sendFile(mimeType, file, response);
|
final Response barePage = Responses.newFileResponse(mimeType, file);
|
||||||
}
|
|
||||||
|
|
||||||
private void sendModulePage(String moduleName, HttpServletResponse response) throws IOException {
|
// Wrap the response to send the extra headers.
|
||||||
ModuleState module = modules.get(moduleName);
|
return new Response() {
|
||||||
if (module == null) {
|
@Override
|
||||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
public void send(HttpServletRequest request, HttpServletResponse response, TreeLogger logger)
|
||||||
logger.log(TreeLogger.WARN, "module not found: " + moduleName);
|
throws IOException {
|
||||||
return;
|
// TODO: why do we need this? Looks like Ray added it a long time ago.
|
||||||
}
|
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||||
PageUtil
|
|
||||||
.sendJsonAndHtml("config", module.getTemplateVariables(), "modulepage.html", response,
|
|
||||||
logger);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendPolicyIndex(HttpServletResponse response) throws IOException {
|
if (sourceMapUrl != null) {
|
||||||
|
response.setHeader("X-SourceMap", sourceMapUrl);
|
||||||
response.setContentType("text/html");
|
response.setHeader("SourceMap", sourceMapUrl);
|
||||||
|
|
||||||
HtmlWriter out = new HtmlWriter(response.getWriter());
|
|
||||||
|
|
||||||
out.startTag("html").nl();
|
|
||||||
out.startTag("head").nl();
|
|
||||||
out.startTag("title").text("Policy Files").endTag("title").nl();
|
|
||||||
out.endTag("head");
|
|
||||||
out.startTag("body");
|
|
||||||
|
|
||||||
out.startTag("h1").text("Policy Files").endTag("h1").nl();
|
|
||||||
|
|
||||||
for (String moduleName : modules) {
|
|
||||||
ModuleState module = modules.get(moduleName);
|
|
||||||
File manifest = module.getExtraFile("rpcPolicyManifest/manifest.txt");
|
|
||||||
if (manifest.isFile()) {
|
|
||||||
out.startTag("h2").text(moduleName).endTag("h2").nl();
|
|
||||||
|
|
||||||
out.startTag("table").nl();
|
|
||||||
String text = PageUtil.loadFile(manifest);
|
|
||||||
for (String line : text.split("\n")) {
|
|
||||||
line = line.trim();
|
|
||||||
if (line.isEmpty() || line.startsWith("#")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String[] fields = line.split(", ");
|
|
||||||
if (fields.length < 2) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
String serviceName = fields[0];
|
|
||||||
String policyFileName = fields[1];
|
|
||||||
|
|
||||||
String serviceUrl = SourceHandler.SOURCEMAP_PATH + moduleName + "/" +
|
|
||||||
serviceName.replace('.', '/') + ".java";
|
|
||||||
String policyUrl = "/policies/" + policyFileName;
|
|
||||||
|
|
||||||
out.startTag("tr");
|
|
||||||
|
|
||||||
out.startTag("td");
|
|
||||||
out.startTag("a", "href=", serviceUrl).text(serviceName).endTag("a");
|
|
||||||
out.endTag("td");
|
|
||||||
|
|
||||||
out.startTag("td");
|
|
||||||
out.startTag("a", "href=", policyUrl).text(policyFileName).endTag("a");
|
|
||||||
out.endTag("td");
|
|
||||||
|
|
||||||
out.endTag("tr").nl();
|
|
||||||
}
|
}
|
||||||
out.endTag("table").nl();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out.endTag("body").nl();
|
if (contentEncoding != null) {
|
||||||
out.endTag("html").nl();
|
if (!request.getHeader("Accept-Encoding").contains("gzip")) {
|
||||||
|
response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
|
||||||
|
logger.log(TreeLogger.WARN, "client doesn't accept gzip; bailing");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
response.setHeader("Content-Encoding", "gzip");
|
||||||
|
}
|
||||||
|
|
||||||
|
barePage.send(request, response, logger);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendPolicyFile(String target, HttpServletResponse response) throws IOException {
|
private Response makeModulePage(String moduleName) {
|
||||||
|
Outbox box = outboxes.findByOutputModuleName(moduleName);
|
||||||
|
if (box == null) {
|
||||||
|
return new ErrorPage("No such module: " + moduleName);
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject json = jsonExporter.exportModulePageVars(box);
|
||||||
|
return Pages.newHtmlPage("config", json, "modulepage.html");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response makePolicyIndexPage() {
|
||||||
|
|
||||||
|
return new Response() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void send(HttpServletRequest request, HttpServletResponse response, TreeLogger logger)
|
||||||
|
throws IOException {
|
||||||
|
response.setContentType("text/html");
|
||||||
|
|
||||||
|
HtmlWriter out = new HtmlWriter(response.getWriter());
|
||||||
|
|
||||||
|
out.startTag("html").nl();
|
||||||
|
out.startTag("head").nl();
|
||||||
|
out.startTag("title").text("Policy Files").endTag("title").nl();
|
||||||
|
out.endTag("head");
|
||||||
|
out.startTag("body");
|
||||||
|
|
||||||
|
out.startTag("h1").text("Policy Files").endTag("h1").nl();
|
||||||
|
|
||||||
|
for (Outbox box : outboxes.getOutboxes()) {
|
||||||
|
List<PolicyFile> policies = box.readRpcPolicyManifest();
|
||||||
|
if (!policies.isEmpty()) {
|
||||||
|
out.startTag("h2").text(box.getOutputModuleName()).endTag("h2").nl();
|
||||||
|
|
||||||
|
out.startTag("table").nl();
|
||||||
|
for (PolicyFile policy : policies) {
|
||||||
|
|
||||||
|
out.startTag("tr");
|
||||||
|
|
||||||
|
out.startTag("td");
|
||||||
|
|
||||||
|
out.startTag("a", "href=", policy.getServiceSourceUrl());
|
||||||
|
out.text(policy.getServiceName());
|
||||||
|
out.endTag("a");
|
||||||
|
|
||||||
|
out.endTag("td");
|
||||||
|
|
||||||
|
out.startTag("td");
|
||||||
|
|
||||||
|
out.startTag("a", "href=", policy.getUrl());
|
||||||
|
out.text(policy.getName());
|
||||||
|
out.endTag("a");
|
||||||
|
|
||||||
|
out.endTag("td");
|
||||||
|
|
||||||
|
out.endTag("tr").nl();
|
||||||
|
}
|
||||||
|
out.endTag("table").nl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out.endTag("body").nl();
|
||||||
|
out.endTag("html").nl();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response makePolicyFilePage(String target) {
|
||||||
|
|
||||||
int secondSlash = target.indexOf('/', 1);
|
int secondSlash = target.indexOf('/', 1);
|
||||||
if (secondSlash < 1) {
|
if (secondSlash < 1) {
|
||||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
return new ErrorPage("invalid URL for policy file: " + target);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String rest = target.substring(secondSlash + 1);
|
String rest = target.substring(secondSlash + 1);
|
||||||
if (rest.contains("/") || !rest.endsWith(".gwt.rpc")) {
|
if (rest.contains("/") || !rest.endsWith(".gwt.rpc")) {
|
||||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
return new ErrorPage("invalid name for policy file: " + rest);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (String moduleName : modules) {
|
File fileToSend = outboxes.findPolicyFile(rest);
|
||||||
ModuleState module = modules.get(moduleName);
|
if (fileToSend == null) {
|
||||||
File policy = module.getOutputFile(moduleName + "/" + rest);
|
return new ErrorPage("Policy file not found: " + rest);
|
||||||
if (policy.isFile()) {
|
|
||||||
PageUtil.sendFile("text/plain", policy, response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.log(TreeLogger.Type.WARN, "policy file not found: " + rest);
|
return Responses.newFileResponse("text/plain", fileToSend);
|
||||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
private JsonObject makeConfig() {
|
|
||||||
JsonArray moduleNames = new JsonArray();
|
|
||||||
for (String module : modules) {
|
|
||||||
moduleNames.add(module);
|
|
||||||
}
|
|
||||||
JsonObject config = JsonObject.create();
|
|
||||||
config.put("moduleNames", moduleNames);
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendJsonpPage(JsonObject json, HttpServletRequest request,
|
|
||||||
HttpServletResponse response) throws IOException {
|
|
||||||
|
|
||||||
response.setStatus(HttpServletResponse.SC_OK);
|
|
||||||
response.setContentType("application/javascript");
|
|
||||||
PrintWriter out = response.getWriter();
|
|
||||||
|
|
||||||
String callbackExpression = request.getParameter("_callback");
|
|
||||||
if (callbackExpression == null || !SAFE_CALLBACK.matcher(callbackExpression).matches()) {
|
|
||||||
logger.log(TreeLogger.ERROR, "invalid callback: " + callbackExpression);
|
|
||||||
out.print("/* invalid callback parameter */");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
out.print(callbackExpression + "(");
|
|
||||||
json.write(out);
|
|
||||||
out.println(");");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends the log file as html with errors highlighted in red.
|
* Sends the log file as html with errors highlighted in red.
|
||||||
*/
|
*/
|
||||||
private void sendLogPage(String moduleName, File file, HttpServletResponse response)
|
private Response makeLogPage(final Outbox box) {
|
||||||
throws IOException {
|
final File file = box.getCompileLog();
|
||||||
BufferedReader reader = new BufferedReader(new FileReader(file));
|
if (!file.isFile()) {
|
||||||
|
return new ErrorPage("log file not found");
|
||||||
|
}
|
||||||
|
|
||||||
response.setStatus(HttpServletResponse.SC_OK);
|
return new Response() {
|
||||||
response.setContentType("text/html");
|
|
||||||
response.setHeader("Content-Style-Type", "text/css");
|
|
||||||
|
|
||||||
HtmlWriter out = new HtmlWriter(response.getWriter());
|
@Override
|
||||||
out.startTag("html").nl();
|
public void send(HttpServletRequest request, HttpServletResponse response, TreeLogger logger)
|
||||||
out.startTag("head").nl();
|
throws IOException {
|
||||||
out.startTag("title").text(moduleName + " compile log").endTag("title").nl();
|
BufferedReader reader = new BufferedReader(new FileReader(file));
|
||||||
out.startTag("style").nl();
|
|
||||||
out.text(".error { color: red; font-weight: bold; }").nl();
|
response.setStatus(HttpServletResponse.SC_OK);
|
||||||
out.endTag("style").nl();
|
response.setContentType("text/html");
|
||||||
out.endTag("head").nl();
|
response.setHeader("Content-Style-Type", "text/css");
|
||||||
out.startTag("body").nl();
|
|
||||||
sendLogAsHtml(reader, out);
|
HtmlWriter out = new HtmlWriter(response.getWriter());
|
||||||
out.endTag("body").nl();
|
out.startTag("html").nl();
|
||||||
out.endTag("html").nl();
|
out.startTag("head").nl();
|
||||||
|
out.startTag("title").text(box.getOutputModuleName() + " compile log").endTag("title").nl();
|
||||||
|
out.startTag("style").nl();
|
||||||
|
out.text(".error { color: red; font-weight: bold; }").nl();
|
||||||
|
out.endTag("style").nl();
|
||||||
|
out.endTag("head").nl();
|
||||||
|
out.startTag("body").nl();
|
||||||
|
sendLogAsHtml(reader, out);
|
||||||
|
out.endTag("body").nl();
|
||||||
|
out.endTag("html").nl();
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Pattern ERROR_PATTERN = Pattern.compile("\\[ERROR\\]");
|
private static final Pattern ERROR_PATTERN = Pattern.compile("\\[ERROR\\]");
|
||||||
@@ -501,11 +534,6 @@ public class WebServer {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String sourceMapLocationForModule(String moduleName) {
|
|
||||||
return SourceHandler.SOURCEMAP_PATH + moduleName +
|
|
||||||
"/gwtSourceMap.json";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void setHandled(HttpServletRequest request) {
|
private static void setHandled(HttpServletRequest request) {
|
||||||
Request baseRequest = (request instanceof Request) ? (Request) request :
|
Request baseRequest = (request instanceof Request) ? (Request) request :
|
||||||
HttpConnection.getCurrentConnection().getHttpChannel().getRequest();
|
HttpConnection.getCurrentConnection().getHttpChannel().getRequest();
|
||||||
|
@@ -5,6 +5,10 @@ from multiprocessing import cpu_count
|
|||||||
DEPS = [
|
DEPS = [
|
||||||
'//gerrit-gwtexpui:CSS',
|
'//gerrit-gwtexpui:CSS',
|
||||||
'//lib:gwtjsonrpc',
|
'//lib:gwtjsonrpc',
|
||||||
|
'//lib/ow2:ow2-asm',
|
||||||
|
'//lib/ow2:ow2-asm-analysis',
|
||||||
|
'//lib/ow2:ow2-asm-util',
|
||||||
|
'//lib/ow2:ow2-asm-tree',
|
||||||
]
|
]
|
||||||
|
|
||||||
genrule(
|
genrule(
|
||||||
|
@@ -39,7 +39,6 @@
|
|||||||
<add-linker name='xsiframe'/>
|
<add-linker name='xsiframe'/>
|
||||||
|
|
||||||
<set-property name='gwt.logging.logLevel' value='SEVERE'/>
|
<set-property name='gwt.logging.logLevel' value='SEVERE'/>
|
||||||
<set-property name='gwt.logging.popupHandler' value='DISABLED'/>
|
|
||||||
|
|
||||||
<entry-point class='com.google.gerrit.client.Gerrit'/>
|
<entry-point class='com.google.gerrit.client.Gerrit'/>
|
||||||
</module>
|
</module>
|
||||||
|
@@ -25,10 +25,13 @@ import com.googlecode.gwt.test.GwtTest;
|
|||||||
import net.codemirror.lib.LineCharacter;
|
import net.codemirror.lib.LineCharacter;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
/** Unit tests for EditIterator */
|
/** Unit tests for EditIterator */
|
||||||
@GwtModule("com.google.gerrit.GerritGwtUI")
|
@GwtModule("com.google.gerrit.GerritGwtUI")
|
||||||
|
@Ignore
|
||||||
|
// TODO(davido): Enable this again when gwt-test-utils lib is fixed.
|
||||||
public class EditIteratorTest extends GwtTest {
|
public class EditIteratorTest extends GwtTest {
|
||||||
private JsArrayString lines;
|
private JsArrayString lines;
|
||||||
|
|
||||||
|
6
lib/BUCK
6
lib/BUCK
@@ -35,9 +35,9 @@ maven_jar(
|
|||||||
|
|
||||||
maven_jar(
|
maven_jar(
|
||||||
name = 'gwtjsonrpc',
|
name = 'gwtjsonrpc',
|
||||||
id = 'gwtjsonrpc:gwtjsonrpc:1.5',
|
id = 'gwtjsonrpc:gwtjsonrpc:1.6',
|
||||||
bin_sha1 = '8995287e2c3c866e826d06993904e2c8d7961e4b',
|
bin_sha1 = '3673018b2d26a428d8fac6d2defce45e79f76452',
|
||||||
src_sha1 = 'c9461f6c0490f26720e3ff15b5607320eab89d96',
|
src_sha1 = '3d638e807dc8e6435f819eaade9b45d370cd164f',
|
||||||
license = 'Apache2.0',
|
license = 'Apache2.0',
|
||||||
repository = GERRIT,
|
repository = GERRIT,
|
||||||
)
|
)
|
||||||
|
17
lib/gwt/BUCK
17
lib/gwt/BUCK
@@ -1,11 +1,11 @@
|
|||||||
include_defs('//lib/maven.defs')
|
include_defs('//lib/maven.defs')
|
||||||
|
|
||||||
VERSION = '2.6.1'
|
VERSION = '2.7.0'
|
||||||
|
|
||||||
maven_jar(
|
maven_jar(
|
||||||
name = 'user',
|
name = 'user',
|
||||||
id = 'com.google.gwt:gwt-user:' + VERSION,
|
id = 'com.google.gwt:gwt-user:' + VERSION,
|
||||||
sha1 = 'c078b1b8cc0281214b0eb458d2c283d039374fad',
|
sha1 = 'bdc7af42581745d3d79c2efe0b514f432b998a5b',
|
||||||
license = 'Apache2.0',
|
license = 'Apache2.0',
|
||||||
attach_source = False,
|
attach_source = False,
|
||||||
)
|
)
|
||||||
@@ -13,7 +13,7 @@ maven_jar(
|
|||||||
maven_jar(
|
maven_jar(
|
||||||
name = 'dev',
|
name = 'dev',
|
||||||
id = 'com.google.gwt:gwt-dev:' + VERSION,
|
id = 'com.google.gwt:gwt-dev:' + VERSION,
|
||||||
sha1 = 'db237e4be0aa1fe43425d2c51ab5485dba211ddd',
|
sha1 = 'c2c3dd5baf648a0bb199047a818be5e560f48982',
|
||||||
license = 'Apache2.0',
|
license = 'Apache2.0',
|
||||||
deps = [
|
deps = [
|
||||||
':javax-validation',
|
':javax-validation',
|
||||||
@@ -24,17 +24,6 @@ maven_jar(
|
|||||||
exclude = ['org/eclipse/jetty/*'],
|
exclude = ['org/eclipse/jetty/*'],
|
||||||
)
|
)
|
||||||
|
|
||||||
maven_jar(
|
|
||||||
name = 'codeserver',
|
|
||||||
id = 'com.google.gwt:gwt-codeserver:' + VERSION,
|
|
||||||
sha1 = '940edc715cc31b1957e18f617f75a068f251346a',
|
|
||||||
license = 'Apache2.0',
|
|
||||||
deps = [
|
|
||||||
':dev',
|
|
||||||
],
|
|
||||||
attach_source = False,
|
|
||||||
)
|
|
||||||
|
|
||||||
maven_jar(
|
maven_jar(
|
||||||
name = 'json',
|
name = 'json',
|
||||||
id = 'org.json:json:20140107',
|
id = 'org.json:json:20140107',
|
||||||
|
@@ -20,7 +20,6 @@ java_library(
|
|||||||
'//lib/bouncycastle:bcprov',
|
'//lib/bouncycastle:bcprov',
|
||||||
'//lib/bouncycastle:bcpg',
|
'//lib/bouncycastle:bcpg',
|
||||||
'//lib/bouncycastle:bcpkix',
|
'//lib/bouncycastle:bcpkix',
|
||||||
'//lib/gwt:codeserver',
|
|
||||||
'//lib/jetty:servlets',
|
'//lib/jetty:servlets',
|
||||||
'//lib/prolog:compiler_lib',
|
'//lib/prolog:compiler_lib',
|
||||||
'//Documentation:index_lib',
|
'//Documentation:index_lib',
|
||||||
|
@@ -13,7 +13,6 @@
|
|||||||
<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
|
<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
|
||||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7" javaProject="gerrit" path="1" type="4"/> "/>
|
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7" javaProject="gerrit" path="1" type="4"/> "/>
|
||||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry id="org.eclipse.jdt.launching.classpathentry.defaultClasspath"> <memento exportedEntriesOnly="false" project="gerrit"/> </runtimeClasspathEntry> "/>
|
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry id="org.eclipse.jdt.launching.classpathentry.defaultClasspath"> <memento exportedEntriesOnly="false" project="gerrit"/> </runtimeClasspathEntry> "/>
|
||||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/gerrit/buck-out/gen/lib/gwt/codeserver/gwt-codeserver-2.6.1.jar" path="3" type="2"/> "/>
|
|
||||||
</listAttribute>
|
</listAttribute>
|
||||||
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
|
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
|
||||||
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gerrit.gwtdebug.GerritGwtDebugLauncher"/>
|
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gerrit.gwtdebug.GerritGwtDebugLauncher"/>
|
||||||
|
Reference in New Issue
Block a user