All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opencms.main.CmsShell Maven / Gradle / Ivy

Go to download

OpenCms is an enterprise-ready, easy to use website content management system based on Java and XML technology. Offering a complete set of features, OpenCms helps content managers worldwide to create and maintain beautiful websites fast and efficiently.

The newest version!
/*
 * This library is part of OpenCms -
 * the Open Source Content Management System
 *
 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
 *
 * This library 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.1 of the License, or (at your option) any later version.
 *
 * This library 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.
 *
 * For further information about Alkacon Software GmbH & Co. KG, please see the
 * company website: http://www.alkacon.com
 *
 * For further information about OpenCms, please see the
 * project website: http://www.opencms.org
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package org.opencms.main;

import org.opencms.configuration.CmsParameterConfiguration;
import org.opencms.db.CmsUserSettings;
import org.opencms.file.CmsObject;
import org.opencms.file.CmsUser;
import org.opencms.i18n.CmsLocaleManager;
import org.opencms.i18n.CmsMessages;
import org.opencms.security.CmsRole;
import org.opencms.util.CmsDataTypeUtil;
import org.opencms.util.CmsFileUtil;
import org.opencms.util.CmsStringUtil;
import org.opencms.util.benchmark.CmsBenchmarkTable;
import org.opencms.util.benchmark.CmsFileBenchmarkReceiver;

import java.awt.event.KeyEvent;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.PrintStream;
import java.io.Reader;
import java.io.StreamTokenizer;
import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;

/**
 * A command line interface to access OpenCms functions which
 * is used for the initial setup and also can be used for scripting access to the OpenCms
 * repository without the Workplace.

* * The CmsShell has direct access to all methods in the "command objects". * Currently, the following classes are used as command objects: * {@link org.opencms.main.CmsShellCommands}, * {@link org.opencms.file.CmsRequestContext} and * {@link org.opencms.file.CmsObject}.

* * It is also possible to add a custom command object when calling the script API, * like in {@link CmsShell#CmsShell(String, String, String, String, List, PrintStream, PrintStream, boolean)}.

* * Only public methods in the command objects that use supported data types * as parameters can be called from the shell. Supported data types are: * String, {@link org.opencms.util.CmsUUID}, boolean, int, long, double, float.

* * If a method name is ambiguous, i.e. the method name with the same number of parameter exist * in more then one of the command objects, the method is only executed on the first matching method object.

* * @since 6.0.0 * * @see org.opencms.main.CmsShellCommands * @see org.opencms.file.CmsRequestContext * @see org.opencms.file.CmsObject */ public class CmsShell { /** * Command object class.

*/ private class CmsCommandObject { /** The list of methods. */ private Map> m_methods; /** The object to execute the methods on. */ private Object m_object; /** * Creates a new command object.

* * @param object the object to execute the methods on */ protected CmsCommandObject(Object object) { m_object = object; initShellMethods(); } /** * Tries to execute a method for the provided parameters on this command object.

* * If methods with the same name and number of parameters exist in this command object, * the given parameters are tried to be converted from String to matching types.

* * @param command the command entered by the user in the shell * @param parameters the parameters entered by the user in the shell * @return true if a method was executed, false otherwise */ @SuppressWarnings("synthetic-access") protected boolean executeMethod(String command, List parameters) { m_hasReportError = false; // build the method lookup String lookup = buildMethodLookup(command, parameters.size()); // try to look up the methods of this command object List possibleMethods = m_methods.get(lookup); if (possibleMethods == null) { return false; } // a match for the method name was found, now try to figure out if the parameters are ok Method onlyStringMethod = null; Method foundMethod = null; Object[] params = null; Iterator i; // first check if there is one method with only has String parameters, make this the fall back i = possibleMethods.iterator(); while (i.hasNext()) { Method method = i.next(); Class[] clazz = method.getParameterTypes(); boolean onlyString = true; for (int j = 0; j < clazz.length; j++) { if (!(clazz[j].equals(String.class))) { onlyString = false; break; } } if (onlyString) { onlyStringMethod = method; break; } } // now check a method matches the provided parameters // if so, use this method, else continue searching i = possibleMethods.iterator(); while (i.hasNext()) { Method method = i.next(); if (method == onlyStringMethod) { // skip the String only signature because this would always match continue; } // now try to convert the parameters to the required types Class[] clazz = method.getParameterTypes(); Object[] converted = new Object[clazz.length]; boolean match = true; for (int j = 0; j < clazz.length; j++) { String value = parameters.get(j); try { converted[j] = CmsDataTypeUtil.parse(value, clazz[j]); } catch (Throwable t) { match = false; break; } } if (match) { // we found a matching method signature params = converted; foundMethod = method; break; } } if ((foundMethod == null) && (onlyStringMethod != null)) { // no match found but String only signature available, use this params = parameters.toArray(); foundMethod = onlyStringMethod; } if ((params == null) || (foundMethod == null)) { // no match found at all return false; } // now try to invoke the method try { Object result = foundMethod.invoke(m_object, params); if (result != null) { if (result instanceof Collection) { Collection c = (Collection)result; m_out.println(c.getClass().getName() + " (size: " + c.size() + ")"); int count = 0; if (result instanceof Map) { Map m = (Map)result; Iterator j = m.entrySet().iterator(); while (j.hasNext()) { Map.Entry entry = (Map.Entry)j.next(); m_out.println(count++ + ": " + entry.getKey() + "= " + entry.getValue()); } } else { Iterator j = c.iterator(); while (j.hasNext()) { m_out.println(count++ + ": " + j.next()); } } } else { m_out.println(result.toString()); } } } catch (InvocationTargetException ite) { m_out.println( Messages.get().getBundle(getLocale()).key( Messages.GUI_SHELL_EXEC_METHOD_1, new Object[] {foundMethod.getName()})); ite.getTargetException().printStackTrace(m_out); if (m_errorCode != -1) { throw new CmsShellCommandException(ite.getCause()); } } catch (Throwable t) { m_out.println( Messages.get().getBundle(getLocale()).key( Messages.GUI_SHELL_EXEC_METHOD_1, new Object[] {foundMethod.getName()})); t.printStackTrace(m_out); if (m_errorCode != -1) { throw new CmsShellCommandException(t); } } if (m_hasReportError && (m_errorCode != -1)) { throw new CmsShellCommandException(true); } return true; } /** * Returns a signature overview of all methods containing the given search String.

* * If no method name matches the given search String, the empty String is returned.

* * @param searchString the String to search for, if null all methods are shown * * @return a signature overview of all methods containing the given search String */ protected String getMethodHelp(String searchString) { StringBuffer buf = new StringBuffer(512); Iterator i = m_methods.keySet().iterator(); while (i.hasNext()) { List l = m_methods.get(i.next()); Iterator j = l.iterator(); while (j.hasNext()) { Method method = j.next(); if ((searchString == null) || (method.getName().toLowerCase().indexOf(searchString.toLowerCase()) > -1)) { buf.append("* "); buf.append(method.getName()); buf.append("("); Class[] params = method.getParameterTypes(); for (int k = 0; k < params.length; k++) { String par = params[k].getName(); par = par.substring(par.lastIndexOf('.') + 1); if (k != 0) { buf.append(", "); } buf.append(par); } buf.append(")\n"); } } } return buf.toString(); } /** * Returns the object to execute the methods on.

* * @return the object to execute the methods on */ protected Object getObject() { return m_object; } /** * Builds a method lookup String.

* * @param methodName the name of the method * @param paramCount the parameter count of the method * * @return a method lookup String */ private String buildMethodLookup(String methodName, int paramCount) { StringBuffer buf = new StringBuffer(32); buf.append(methodName.toLowerCase()); buf.append(" ["); buf.append(paramCount); buf.append("]"); return buf.toString(); } /** * Initializes the map of accessible methods.

*/ private void initShellMethods() { Map> result = new TreeMap>(); Method[] methods = m_object.getClass().getMethods(); for (int i = 0; i < methods.length; i++) { // only public methods directly declared in the base class can be used in the shell if ((methods[i].getDeclaringClass() == m_object.getClass()) && (methods[i].getModifiers() == Modifier.PUBLIC)) { // check if the method signature only uses primitive data types boolean onlyPrimitive = true; Class[] clazz = methods[i].getParameterTypes(); for (int j = 0; j < clazz.length; j++) { if (!CmsDataTypeUtil.isParseable(clazz[j])) { // complex data type methods can not be called from the shell onlyPrimitive = false; break; } } if (onlyPrimitive) { // add this method to the set of methods that can be called from the shell String lookup = buildMethodLookup(methods[i].getName(), methods[i].getParameterTypes().length); List l; if (result.containsKey(lookup)) { l = result.get(lookup); } else { l = new ArrayList(1); } l.add(methods[i]); result.put(lookup, l); } } } m_methods = result; } } /** Prefix for "additional" parameter. */ public static final String SHELL_PARAM_ADDITIONAL_COMMANDS = "-additional="; /** Prefix for "base" parameter. */ public static final String SHELL_PARAM_BASE = "-base="; /** Prefix for "servletMapping" parameter. */ public static final String SHELL_PARAM_DEFAULT_WEB_APP = "-defaultWebApp="; /** Prefix for errorCode parameter. */ public static final String SHELL_PARAM_ERROR_CODE = "-errorCode="; /** Command line parameter to prevent disabling of JLAN. */ public static final String SHELL_PARAM_JLAN = "-jlan"; /** Prefix for "script" parameter. */ public static final String SHELL_PARAM_SCRIPT = "-script="; /** Prefix for "servletMapping" parameter. */ public static final String SHELL_PARAM_SERVLET_MAPPING = "-servletMapping="; /** * Thread local which stores the currently active shell instance. * *

We need multiple ones because shell commands may cause another nested shell to be launched (e.g. for module import scripts). */ public static final ThreadLocal> SHELL_STACK = ThreadLocal.withInitial(() -> new ArrayList<>()); /** Boolean variable to disable JLAN. */ private static boolean JLAN_DISABLED; /** The benchmark table. */ private CmsBenchmarkTable m_benchmarkTable; /** The OpenCms context object. */ protected CmsObject m_cms; /** Stream to write the error messages output to. */ protected PrintStream m_err; /** The code which the process should exit with in case of errors; -1 means exit is not called. */ protected int m_errorCode = -1; /** Stream to write the regular output messages to. */ protected PrintStream m_out; /** Additional shell commands object. */ private List m_additionalShellCommands; /** All shell callable objects. */ private List m_commandObjects; /** If set to true, all commands are echoed. */ private boolean m_echo; /** Indicates if the 'exit' command has been called. */ private boolean m_exitCalled; /** Flag to indicate whether an error was added to a shell report during the last command execution. */ private boolean m_hasReportError; /** Indicates if this is an interactive session with a user sitting on a console. */ private boolean m_interactive; /** The messages object. */ private CmsMessages m_messages; /** The OpenCms system object. */ private OpenCmsCore m_opencms; /** The shell prompt format. */ private String m_prompt; /** The current users settings. */ private CmsUserSettings m_settings; /** Internal shell command object. */ private I_CmsShellCommands m_shellCommands; /** * Creates a new CmsShell.

* * @param cms the user context to run the shell from * @param prompt the prompt format to set * @param additionalShellCommands optional objects for additional shell commands, or null * @param out stream to write the regular output messages to * @param err stream to write the error messages output to */ public CmsShell( CmsObject cms, String prompt, List additionalShellCommands, PrintStream out, PrintStream err) { setPrompt(prompt); try { // has to be initialized already if this constructor is used m_opencms = null; Locale locale = getLocale(); m_messages = Messages.get().getBundle(locale); m_cms = cms; // initialize the shell initShell(additionalShellCommands, out, err); } catch (Exception e) { throw new RuntimeException("Error initializing CmsShell: " + e.getLocalizedMessage(), e); } } /** * Creates a new CmsShell using System.out and System.err for output of the messages.

* * @param webInfPath the path to the 'WEB-INF' folder of the OpenCms installation * @param servletMapping the mapping of the servlet (or null to use the default "/opencms/*") * @param defaultWebAppName the name of the default web application (or null to use the default "ROOT") * @param prompt the prompt format to set * @param additionalShellCommands optional object for additional shell commands, or null */ public CmsShell( String webInfPath, String servletMapping, String defaultWebAppName, String prompt, I_CmsShellCommands additionalShellCommands) { this( webInfPath, servletMapping, defaultWebAppName, prompt, additionalShellCommands != null ? Arrays.asList(additionalShellCommands) : Collections.emptyList()); } /** * Creates a new CmsShell using System.out and System.err for output of the messages.

* * @param webInfPath the path to the 'WEB-INF' folder of the OpenCms installation * @param servletMapping the mapping of the servlet (or null to use the default "/opencms/*") * @param defaultWebAppName the name of the default web application (or null to use the default "ROOT") * @param prompt the prompt format to set * @param additionalShellCommands optional objects for additional shell commands, or null */ public CmsShell( String webInfPath, String servletMapping, String defaultWebAppName, String prompt, List additionalShellCommands) { this( webInfPath, servletMapping, defaultWebAppName, prompt, additionalShellCommands, System.out, System.err, false); } /** * Creates a new CmsShell.

* * @param webInfPath the path to the 'WEB-INF' folder of the OpenCms installation * @param servletMapping the mapping of the servlet (or null to use the default "/opencms/*") * @param defaultWebAppName the name of the default web application (or null to use the default "ROOT") * @param prompt the prompt format to set * @param additionalShellCommands optional list of objects for additional shell commands, or null * @param out stream to write the regular output messages to * @param err stream to write the error messages output to * @param interactive if true this is an interactive session with a user sitting on a console */ public CmsShell( String webInfPath, String servletMapping, String defaultWebAppName, String prompt, List additionalShellCommands, PrintStream out, PrintStream err, boolean interactive) { setPrompt(prompt); setInteractive(interactive); if (CmsStringUtil.isEmpty(servletMapping)) { servletMapping = "/opencms/*"; } if (CmsStringUtil.isEmpty(defaultWebAppName)) { defaultWebAppName = "ROOT"; } try { // first initialize runlevel 1 m_opencms = OpenCmsCore.getInstance(); // Externalization: get Locale: will be the System default since no CmsObject is up before // runlevel 2 Locale locale = getLocale(); m_messages = Messages.get().getBundle(locale); // search for the WEB-INF folder if (CmsStringUtil.isEmpty(webInfPath)) { out.println(m_messages.key(Messages.GUI_SHELL_NO_HOME_FOLDER_SPECIFIED_0)); out.println(); webInfPath = CmsFileUtil.searchWebInfFolder(System.getProperty("user.dir")); if (CmsStringUtil.isEmpty(webInfPath)) { err.println(m_messages.key(Messages.GUI_SHELL_HR_0)); err.println(m_messages.key(Messages.GUI_SHELL_NO_HOME_FOLDER_FOUND_0)); err.println(); err.println(m_messages.key(Messages.GUI_SHELL_START_DIR_LINE1_0)); err.println(m_messages.key(Messages.GUI_SHELL_START_DIR_LINE2_0)); err.println(m_messages.key(Messages.GUI_SHELL_HR_0)); return; } } out.println(Messages.get().getBundle(locale).key(Messages.GUI_SHELL_WEB_INF_PATH_1, webInfPath)); // set the path to the WEB-INF folder (the 2nd and 3rd parameters are just reasonable dummies) CmsServletContainerSettings settings = new CmsServletContainerSettings( webInfPath, defaultWebAppName, servletMapping, null, null); m_opencms.getSystemInfo().init(settings); // now read the configuration properties String propertyPath = m_opencms.getSystemInfo().getConfigurationFileRfsPath(); out.println(m_messages.key(Messages.GUI_SHELL_CONFIG_FILE_1, propertyPath)); out.println(); CmsParameterConfiguration configuration = new CmsParameterConfiguration(propertyPath); // now upgrade to runlevel 2 m_opencms = m_opencms.upgradeRunlevel(configuration); // create a context object with 'Guest' permissions m_cms = m_opencms.initCmsObject(m_opencms.getDefaultUsers().getUserGuest()); // initialize the shell initShell(additionalShellCommands, out, err); } catch (Exception e) { throw new RuntimeException("Error initializing CmsShell: " + e.getLocalizedMessage(), e); } } /** * Gets the top of thread-local shell stack, or null if it is empty. * * @return the top of the shell stack */ public static CmsShell getTopShell() { ArrayList shells = SHELL_STACK.get(); if (shells.isEmpty()) { return null; } return shells.get(shells.size() - 1); } /** * Check if JLAN should be disabled.

* * @return true if JLAN should be disabled */ public static boolean isJlanDisabled() { return JLAN_DISABLED; } /** * Main program entry point when started via the command line.

* * @param args parameters passed to the application via the command line */ public static void main(String[] args) { JLAN_DISABLED = true; boolean wrongUsage = false; String webInfPath = null; String script = null; String servletMapping = null; String defaultWebApp = null; String additionalCommandsNames = null; int errorCode = -1; if (args.length > 4) { wrongUsage = true; } else { for (int i = 0; i < args.length; i++) { String arg = args[i]; if (arg.startsWith(SHELL_PARAM_BASE)) { webInfPath = arg.substring(SHELL_PARAM_BASE.length()); } else if (arg.startsWith(SHELL_PARAM_SCRIPT)) { script = arg.substring(SHELL_PARAM_SCRIPT.length()); } else if (arg.startsWith(SHELL_PARAM_SERVLET_MAPPING)) { servletMapping = arg.substring(SHELL_PARAM_SERVLET_MAPPING.length()); } else if (arg.startsWith(SHELL_PARAM_DEFAULT_WEB_APP)) { defaultWebApp = arg.substring(SHELL_PARAM_DEFAULT_WEB_APP.length()); } else if (arg.startsWith(SHELL_PARAM_ADDITIONAL_COMMANDS)) { additionalCommandsNames = arg.substring(SHELL_PARAM_ADDITIONAL_COMMANDS.length()); } else if (arg.startsWith(SHELL_PARAM_ERROR_CODE)) { errorCode = Integer.valueOf(arg.substring(SHELL_PARAM_ERROR_CODE.length())).intValue(); } else if (arg.startsWith(SHELL_PARAM_JLAN)) { JLAN_DISABLED = false; } else { System.out.println(Messages.get().getBundle().key(Messages.GUI_SHELL_WRONG_USAGE_0)); wrongUsage = true; } } } if (wrongUsage) { System.out.println(Messages.get().getBundle().key(Messages.GUI_SHELL_USAGE_1, CmsShell.class.getName())); } else { List additionalCommands = new ArrayList<>(); if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(additionalCommandsNames)) { String[] classNames = additionalCommandsNames.split(","); for (String className : classNames) { try { className = className.trim(); Class commandClass = Class.forName(className); if (I_CmsShellCommands.class.isAssignableFrom(commandClass)) { additionalCommands.add( (I_CmsShellCommands)commandClass.getDeclaredConstructor().newInstance()); System.out.println( "Class " + className + " has been loaded and added to additional commands."); } else { // The class does not implement the required interface System.err.println( Messages.get().getBundle().key( Messages.GUI_SHELL_ERR_ADDITIONAL_COMMANDS_NOT_CMSSHELLCOMMANDS_1, className)); return; } } catch (ClassNotFoundException e) { System.out.println( Messages.get().getBundle().key( Messages.GUI_SHELL_ERR_ADDITIONAL_COMMANDS_CLASS_NOT_FOUND_1, className)); return; } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { System.out.println( Messages.get().getBundle().key( Messages.GUI_SHELL_ERR_ADDITIONAL_COMMANDS_DURING_INSTANTIATION_2, className, e.getLocalizedMessage())); return; } } } boolean interactive = true; FileInputStream stream = null; if (script != null) { try { stream = new FileInputStream(script); } catch (IOException exc) { System.out.println(Messages.get().getBundle().key(Messages.GUI_SHELL_ERR_SCRIPTFILE_1, script)); } } if (stream == null) { // no script-file, use standard input stream stream = new FileInputStream(FileDescriptor.in); interactive = true; } CmsShell shell = new CmsShell( webInfPath, servletMapping, defaultWebApp, "${user}@${project}:${siteroot}|${uri}>", additionalCommands, System.out, System.err, interactive); shell.m_errorCode = errorCode; shell.execute(stream); try { stream.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * Removes top of thread-local shell stack. */ public static void popShell() { ArrayList shells = SHELL_STACK.get(); if (shells.size() > 0) { shells.remove(shells.size() - 1); } } /** * Pushes shell instance on thread-local stack. * * @param shell the shell to push */ public static void pushShell(CmsShell shell) { SHELL_STACK.get().add(shell); } /** * If running in the context of a CmsShell, this method notifies the running shell instance that an error has occured in a report.

*/ public static void setReportError() { CmsShell instance = getTopShell(); if (instance != null) { instance.m_hasReportError = true; } } /** * Executes the commands from the given input stream in this shell.

* *

    *
  • Commands in the must be separated with a line break '\n'. *
  • Only one command per line is allowed. *
  • String parameters must be quoted like this: 'string value'. *
* * @param inputStream the input stream from which the commands are read */ public void execute(InputStream inputStream) { execute(new InputStreamReader(inputStream)); } /** * Executes the commands from the given reader in this shell.

* *

    *
  • Commands in the must be separated with a line break '\n'. *
  • Only one command per line is allowed. *
  • String parameters must be quoted like this: 'string value'. *
* * @param reader the reader from which the commands are read */ public void execute(Reader reader) { try { pushShell(this); LineNumberReader lnr = new LineNumberReader(reader); while (!m_exitCalled) { String line = lnr.readLine(); if (m_interactive || m_echo) { // print the prompt in front of the commands to process only when 'interactive' if ((line != null) | m_interactive) { printPrompt(); } } if (line == null) { // if null the file has been read to the end if (m_interactive) { try { Thread.sleep(500); } catch (Throwable t) { // noop } } // end the while loop break; } if (line.trim().startsWith("#")) { m_out.println(line); continue; } // In linux, the up and down arrows generate escape sequences that cannot be properly handled. // If a escape sequence is detected, OpenCms prints a warning message if (line.indexOf(KeyEvent.VK_ESCAPE) != -1) { m_out.println(m_messages.key(Messages.GUI_SHELL_ESCAPE_SEQUENCES_NOT_SUPPORTED_0)); continue; } StringReader lineReader = new StringReader(line); StreamTokenizer st = new StreamTokenizer(lineReader); st.eolIsSignificant(true); st.wordChars('*', '*'); // put all tokens into a List List parameters = new ArrayList(); while (st.nextToken() != StreamTokenizer.TT_EOF) { if (st.ttype == StreamTokenizer.TT_NUMBER) { parameters.add(Integer.toString(Double.valueOf(st.nval).intValue())); } else { if (null != st.sval) { parameters.add(st.sval); } } } lineReader.close(); if (parameters.size() == 0) { // empty line, just need to check if echo is on if (m_echo) { m_out.println(); } continue; } // extract command and arguments String command = parameters.get(0); List arguments = parameters.subList(1, parameters.size()); // execute the command with the given arguments executeCommand(command, arguments); } } catch (Throwable t) { if (!(t instanceof CmsShellCommandException)) { // in case it's a shell command exception, the stack trace has already been written t.printStackTrace(m_err); } if (m_errorCode != -1) { System.exit(m_errorCode); } } finally { popShell(); } } /** * Executes the commands from the given string in this shell.

* *

    *
  • Commands in the must be separated with a line break '\n'. *
  • Only one command per line is allowed. *
  • String parameters must be quoted like this: 'string value'. *
* * @param commands the string from which the commands are read */ public void execute(String commands) { execute(new StringReader(commands)); } /** * Executes a shell command with a list of parameters.

* * @param command the command to execute * @param parameters the list of parameters for the command */ public void executeCommand(String command, List parameters) { if (null == command) { return; } if (m_echo) { // echo the command to STDOUT m_out.print(command); boolean censorParams = Arrays.asList("login", "loginUser", "changePassword").contains(command); for (int i = 0; i < parameters.size(); i++) { m_out.print(" '"); m_out.print(censorParams ? "******" : parameters.get(i)); m_out.print("'"); } m_out.println(); } // prepare to lookup a method in CmsObject or CmsShellCommands boolean executed = false; Iterator i = m_commandObjects.iterator(); while (!executed && i.hasNext()) { CmsCommandObject cmdObj = i.next(); executed = cmdObj.executeMethod(command, parameters); } if (!executed) { // method not found m_out.println(); StringBuffer commandMsg = new StringBuffer(command).append("("); for (int j = 0; j < parameters.size(); j++) { commandMsg.append("value"); if (j < (parameters.size() - 1)) { commandMsg.append(", "); } } commandMsg.append(")"); m_out.println(m_messages.key(Messages.GUI_SHELL_METHOD_NOT_FOUND_1, commandMsg.toString())); m_out.println(m_messages.key(Messages.GUI_SHELL_HR_0)); ((CmsShellCommands)m_shellCommands).help(); } } /** * Exits this shell and destroys the OpenCms instance.

*/ public void exit() { if (m_exitCalled) { return; } m_exitCalled = true; try { if ((m_additionalShellCommands != null) && !m_additionalShellCommands.isEmpty()) { for (I_CmsShellCommands shellCommands : m_additionalShellCommands) { if (shellCommands != null) { shellCommands.shellExit(); } } } else if (null != m_shellCommands) { m_shellCommands.shellExit(); } } catch (Throwable t) { t.printStackTrace(); } if (m_opencms != null) { // if called by an in line script we don't want to kill the whole instance try { m_opencms.shutDown(); } catch (Throwable t) { t.printStackTrace(); } } } /** * Gets the benchmark table for the shell, lazily initializing it if it didn't exist yet. * * @return the benchmark table for the shell. */ public CmsBenchmarkTable getBenchmarkTable() { if (m_benchmarkTable == null) { m_benchmarkTable = new CmsBenchmarkTable(new CmsFileBenchmarkReceiver()); } return m_benchmarkTable; } /** * Returns the stream this shell writes its error messages to.

* * @return the stream this shell writes its error messages to */ public PrintStream getErr() { return m_err; } /** * Gets the error code.

* * @return the error code */ public int getErrorCode() { return m_errorCode; } /** * Private internal helper for localization to the current user's locale * within OpenCms.

* * @return the current user's Locale. */ public Locale getLocale() { if (getSettings() == null) { return CmsLocaleManager.getDefaultLocale(); } return getSettings().getLocale(); } /** * Returns the localized messages object for the current user.

* * @return the localized messages object for the current user */ public CmsMessages getMessages() { return m_messages; } /** * Returns the stream this shell writes its regular messages to.

* * @return the stream this shell writes its regular messages to */ public PrintStream getOut() { return m_out; } /** * Gets the prompt.

* * @return the prompt */ public String getPrompt() { String prompt = m_prompt; try { prompt = CmsStringUtil.substitute(prompt, "${user}", m_cms.getRequestContext().getCurrentUser().getName()); prompt = CmsStringUtil.substitute(prompt, "${siteroot}", m_cms.getRequestContext().getSiteRoot()); prompt = CmsStringUtil.substitute( prompt, "${project}", m_cms.getRequestContext().getCurrentProject().getName()); prompt = CmsStringUtil.substitute(prompt, "${uri}", m_cms.getRequestContext().getUri()); } catch (Throwable t) { // ignore } return prompt; } /** * Obtain the additional settings related to the current user. * * @return the additional settings related to the current user. */ public CmsUserSettings getSettings() { return m_settings; } /** * Returns true if echo mode is on.

* * @return true if echo mode is on */ public boolean hasEcho() { return m_echo; } /** * Checks whether a report error occurred during execution of the last command.

* * @return true if a report error occurred */ public boolean hasReportError() { return m_hasReportError; } /** * Initializes the CmsShell.

* * @param additionalShellCommands optional objects for additional shell commands, or null * @param out stream to write the regular output messages to * @param err stream to write the error messages output to */ public void initShell(List additionalShellCommands, PrintStream out, PrintStream err) { // set the output streams m_out = out; m_err = err; // initialize the settings of the user m_settings = initSettings(); // initialize shell command object m_shellCommands = new CmsShellCommands(); m_shellCommands.initShellCmsObject(m_cms, this); // initialize additional shell command object if ((additionalShellCommands != null) && !additionalShellCommands.isEmpty()) { m_additionalShellCommands = additionalShellCommands; for (I_CmsShellCommands shellCommands : additionalShellCommands) { if (shellCommands != null) { shellCommands.initShellCmsObject(m_cms, this); shellCommands.shellStart(); } } } else { m_shellCommands.shellStart(); } m_commandObjects = new ArrayList(); if ((m_additionalShellCommands != null) && !m_additionalShellCommands.isEmpty()) { for (I_CmsShellCommands shellCommands : m_additionalShellCommands) { if (shellCommands != null) { // get all shell callable methods from the additional shell command object m_commandObjects.add(new CmsCommandObject(shellCommands)); } } } // get all shell callable methods from the CmsShellCommands m_commandObjects.add(new CmsCommandObject(m_shellCommands)); // get all shell callable methods from the CmsRequestContext m_commandObjects.add(new CmsCommandObject(m_cms.getRequestContext())); // get all shell callable methods from the CmsObject m_commandObjects.add(new CmsCommandObject(m_cms)); } /** * Returns true if exit was called.

* * @return true if exit was called */ public boolean isExitCalled() { return m_exitCalled; } /** * If true this is an interactive session with a user sitting on a console.

* * @return true if this is an interactive session with a user sitting on a console */ public boolean isInteractive() { return m_interactive; } /** * Prints the shell prompt.

*/ public void printPrompt() { String prompt = getPrompt(); m_out.print(prompt); m_out.flush(); } /** * Set true if this is an interactive session with a user sitting on a console.

* * This controls the output of the prompt and some other info that is valuable * on the console, but not required in an automatic session.

* * @param interactive if true this is an interactive session with a user sitting on a console */ public void setInteractive(boolean interactive) { m_interactive = interactive; } /** * Sets the locale of the current user.

* * @param locale the locale to set * * @throws CmsException in case the locale of the current user can not be stored */ public void setLocale(Locale locale) throws CmsException { CmsUserSettings settings = getSettings(); if (settings != null) { settings.setLocale(locale); settings.save(m_cms); m_messages = Messages.get().getBundle(locale); } } /** * Reads the given stream and executes the commands in this shell.

* * @param inputStream an input stream from which commands are read * @deprecated use {@link #execute(InputStream)} instead */ @Deprecated public void start(FileInputStream inputStream) { setInteractive(true); execute(inputStream); } /** * Validates the given user and password and checks if the user has the requested role.

* * @param userName the user name * @param password the password * @param requiredRole the required role * * @return true if the user is valid */ public boolean validateUser(String userName, String password, CmsRole requiredRole) { boolean result = false; try { CmsUser user = m_cms.readUser(userName, password); result = OpenCms.getRoleManager().hasRole(m_cms, user.getName(), requiredRole); } catch (CmsException e) { // nothing to do } return result; } /** * Shows the signature of all methods containing the given search String.

* * @param searchString the String to search for in the methods, if null all methods are shown */ protected void help(String searchString) { String commandList; boolean foundSomething = false; m_out.println(); Iterator i = m_commandObjects.iterator(); while (i.hasNext()) { CmsCommandObject cmdObj = i.next(); commandList = cmdObj.getMethodHelp(searchString); if (!CmsStringUtil.isEmpty(commandList)) { m_out.println( m_messages.key(Messages.GUI_SHELL_AVAILABLE_METHODS_1, cmdObj.getObject().getClass().getName())); m_out.println(commandList); foundSomething = true; } } if (!foundSomething) { m_out.println(m_messages.key(Messages.GUI_SHELL_MATCH_SEARCHSTRING_1, searchString)); } } /** * Initializes the internal CmsWorkplaceSettings that contain (amongst other * information) important information additional information about the current user * (an instance of {@link CmsUserSettings}).

* * This step is performed within the CmsShell constructor directly after * switching to run-level 2 and obtaining the CmsObject for the guest user as * well as when invoking the CmsShell command login.

* * @return the user settings for the current user. */ protected CmsUserSettings initSettings() { m_settings = new CmsUserSettings(m_cms); return m_settings; } /** * Sets the echo status.

* * @param echo the echo status to set */ protected void setEcho(boolean echo) { m_echo = echo; } /** * Sets the current shell prompt.

* * To set the prompt, the following variables are available:

* * $u the current user name
* $s the current site root
* $p the current project name

* * @param prompt the prompt to set */ protected void setPrompt(String prompt) { m_prompt = prompt; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy