/*
* (C) Copyright 2011 Nuxeo SA (http://nuxeo.com/) and others.
*
* 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.
*
* Contributors:
* Julien Carsique
*
*/
package org.nuxeo.launcher.monitoring;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.URL;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuxeo.launcher.config.ConfigurationGenerator;
/**
* HTTP client monitoring Nuxeo server starting status
*
* @see org.nuxeo.ecm.core.management.statuses.StatusServlet
* @since 5.5
*/
public class StatusServletClient {
private static final Log log = LogFactory.getLog(StatusServletClient.class);
protected static final String URL_PATTERN = "runningstatus";
protected static final String POST_PARAM = "info";
protected static final String POST_PARAM_STARTED = "started";
protected static final String POST_PARAM_SUMMARY = "summary";
private static final int TIMEOUT = 1000;
private static final int SUMMARY_TIMEOUT = 2000;
private URL url;
private HttpURLConnection server;
private int timeout;
private boolean startupFine = false;
private String key;
/**
* Set secure key used for connection
*
* @param key any {@link String}
*/
public void setKey(String key) {
this.key = key;
}
/**
* @param configurationGenerator
*/
public StatusServletClient(ConfigurationGenerator configurationGenerator) {
final String servletURL = configurationGenerator.getUserConfig().getProperty(
ConfigurationGenerator.PARAM_LOOPBACK_URL)
+ "/" + URL_PATTERN;
try {
url = new URL(servletURL);
} catch (MalformedURLException e) {
log.error("Malformed URL: " + servletURL, e);
}
}
/**
* @return true if Nuxeo finished starting
* @throws SocketTimeoutException
*/
public boolean isStarted() throws SocketTimeoutException {
timeout = TIMEOUT;
return post(POST_PARAM, POST_PARAM_STARTED);
}
/**
* @param postParam
* @param postParamStarted
* @return
* @throws SocketTimeoutException
*/
private boolean post(String postParam, String postParamStarted) throws SocketTimeoutException {
return post(postParam, postParamStarted, null);
}
/**
* @return true if succeed to connect on StatusServlet
* @throws SocketTimeoutException
*/
public boolean init() throws SocketTimeoutException {
try {
timeout = TIMEOUT;
connect("GET");
} catch (SocketTimeoutException e) {
throw e;
} catch (IOException e) {
return false;
} finally {
disconnect();
}
return true;
}
protected synchronized void disconnect() {
if (server != null) {
server.disconnect();
server = null;
}
notifyAll();
}
protected synchronized void connect(String method) throws IOException {
while (server != null) {
try {
wait();
} catch (InterruptedException e) {
// do nothing
}
}
server = (HttpURLConnection) url.openConnection();
server.setConnectTimeout(timeout);
server.setReadTimeout(timeout);
server.setDoInput(true);
server.setDoOutput(true);
server.setRequestMethod(method);
server.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
server.connect();
}
/**
* @return Nuxeo server startup summary (components loading status)
* @throws SocketTimeoutException
*/
public String getStartupSummary() throws SocketTimeoutException {
timeout = SUMMARY_TIMEOUT;
StringBuilder sb = new StringBuilder();
startupFine = post(POST_PARAM, POST_PARAM_SUMMARY, sb);
return sb.toString();
}
protected boolean post(String param, String value, StringBuilder response) throws SocketTimeoutException {
String post = param + "=" + value;
post += "&key=" + key;
try {
connect("POST");
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(server.getOutputStream()));
bw.write(post, 0, post.length());
bw.close();
return getResponse(response);
} catch (SocketTimeoutException e) {
throw e;
} catch (IOException e) {
return false;
} finally {
disconnect();
}
}
protected boolean getResponse(StringBuilder response) throws IOException {
String line;
boolean answer;
BufferedReader s = null;
try {
s = new BufferedReader(new InputStreamReader(server.getInputStream()));
// First line is a status (true or false)
answer = Boolean.parseBoolean(s.readLine());
// Next (if exists) is a response body
while ((line = s.readLine()) != null) {
if (response != null) {
response.append(line + "\n");
}
}
} catch (IOException e) {
throw e;
} finally {
IOUtils.closeQuietly(s);
}
return answer;
}
/**
* Return detected status of Nuxeo server by last call to {@link #getStartupSummary()}
*
* @return true if everything is fine; false is there was any error or status is unknown
*/
public boolean isStartupFine() {
return startupFine;
}
}