blob: f697ade8a39bc537c3154bae6d4beb5deb6d6810 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.cloud.cluster;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URLDecoder;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.entity.BasicHttpEntity;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestHandler;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
public class ClusterServiceServletHttpHandler implements HttpRequestHandler {
private static final Logger s_logger = Logger.getLogger(ClusterServiceServletHttpHandler.class);
private final ClusterManager manager;
public ClusterServiceServletHttpHandler(ClusterManager manager) {
this.manager = manager;
}
@Override
public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException {
try {
if (s_logger.isTraceEnabled()) {
s_logger.trace("Start Handling cluster HTTP request");
}
parseRequest(request);
handleRequest(request, response);
if (s_logger.isTraceEnabled()) {
s_logger.trace("Handle cluster HTTP request done");
}
} catch (final Throwable e) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Exception " + e.toString());
}
try {
writeResponse(response, HttpStatus.SC_INTERNAL_SERVER_ERROR, null);
} catch (final Throwable e2) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Exception " + e2.toString());
}
}
}
}
@SuppressWarnings("deprecation")
private void parseRequest(HttpRequest request) throws IOException {
if (request instanceof HttpEntityEnclosingRequest) {
final HttpEntityEnclosingRequest entityRequest = (HttpEntityEnclosingRequest)request;
final String body = EntityUtils.toString(entityRequest.getEntity());
if (body != null) {
final String[] paramArray = body.split("&");
if (paramArray != null) {
for (final String paramEntry : paramArray) {
final String[] paramValue = paramEntry.split("=");
if (paramValue.length != 2) {
continue;
}
final String name = URLDecoder.decode(paramValue[0]);
final String value = URLDecoder.decode(paramValue[1]);
if (s_logger.isTraceEnabled()) {
s_logger.trace("Parsed request parameter " + name + "=" + value);
}
request.getParams().setParameter(name, value);
}
}
}
}
}
private void writeResponse(HttpResponse response, int statusCode, String content) {
if (content == null) {
content = "";
}
response.setStatusCode(statusCode);
final BasicHttpEntity body = new BasicHttpEntity();
body.setContentType("text/html; charset=UTF-8");
final byte[] bodyData = content.getBytes();
body.setContent(new ByteArrayInputStream(bodyData));
body.setContentLength(bodyData.length);
response.setEntity(body);
}
protected void handleRequest(HttpRequest req, HttpResponse response) {
final String method = (String)req.getParams().getParameter("method");
int nMethod = RemoteMethodConstants.METHOD_UNKNOWN;
String responseContent = null;
try {
if (method != null) {
nMethod = Integer.parseInt(method);
}
switch (nMethod) {
case RemoteMethodConstants.METHOD_DELIVER_PDU:
responseContent = handleDeliverPduMethodCall(req);
break;
case RemoteMethodConstants.METHOD_PING:
responseContent = handlePingMethodCall(req);
break;
case RemoteMethodConstants.METHOD_UNKNOWN:
default:
assert false;
s_logger.error("unrecognized method " + nMethod);
break;
}
} catch (final Throwable e) {
s_logger.error("Unexpected exception when processing cluster service request : ", e);
}
if (responseContent != null) {
if (s_logger.isTraceEnabled()) {
s_logger.trace("Write response with HTTP OK " + responseContent);
}
writeResponse(response, HttpStatus.SC_OK, responseContent);
} else {
if (s_logger.isTraceEnabled()) {
s_logger.trace("Write response with HTTP Bad request");
}
writeResponse(response, HttpStatus.SC_BAD_REQUEST, null);
}
}
private String handleDeliverPduMethodCall(HttpRequest req) {
final String pduSeq = (String)req.getParams().getParameter("pduSeq");
final String pduAckSeq = (String)req.getParams().getParameter("pduAckSeq");
final String sourcePeer = (String)req.getParams().getParameter("sourcePeer");
final String destPeer = (String)req.getParams().getParameter("destPeer");
final String agentId = (String)req.getParams().getParameter("agentId");
final String gsonPackage = (String)req.getParams().getParameter("gsonPackage");
final String stopOnError = (String)req.getParams().getParameter("stopOnError");
final String pduType = (String)req.getParams().getParameter("pduType");
final ClusterServicePdu pdu = new ClusterServicePdu();
pdu.setSourcePeer(sourcePeer);
pdu.setDestPeer(destPeer);
pdu.setAgentId(Long.parseLong(agentId));
pdu.setSequenceId(Long.parseLong(pduSeq));
pdu.setAckSequenceId(Long.parseLong(pduAckSeq));
pdu.setJsonPackage(gsonPackage);
pdu.setStopOnError("1".equals(stopOnError));
pdu.setPduType(Integer.parseInt(pduType));
manager.OnReceiveClusterServicePdu(pdu);
return "true";
}
private String handlePingMethodCall(HttpRequest req) {
final String callingPeer = (String)req.getParams().getParameter("callingPeer");
if (s_logger.isDebugEnabled()) {
s_logger.debug("Handle ping request from " + callingPeer);
}
return "true";
}
}