1 /** 2 * This file Copyright (c) 2010-2010 Magnolia International 3 * Ltd. (http://www.magnolia-cms.com). All rights reserved. 4 * 5 * 6 * This file is dual-licensed under both the Magnolia 7 * Network Agreement and the GNU General Public License. 8 * You may elect to use one or the other of these licenses. 9 * 10 * This file is distributed in the hope that it will be 11 * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the 12 * implied warranty of MERCHANTABILITY or FITNESS FOR A 13 * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. 14 * Redistribution, except as permitted by whichever of the GPL 15 * or MNA you select, is prohibited. 16 * 17 * 1. For the GPL license (GPL), you can redistribute and/or 18 * modify this file under the terms of the GNU General 19 * Public License, Version 3, as published by the Free Software 20 * Foundation. You should have received a copy of the GNU 21 * General Public License, Version 3 along with this program; 22 * if not, write to the Free Software Foundation, Inc., 51 23 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 24 * 25 * 2. For the Magnolia Network Agreement (MNA), this file 26 * and the accompanying materials are made available under the 27 * terms of the MNA which accompanies this distribution, and 28 * is available at http://www.magnolia.info/mna.html 29 * 30 * Any modifications to this file must keep this entire header 31 * intact. 32 * 33 */ 34 package info.magnolia.module.groovy.servlets; 35 36 import java.io.IOException; 37 38 import info.magnolia.context.MgnlContext; 39 import info.magnolia.module.groovy.console.MgnlGroovyInteractiveConsole; 40 41 import javax.servlet.ServletException; 42 import javax.servlet.http.HttpServlet; 43 import javax.servlet.http.HttpServletRequest; 44 import javax.servlet.http.HttpServletResponse; 45 46 import org.slf4j.Logger; 47 import org.slf4j.LoggerFactory; 48 49 50 /** 51 * A special servlet which makes at your disposal the Magnolia's Groovy interactive console bypassing the 52 * normal Magnolia's filters chain. This can be useful, for instance, to perform rescue operations on a corrupted Magnolia instance. 53 * <strong>Warning:</strong> All operations are executed in system context, meaning that no security restrictions are enforced which 54 * might expose your data to risk of irreversible damages if you are not aware of what you are doing. In other words, <strong>use it at your own risk</strong>. 55 * <br> 56 * To use it, in your <code>web.xml</code> you must explicitely comment out the Magnolia filter chain part and add or uncomment the Groovy rescue servlet. 57 * <strong>Important</strong>: You also need to explicitely add a <code>servlet</code> and a <code>servlet-mapping</code> for 58 * <code>info.magnolia.cms.servlets.ClasspathSpool</code> as this is needed to serve correctly the javascript and css needed by the console. <br> 59 * For a sample configuration, see the <code>web.xml</code> fragment below: 60 * 61 * <pre> 62 * [...] 63 * <!-- 64 * <filter> 65 * <display-name>Magnolia global filters</display-name> 66 * <filter-name>magnoliaFilterChain</filter-name> 67 * <filter-class>info.magnolia.cms.filters.MgnlMainFilter</filter-class> 68 * </filter> 69 * <filter-mapping> 70 * <filter-name>magnoliaFilterChain</filter-name> 71 * <url-pattern>/*</url-pattern> 72 * <dispatcher>REQUEST</dispatcher> 73 * <dispatcher>FORWARD</dispatcher> 74 * <dispatcher>ERROR</dispatcher> 75 * </filter-mapping> 76 * --> 77 * <servlet> 78 * <servlet-name>mgnlGroovyServlet</servlet-name> 79 * <servlet-class>info.magnolia.module.groovy.servlets.MgnlGroovyRescueServlet</servlet-class> 80 * </servlet> 81 * <servlet-mapping> 82 * <servlet-name>mgnlGroovyServlet</servlet-name> 83 * <url-pattern>/.magnolia/pages/groovyInteractiveConsole.html</url-pattern> 84 * </servlet-mapping> 85 * <servlet> 86 * <servlet-name>resourcesServlet</servlet-name> 87 * <servlet-class>info.magnolia.cms.servlets.ClasspathSpool</servlet-class> 88 * </servlet> 89 * <servlet-mapping> 90 * <servlet-name>resourcesServlet</servlet-name> 91 * <url-pattern>/.resources/*</url-pattern> 92 * </servlet-mapping> 93 * [...] 94 * </pre> 95 * Once configured and having restarted the web container, you can access the console like this 96 * <pre> 97 * http://yourserver[:port]/contextname/.magnolia/pages/groovyInteractiveConsole.html 98 * </pre> 99 * @author fgrilli 100 * @version $Id$ 101 * 102 */ 103 public final class MgnlGroovyRescueServlet extends HttpServlet { 104 105 private static final long serialVersionUID = 222L; 106 107 private static final Logger log = LoggerFactory.getLogger(MgnlGroovyRescueServlet.class); 108 109 @Override 110 public void init() throws ServletException { 111 log.info("Starting MgnlGroovyRescueServlet..."); 112 super.init(); 113 } 114 115 @Override 116 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 117 doPost(req, resp); 118 } 119 120 @Override 121 protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { 122 try { 123 MgnlContext.doInSystemContext(new MgnlContext.Op<Void, Throwable>() { 124 public Void exec() throws Throwable { 125 executeCommand(request, response); 126 return null; 127 } 128 }, true ); 129 } 130 catch (Throwable e) { 131 log.error("An error occurred: ", e); 132 } 133 } 134 135 private void executeCommand(final HttpServletRequest request, final HttpServletResponse response) throws IOException { 136 final MgnlGroovyInteractiveConsole handler = new MgnlGroovyInteractiveConsole(null, request, response); 137 //if no command was found, defaults to clean (removes old groovy binding from http session and creates a new empty one) 138 final String command = request.getParameter("command") == null || request.getParameter("command").length() == 0 ? "clean" : request.getParameter("command"); 139 final String code = request.getParameter("code"); 140 log.info("Executing {}", code != null ? code : command); 141 final String view = handler.execute(command); 142 response.setCharacterEncoding("UTF-8"); 143 handler.renderHtml(view); 144 } 145 }