| /******************************************************************************* |
| * Copyright (c) 2000, 2015 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.help.internal.webapp.servlet; |
| |
| import java.io.IOException; |
| import java.lang.reflect.Constructor; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| |
| import javax.servlet.ServletException; |
| import javax.servlet.http.HttpServlet; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.help.internal.base.BaseHelpSystem; |
| import org.eclipse.help.internal.base.HelpApplication; |
| import org.eclipse.help.internal.base.HelpDisplay; |
| import org.eclipse.help.internal.webapp.data.UrlUtil; |
| import org.osgi.framework.Bundle; |
| |
| /** |
| * Servlet to control Eclipse helpApplication from standalone application. |
| * Accepts the following parameters: command=displayHelp | shutdown |
| * | install | update | enable | disable | uninstall | search | listFeatures |
| * | addSite | removeSite | apply. |
| * href - may be provided if comand==displayHelp. |
| * featureId, version, from, to, verifyOnly may be provided for update commands |
| */ |
| public class ControlServlet extends HttpServlet { |
| private static final long serialVersionUID = 1L; |
| public static final String UPDATE_PLUGIN_ID = "org.eclipse.update.core"; //$NON-NLS-1$ |
| |
| public static final String CMD_DISPLAYHELP = "displayHelp"; //$NON-NLS-1$ |
| |
| public static final String CMD_DISPLAYHELPWINDOW = "displayHelpWindow"; //$NON-NLS-1$ |
| |
| public static final String CMD_SHUTDOWN = "shutdown"; //$NON-NLS-1$ |
| |
| public static final String CMD_INSTALL = "install"; //$NON-NLS-1$ |
| |
| public static final String CMD_UPDATE = "update"; //$NON-NLS-1$ |
| |
| public static final String CMD_ENABLE = "enable"; //$NON-NLS-1$ |
| |
| public static final String CMD_DISABLE = "disable"; //$NON-NLS-1$ |
| |
| public static final String CMD_UNINSTALL = "uninstall"; //$NON-NLS-1$ |
| |
| public static final String CMD_SEARCH = "search"; //$NON-NLS-1$ |
| |
| public static final String CMD_LIST = "listFeatures"; //$NON-NLS-1$ |
| |
| public static final String CMD_ADDSITE = "addSite"; //$NON-NLS-1$ |
| |
| public static final String CMD_APPLY = "apply"; //$NON-NLS-1$ |
| |
| public static final String CMD_REMOVESITE = "removeSite"; //$NON-NLS-1$ |
| |
| public static final String PACKAGE_PREFIX = "org.eclipse.update.standalone."; //$NON-NLS-1$ |
| |
| public static final String CLASS_INSTALL = PACKAGE_PREFIX |
| + "InstallCommand"; //$NON-NLS-1$ |
| |
| public static final String CLASS_UPDATE = PACKAGE_PREFIX + "UpdateCommand"; //$NON-NLS-1$ |
| |
| public static final String CLASS_ENABLE = PACKAGE_PREFIX + "EnableCommand"; //$NON-NLS-1$ |
| |
| public static final String CLASS_DISABLE = PACKAGE_PREFIX |
| + "DisableCommand"; //$NON-NLS-1$ |
| |
| public static final String CLASS_UNINSTALL = PACKAGE_PREFIX |
| + "UninstallCommand"; //$NON-NLS-1$ |
| |
| public static final String CLASS_SEARCH = PACKAGE_PREFIX + "SearchCommand"; //$NON-NLS-1$ |
| |
| public static final String CLASS_LIST = PACKAGE_PREFIX |
| + "ListFeaturesCommand"; //$NON-NLS-1$ |
| |
| public static final String CLASS_ADDSITE = PACKAGE_PREFIX |
| + "AddSiteCommand"; //$NON-NLS-1$ |
| |
| public static final String CLASS_REMOVESITE = PACKAGE_PREFIX |
| + "RemoveSiteCommand"; //$NON-NLS-1$ |
| |
| public static final String PARAM_FEATUREID = "featureId"; //$NON-NLS-1$ |
| |
| public static final String PARAM_VERSION = "version"; //$NON-NLS-1$ |
| |
| public static final String PARAM_FROM = "from"; //$NON-NLS-1$ |
| |
| public static final String PARAM_TO = "to"; //$NON-NLS-1$ |
| |
| public static final String PARAM_VERIFYONLY = "verifyOnly"; //$NON-NLS-1$ |
| |
| private HelpDisplay helpDisplay = null; |
| |
| private boolean shuttingDown = false; |
| |
| /** |
| * Called by the servlet container to indicate to a servlet that the servlet |
| * is being placed into service. |
| */ |
| @Override |
| public void init() throws ServletException { |
| super.init(); |
| if (BaseHelpSystem.getMode() == BaseHelpSystem.MODE_STANDALONE) { |
| helpDisplay = BaseHelpSystem.getHelpDisplay(); |
| } |
| } |
| |
| /** |
| * Called by the server (via the <code>service</code> method) to allow a |
| * servlet to handle a GET request. |
| */ |
| @Override |
| protected void doGet(HttpServletRequest req, HttpServletResponse resp) |
| throws ServletException, IOException { |
| processRequest(req, resp); |
| } |
| |
| /** |
| * Called by the server (via the <code>service</code> method) to allow a |
| * servlet to handle a POST request. |
| */ |
| @Override |
| protected void doPost(HttpServletRequest req, HttpServletResponse resp) |
| throws ServletException, IOException { |
| processRequest(req, resp); |
| } |
| |
| private void processRequest(HttpServletRequest req, HttpServletResponse resp) |
| throws ServletException, IOException { |
| |
| req.setCharacterEncoding("UTF-8"); //$NON-NLS-1$ |
| |
| // for HTTP 1.1 |
| resp.setHeader("Cache-Control", "no-cache"); //$NON-NLS-1$ //$NON-NLS-2$ |
| // for HTTP 1.0 |
| resp.setHeader("Pragma", "no-cache"); //$NON-NLS-1$ //$NON-NLS-2$ |
| resp.setDateHeader("Expires", 0); //$NON-NLS-1$ |
| //prevents caching at the proxy server |
| |
| if (!UrlUtil.isLocalRequest(req)) { |
| // do not allow remote clients to execute this servlet |
| return; |
| } |
| if (!"/help".equals(req.getContextPath()) //$NON-NLS-1$ |
| || !"/control".equals(req.getServletPath())) { //$NON-NLS-1$ |
| // do not allow arbitrary URLs to execute this servlet |
| resp.sendError(HttpServletResponse.SC_FORBIDDEN, ""); //$NON-NLS-1$ |
| return; |
| } |
| |
| if (shuttingDown) { |
| return; |
| } |
| |
| String command = req.getParameter("command"); //$NON-NLS-1$ |
| if (command == null) { |
| // this should never happen and is invisible to the user |
| resp.getWriter().print("No command."); //$NON-NLS-1$ |
| return; |
| } |
| |
| if (CMD_SHUTDOWN.equalsIgnoreCase(command)) { |
| shutdown(); |
| } else if (CMD_DISPLAYHELP.equalsIgnoreCase(command)) { |
| if (BaseHelpSystem.getMode() == BaseHelpSystem.MODE_STANDALONE) { |
| displayHelp(req); |
| } |
| } else if (CMD_DISPLAYHELPWINDOW.equalsIgnoreCase(command)) { |
| if (BaseHelpSystem.getMode() == BaseHelpSystem.MODE_STANDALONE) { |
| displayHelp(req); |
| HelpApplication.setShutdownOnClose(true); |
| } |
| } else if (CMD_INSTALL.equalsIgnoreCase(command) |
| || CMD_ENABLE.equalsIgnoreCase(command) |
| || CMD_UPDATE.equalsIgnoreCase(command) |
| || CMD_DISABLE.equalsIgnoreCase(command) |
| || CMD_UNINSTALL.equalsIgnoreCase(command) |
| || CMD_SEARCH.equalsIgnoreCase(command) |
| || CMD_LIST.equalsIgnoreCase(command) |
| || CMD_ADDSITE.equalsIgnoreCase(command) |
| || CMD_REMOVESITE.equalsIgnoreCase(command) |
| || CMD_APPLY.equalsIgnoreCase(command)) { |
| updateDocs(command, req); |
| } else { |
| // this should never happen and is invisible to the user |
| resp.getWriter().print("Unrecognized command."); //$NON-NLS-1$ |
| } |
| } |
| |
| private void updateDocs(String command, HttpServletRequest req) { |
| Bundle bundle = Platform.getBundle(UPDATE_PLUGIN_ID); |
| if (bundle == null) { |
| // no update plugin present |
| return; |
| } |
| try { |
| String className = getStandaloneClassName(command); |
| if (className == null) { |
| System.out.println("No class name for command " + command); //$NON-NLS-1$ |
| return; |
| } |
| Class<?> c = bundle.loadClass(className); |
| if (c == null) { |
| System.out.println("No class for command " + command); //$NON-NLS-1$ |
| return; |
| } |
| Class<?>[] parameterTypes = getParameterTypes(className); |
| Constructor<?> constr = c.getConstructor(parameterTypes); |
| if (constr == null) { |
| System.out.println("No expected constructor for command " //$NON-NLS-1$ |
| + command); |
| return; |
| } |
| Method m; |
| if (!CMD_APPLY.equalsIgnoreCase(command)) { |
| m = c.getMethod("run", new Class[]{}); //$NON-NLS-1$ |
| } else { |
| m = c.getMethod("applyChangesNow", new Class[]{}); //$NON-NLS-1$ |
| } |
| Object[] initargs = getInitArgs(className, req); |
| Object o = constr.newInstance(initargs); |
| Object ret = m.invoke(o, new Object[]{}); |
| if (!CMD_APPLY.equalsIgnoreCase(command) &&((Boolean)ret).equals(Boolean.FALSE)){ |
| System.out.println("Command not executed."); //$NON-NLS-1$ |
| } else { |
| System.out.println("Command executed."); //$NON-NLS-1$ |
| } |
| } catch (Exception e) { |
| Throwable t = e; |
| if (e instanceof InvocationTargetException) { |
| t = ((InvocationTargetException) e).getTargetException(); |
| } |
| System.out.println(t.getLocalizedMessage()); |
| //t.printStackTrace(); |
| } |
| } |
| |
| private String getStandaloneClassName(String command) { |
| if (CMD_INSTALL.equalsIgnoreCase(command)) |
| return CLASS_INSTALL; |
| else if (CMD_UPDATE.equalsIgnoreCase(command)) |
| return CLASS_UPDATE; |
| else if (CMD_ENABLE.equalsIgnoreCase(command)) |
| return CLASS_ENABLE; |
| else if (CMD_DISABLE.equalsIgnoreCase(command)) |
| return CLASS_DISABLE; |
| else if (CMD_UNINSTALL.equalsIgnoreCase(command)) |
| return CLASS_UNINSTALL; |
| else if (CMD_SEARCH.equalsIgnoreCase(command)) |
| return CLASS_SEARCH; |
| else if (CMD_LIST.equalsIgnoreCase(command) |
| || CMD_APPLY.equalsIgnoreCase(command)) |
| return CLASS_LIST; |
| else if (CMD_ADDSITE.equalsIgnoreCase(command)) |
| return CLASS_ADDSITE; |
| else if (CMD_REMOVESITE.equalsIgnoreCase(command)) |
| return CLASS_REMOVESITE; |
| else |
| return null; |
| } |
| |
| private Class<?>[] getParameterTypes(String className) { |
| if (CLASS_INSTALL.equals(className)) |
| return new Class[]{String.class, String.class, String.class, |
| String.class, String.class}; |
| else if (CLASS_UPDATE.equals(className)) |
| return new Class[]{String.class, String.class, String.class}; |
| else if (CLASS_ENABLE.equals(className) |
| || CLASS_DISABLE.equals(className) |
| || CLASS_UNINSTALL.equals(className)) |
| return new Class[]{String.class, String.class, String.class, |
| String.class}; |
| else |
| return new Class[]{String.class}; |
| } |
| |
| private Object[] getInitArgs(String className, HttpServletRequest req) { |
| String featureId = req.getParameter(PARAM_FEATUREID); |
| String version = req.getParameter(PARAM_VERSION); |
| String fromSite = req.getParameter(PARAM_FROM); |
| String toSite = req.getParameter(PARAM_TO); |
| String verifyOnly = req.getParameter(PARAM_VERIFYONLY); |
| if (CLASS_INSTALL.equals(className)) |
| return new Object[]{featureId, version, fromSite, toSite, |
| verifyOnly}; |
| else if (CLASS_UPDATE.equals(className)) |
| return new Object[]{featureId, version, verifyOnly}; |
| else if (CLASS_ENABLE.equals(className) |
| || CLASS_DISABLE.equals(className) |
| || CLASS_UNINSTALL.equals(className)) |
| return new Object[]{featureId, version, toSite, verifyOnly}; |
| else if (CLASS_REMOVESITE.equals(className)) |
| return new Object[]{toSite}; |
| else |
| return new Object[]{fromSite}; |
| } |
| |
| /** |
| * Shuts-down Eclipse helpApplication. |
| */ |
| private void shutdown() { |
| shuttingDown = true; |
| HelpApplication.stopHelp(); |
| } |
| |
| /** |
| * Displays help. |
| * |
| * @param req |
| * HttpServletRequest that might contain href parameter, which is |
| * the resource to display |
| */ |
| private void displayHelp(HttpServletRequest req) { |
| String href = req.getParameter("href"); //$NON-NLS-1$ |
| if (href != null) { |
| helpDisplay.displayHelpResource(href, false); |
| } else { |
| helpDisplay.displayHelp(false); |
| } |
| } |
| } |