/** * Copyright (c) 2009--2012 Red Hat, Inc. * * This software is licensed to you under the GNU General Public License, * version 2 (GPLv2). There is NO WARRANTY for this software, express or * implied, including the implied warranties of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 * along with this software; if not, see * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. * * Red Hat trademarks are not licensed under GPLv2. No permission is * granted to use or replicate Red Hat trademarks that are incorporated * in this software or its documentation. */ package com.redhat.rhn.frontend.xmlrpc; import com.redhat.rhn.frontend.xmlrpc.serializer.SerializerFactory; import org.apache.log4j.Logger; import java.io.IOException; import java.util.Iterator; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import redstone.xmlrpc.XmlRpcCustomSerializer; /** * A basic servlet class that registers handlers for xmlrpc calls * * @version $Rev$ * todo pull in namespace + classes for handlers from, say, a properties file * todo perhaps override doGet ?? */ public class XmlRpcServlet extends HttpServlet { /** Comment for <code>serialVersionUID</code> */ private static final long serialVersionUID = -9173485623604749521L; private static Logger log = Logger.getLogger(XmlRpcServlet.class); private RhnXmlRpcServer server; private HandlerFactory handlers; private SerializerFactory serializers; /** * Constructor which takes in HandlerFactory and SerializerFactory. The * HandlerFactory determines what methods are exposed and which handlers * "handle" those calls. The SerializerFactory adds custom serializers * to the mix, extending the capabilities of the XMLRPC library. * @param hf HandlerFactory to use. * @param sf SerializerFactory to use. */ public XmlRpcServlet(HandlerFactory hf, SerializerFactory sf) { handlers = hf; serializers = sf; } /** * default constructor */ public XmlRpcServlet() { this(new HandlerFactory(), new SerializerFactory()); } private void passControl(HttpServletRequest request, HttpServletResponse response) throws IOException { response.sendRedirect("/rhn/apidoc/index.jsp"); } /** * initialize the servlet */ public void init() { server = new RhnXmlRpcServer(); registerInvocationHandlers(server); registerCustomSerializers(server); // enhancement: if we ever need more than one InvocationProcessor // we should use the ManifestFactory like we did above for the // handlers. server.addInvocationInterceptor(new LoggingInvocationProcessor()); } private void registerCustomSerializers(RhnXmlRpcServer srvr) { if (serializers == null) { serializers = new SerializerFactory(); } // find the configured serializers... for (Iterator i = serializers.getSerializers().iterator(); i.hasNext();) { srvr.getSerializer().addCustomSerializer( (XmlRpcCustomSerializer) i.next()); } } private void registerInvocationHandlers(RhnXmlRpcServer srvr) { if (handlers == null) { handlers = new HandlerFactory(); } // find the configured handlers... Iterator i = handlers.getKeys().iterator(); while (i.hasNext()) { String namespace = (String)i.next(); if (log.isDebugEnabled()) { log.debug("registerInvocationHandler: namespace [" + namespace + "] handler [" + handlers.getHandler(namespace) + "]"); } srvr.addInvocationHandler(namespace, handlers.getHandler(namespace)); } } /** * executed when a get request happens * * @param request the request object * @param response the response object * @throws ServletException if an error occurs * @throws IOException if an error occurs */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { passControl(request, response); } /** * executed when a post request happens * * @param request the request object * @param response the response object * @throws ServletException if a read error occurs * @throws IOException if a read error occurs */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { if (log.isDebugEnabled()) { log.debug("Entered doPost"); } if (request.getHeader("SOAPAction") != null) { passControl(request, response); return; } response.setContentType("text/xml"); try { if (log.isDebugEnabled()) { log.debug("Passing control to XmlRpcServer.execute"); } server.execute(request.getInputStream(), response.getWriter(), request.getRemoteAddr(), request.getLocalName(), request.getProtocol()); /* * jesusr - 2007.09.14 * this is still the case * * mbowman - 2005.10.06 * Like we were raised in a barn, we are going to leave here without * flushing ;) * -- The current thinking is that Tocmat handles the outputStream * -- flushing and closing for us. This make sense since after this * -- method runs, the response still needs to go back up through * -- the filters and out. If things start breaking in the future, * -- this is a good place to start looking. */ } // As bad as this is, we have no choice, Marquee-xmlrpc throws // Throwable, so we have to catch it. catch (Throwable t) { // By the time we get here, it can't be a FaultException, so just // wrap it in a ServletException and toss. ServletException e = new ServletException("Throwable from XmlRpc", t); t.printStackTrace(); if (e.getCause() != t) { e.initCause(t); } throw e; } } }