blob: dffc45a88410f416483376b2b0a760550421cf58 [file] [log] [blame]
/*
* Copyright 2013 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.user.server.rpc;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
/**
* A simple and relatively naive client for downloading serialization policies from a URL.
* (Intended only for development.)
*/
class SerializationPolicyClient {
private final int connectTimeout;
private final int readTimeout;
/**
* Creates an client with the given configuration,
* @param connectTimeoutMs see {@link URLConnection#setConnectTimeout}
* @param readTimeoutMs see {@link URLConnection#setReadTimeout}
*/
SerializationPolicyClient(int connectTimeoutMs, int readTimeoutMs) {
this.connectTimeout = connectTimeoutMs;
this.readTimeout = readTimeoutMs;
}
SerializationPolicy loadPolicy(String url, Logger logger) {
URL urlObj;
try {
urlObj = new URL(url);
} catch (MalformedURLException e) {
logger.logError("Can't parse serialization policy URL: " + url, e);
return null;
}
URLConnection conn;
InputStream in;
try {
conn = urlObj.openConnection();
conn.setConnectTimeout(connectTimeout);
conn.setReadTimeout(readTimeout);
// The code server doesn't redirect. Fail fast if we get a redirect since
// it's likely a configuration error.
if (conn instanceof HttpURLConnection) {
((HttpURLConnection)conn).setInstanceFollowRedirects(false);
}
conn.connect();
in = conn.getInputStream();
} catch (IOException e) {
logger.logError("Can't open serialization policy URL: " + url, e);
return null;
}
return readPolicy(in, url, logger);
}
/**
* Attempts to read a policy from a given InputStream and logs any errors.
*
* @param sourceName names the source of the input stream for log messages.
* @return the policy or null if unavailable.
*/
private static SerializationPolicy readPolicy(InputStream in, String sourceName,
Logger logger) {
try {
List<ClassNotFoundException> errs = new ArrayList<ClassNotFoundException>();
SerializationPolicy policy = SerializationPolicyLoader.loadFromStream(in, errs);
logger.logInfo("Downloaded serialization policy from " + sourceName);
if (!errs.isEmpty()) {
logMissingClasses(logger, errs);
}
return policy;
} catch (ParseException e) {
logger.logError("Can't parse serialization policy from " + sourceName, e);
return null;
} catch (IOException e) {
logger.logError("Can't read serialization policy from " + sourceName, e);
return null;
} finally {
try {
in.close();
} catch (IOException e) {
logger.logError("Can't close serialization policy url: " + sourceName, e);
}
}
}
private static void logMissingClasses(Logger logger, List<ClassNotFoundException> errs) {
StringBuilder message = new StringBuilder();
message.append("Unable to load server-side classes used by policy:\n");
int limit = Math.min(10, errs.size());
for (int i = 0; i < limit; i++) {
message.append(" " + errs.get(i).getMessage() + "\n");
}
int omitted = errs.size() - limit;
if (omitted > 0) {
message.append(" (omitted " + omitted + " more classes)\n");
}
logger.logInfo(message.toString());
}
/**
* Destination for the loader's log messages.
*/
interface Logger {
void logInfo(String message);
void logError(String message, Throwable throwable);
}
}