// 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 reponse with HTTP OK " + responseContent); } writeResponse(response, HttpStatus.SC_OK, responseContent); } else { if (s_logger.isTraceEnabled()) { s_logger.trace("Write reponse 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"; } }