blob: 570aa29e4a2dbc6021aade95c71481e13a4f99b6 [file] [log] [blame]
/*******************************************************************************
* 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);
}
}
}