/* * eXist Open Source Native XML Database * Copyright (C) 2001-2015 The eXist Project * http://exist-db.org * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package org.exist.xmlrpc; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.xmlrpc.XmlRpcException; import org.apache.xmlrpc.XmlRpcHandler; import org.apache.xmlrpc.server.AbstractReflectiveHandlerMapping; import org.apache.xmlrpc.server.RequestProcessorFactoryFactory; import org.apache.xmlrpc.server.XmlRpcHandlerMapping; import org.apache.xmlrpc.webserver.XmlRpcServlet; import org.exist.EXistException; import org.exist.http.Descriptor; import org.exist.http.servlets.HttpServletRequestWrapper; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class RpcServlet extends XmlRpcServlet { private static final long serialVersionUID = -1003413291835771186L; private static final Logger LOG = LogManager.getLogger(RpcServlet.class); private static boolean useDefaultUser = true; public static boolean isUseDefaultUser() { return useDefaultUser; } public static void setUseDefaultUser(final boolean useDefaultUser) { RpcServlet.useDefaultUser = useDefaultUser; } @Override public void doPost(HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException { // Request logger final Descriptor descriptor = Descriptor.getDescriptorSingleton(); if (descriptor.allowRequestLogging() && !descriptor.requestsFiltered()) { // Wrap HttpServletRequest, because both request Logger and xmlrpc // need the request InputStream, which is consumed when read. request = new HttpServletRequestWrapper(request, /*formEncoding*/ "utf-8"); descriptor.doLogRequestInReplayLog(request); } try { super.doPost(request, response); } catch (final Throwable e){ LOG.error("Problem during XmlRpc execution", e); final String exceptionMessage; if (e instanceof XmlRpcException) { final Throwable linkedException = ((XmlRpcException)e).linkedException; LOG.error(linkedException.getMessage(), linkedException); exceptionMessage = "An error occurred: " + e.getMessage() + ": " + linkedException.getMessage(); } else { exceptionMessage = "An unknown error occurred: " + e.getMessage(); } throw new ServletException(exceptionMessage, e); } } protected XmlRpcHandlerMapping newXmlRpcHandlerMapping() throws XmlRpcException { final DefaultHandlerMapping mapping = new DefaultHandlerMapping(); mapping.setVoidMethodEnabled(true); mapping.setRequestProcessorFactoryFactory(new XmldbRequestProcessorFactoryFactory()); mapping.loadDefault(RpcConnection.class); return mapping; } private static class XmldbRequestProcessorFactoryFactory extends RequestProcessorFactoryFactory.RequestSpecificProcessorFactoryFactory { RequestProcessorFactory instance = null; @Override public RequestProcessorFactory getRequestProcessorFactory(final Class pClass) throws XmlRpcException { try { if (instance == null) { instance = new XmldbRequestProcessorFactory("exist", useDefaultUser); } return instance; } catch (final EXistException e) { throw new XmlRpcException("Failed to initialize XMLRPC interface: " + e.getMessage(), e); } } } private static class DefaultHandlerMapping extends AbstractReflectiveHandlerMapping { private DefaultHandlerMapping() throws XmlRpcException { } public void loadDefault(final Class<?> clazz) throws XmlRpcException { registerPublicMethods("Default", clazz); } @Override public XmlRpcHandler getHandler(String pHandlerName) throws XmlRpcException { if (pHandlerName.indexOf('.') < 0) { pHandlerName = "Default." + pHandlerName; } return super.getHandler(pHandlerName); } } }