| /******************************************************************************* |
| * Copyright (c) 2005, 2011 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Alex Blewitt (bug 196071) |
| *******************************************************************************/ |
| package org.eclipse.equinox.internal.app; |
| |
| import java.util.*; |
| import java.util.Map.Entry; |
| import org.eclipse.equinox.app.IApplicationContext; |
| import org.eclipse.osgi.framework.console.CommandInterpreter; |
| import org.eclipse.osgi.framework.console.CommandProvider; |
| import org.osgi.framework.*; |
| import org.osgi.service.application.*; |
| import org.osgi.util.tracker.ServiceTracker; |
| |
| public class AppCommands implements CommandProvider { |
| private final static String LAUNCHABLE_APP_FILTER = "(&(application.locked=false)(application.launchable=true)(application.visible=true))"; //$NON-NLS-1$ |
| private final static String ACTIVE_APP_FILTER = "(!(application.state=STOPPING))"; //$NON-NLS-1$ |
| private final static String LOCKED_APP_FILTER = "(application.locked=true)"; //$NON-NLS-1$ |
| private final static String NEW_LINE = "\r\n"; //$NON-NLS-1$ |
| private final static String TAB = "\t"; //$NON-NLS-1$ |
| |
| // holds the mappings from command name to command arguments and command description |
| private Map commandsHelp = null; |
| |
| private static AppCommands instance; |
| private BundleContext context; |
| private ServiceTracker applicationDescriptors; |
| private ServiceTracker applicationHandles; |
| private ServiceTracker scheduledApplications; |
| private Filter launchableApp; |
| private Filter activeApp; |
| private Filter lockedApp; |
| private ServiceRegistration providerRegistration; |
| |
| static synchronized void create(BundleContext context) { |
| if (instance != null) |
| return; |
| instance = new AppCommands(); |
| instance.start(context); |
| } |
| |
| static synchronized void destroy(BundleContext context) { |
| if (instance == null) |
| return; |
| instance.stop(context); |
| instance = null; |
| } |
| |
| protected AppCommands() { |
| // empty |
| } |
| |
| public void start(BundleContext ctx) { |
| this.context = ctx; |
| try { |
| applicationDescriptors = new ServiceTracker(ctx, ApplicationDescriptor.class.getName(), null); |
| applicationDescriptors.open(); |
| applicationHandles = new ServiceTracker(ctx, ApplicationHandle.class.getName(), null); |
| applicationHandles.open(); |
| scheduledApplications = new ServiceTracker(ctx, ScheduledApplication.class.getName(), null); |
| scheduledApplications.open(); |
| launchableApp = ctx.createFilter(LAUNCHABLE_APP_FILTER); |
| activeApp = ctx.createFilter(ACTIVE_APP_FILTER); |
| lockedApp = ctx.createFilter(LOCKED_APP_FILTER); |
| providerRegistration = ctx.registerService(CommandProvider.class.getName(), this, null); |
| } catch (InvalidSyntaxException e) { |
| // should not happen. |
| } |
| } |
| |
| public void stop(BundleContext ctx) { |
| providerRegistration.unregister(); |
| if (applicationDescriptors != null) |
| applicationDescriptors.close(); |
| if (applicationHandles != null) |
| applicationHandles.close(); |
| if (scheduledApplications != null) |
| scheduledApplications.close(); |
| } |
| |
| public String getHelp() { |
| return getHelp(null); |
| } |
| |
| /* |
| * This method either returns the help message for a particular command, |
| * or returns the help messages for all commands (if commandName is null) |
| */ |
| private String getHelp(String commandName) { |
| StringBuffer sb = new StringBuffer(); |
| |
| if (commandsHelp == null) { |
| initializeCommandsHelp(); |
| } |
| |
| if (commandName != null) { |
| if (commandsHelp.containsKey(commandName)) { |
| addCommand(commandName, (String[]) commandsHelp.get(commandName), sb); |
| } |
| return sb.toString(); |
| } |
| |
| addHeader(Messages.console_help_app_commands_header, sb); |
| Iterator i = commandsHelp.entrySet().iterator(); |
| while (i.hasNext()) { |
| Entry entry = (Entry) i.next(); |
| String command = (String) entry.getKey(); |
| String[] attributes = (String[]) entry.getValue(); |
| addCommand(command, attributes, sb); |
| } |
| |
| return sb.toString(); |
| } |
| |
| private void initializeCommandsHelp() { |
| commandsHelp = new LinkedHashMap(); |
| commandsHelp.put("activeApps", new String[] {Messages.console_help_activeapps_description}); //$NON-NLS-1$ |
| commandsHelp.put("apps", new String[] {Messages.console_help_apps_description}); //$NON-NLS-1$ |
| commandsHelp.put("lockApp", new String[] {Messages.console_help_arguments, Messages.console_help_lockapp_description}); //$NON-NLS-1$ |
| commandsHelp.put("schedApp", new String[] {Messages.console_help_schedapp_arguments, Messages.console_help_schedapp_description}); //$NON-NLS-1$ |
| commandsHelp.put("startApp", new String[] {Messages.console_help_arguments, Messages.console_help_startapp_description}); //$NON-NLS-1$ |
| commandsHelp.put("stopApp", new String[] {Messages.console_help_arguments, Messages.console_help_stopapp_description}); //$NON-NLS-1$ |
| commandsHelp.put("unlockApp", new String[] {Messages.console_help_arguments, Messages.console_help_unlockapp_description}); //$NON-NLS-1$ |
| commandsHelp.put("unschedApp", new String[] {Messages.console_help_arguments, Messages.console_help_unschedapp_description}); //$NON-NLS-1$ |
| } |
| |
| /** Private helper method for getHelp. Formats the help headers. */ |
| private void addHeader(String header, StringBuffer help) { |
| help.append("---"); //$NON-NLS-1$ |
| help.append(header); |
| help.append("---"); //$NON-NLS-1$ |
| help.append(NEW_LINE); |
| } |
| |
| /** Private helper method for getHelp. Formats the command descriptions. */ |
| private void addCommand(String command, String description, StringBuffer help) { |
| help.append(TAB); |
| help.append(command); |
| help.append(" - "); //$NON-NLS-1$ |
| help.append(description); |
| help.append(NEW_LINE); |
| } |
| |
| /** Private helper method for getHelp. Formats the command descriptions with command arguments. */ |
| private void addCommand(String command, String parameters, String description, StringBuffer help) { |
| help.append(TAB); |
| help.append(command); |
| help.append(" "); //$NON-NLS-1$ |
| help.append(parameters); |
| help.append(" - "); //$NON-NLS-1$ |
| help.append(description); |
| help.append(NEW_LINE); |
| } |
| |
| /** Private helper method for getHelp. According to its arguments chooses which one of the above addCommand methods to use. */ |
| private void addCommand(String command, String[] attributes, StringBuffer help) { |
| if (attributes.length == 1) { |
| addCommand(command, attributes[0], help); |
| } else if (attributes.length == 2) { |
| addCommand(command, attributes[0], attributes[1], help); |
| } |
| } |
| |
| private Dictionary getServiceProps(ServiceReference ref) { |
| String[] keys = ref.getPropertyKeys(); |
| Hashtable props = new Hashtable(keys.length); |
| for (int i = 0; i < keys.length; i++) |
| props.put(keys[i], ref.getProperty(keys[i])); |
| return props; |
| } |
| |
| public void _apps(CommandInterpreter intp) { |
| ServiceReference[] apps = applicationDescriptors.getServiceReferences(); |
| if (apps == null) { |
| intp.println("No applications found."); //$NON-NLS-1$ |
| return; |
| } |
| for (int i = 0; i < apps.length; i++) { |
| String application = (String) apps[i].getProperty(ApplicationDescriptor.APPLICATION_PID); |
| intp.print(application); |
| |
| if (getApplication(applicationHandles.getServiceReferences(), application, ApplicationHandle.APPLICATION_DESCRIPTOR, true) != null) |
| intp.print(" [running]"); //$NON-NLS-1$ |
| |
| if (getApplication(scheduledApplications.getServiceReferences(), application, ScheduledApplication.APPLICATION_PID, true) != null) |
| intp.print(" [scheduled]"); //$NON-NLS-1$ |
| |
| if (!launchableApp.match(getServiceProps(apps[i]))) |
| intp.print(" [not launchable]"); //$NON-NLS-1$ |
| else |
| intp.print(" [launchable]"); //$NON-NLS-1$ |
| |
| if (lockedApp.match(getServiceProps(apps[i]))) |
| intp.print(" [locked]"); //$NON-NLS-1$ |
| intp.println(); |
| } |
| } |
| |
| public void _activeApps(CommandInterpreter intp) { |
| ServiceReference[] active = applicationHandles.getServiceReferences(); |
| if (active == null) { |
| intp.println("No active applications found"); //$NON-NLS-1$ |
| return; |
| } |
| for (int i = 0; i < active.length; i++) { |
| intp.print(active[i].getProperty(ApplicationHandle.APPLICATION_PID)); |
| intp.print(" ["); //$NON-NLS-1$ |
| intp.print(activeApp.match(getServiceProps(active[i])) ? "running" : "stopping"); //$NON-NLS-1$ //$NON-NLS-2$ |
| intp.println("]"); //$NON-NLS-1$ |
| } |
| } |
| |
| private ServiceReference getApplication(ServiceReference[] apps, String targetId, String idKey, boolean perfectMatch) { |
| if (apps == null || targetId == null) |
| return null; |
| |
| ServiceReference result = null; |
| boolean ambigous = false; |
| for (int i = 0; i < apps.length; i++) { |
| String id = (String) apps[i].getProperty(idKey); |
| if (targetId.equals(id)) |
| return apps[i]; // always return a perfect match |
| if (perfectMatch) |
| continue; |
| if (id.indexOf(targetId) >= 0) { |
| if (result != null) |
| ambigous = true; |
| result = apps[i]; |
| } |
| } |
| return ambigous ? null : result; |
| } |
| |
| public void _startApp(CommandInterpreter intp) throws Exception { |
| String appId = intp.nextArgument(); |
| ServiceReference application = getApplication(applicationDescriptors.getServiceReferences(), appId, ApplicationDescriptor.APPLICATION_PID, false); |
| if (application == null) |
| intp.println("\"" + appId + "\" does not exist or is ambigous."); //$NON-NLS-1$ //$NON-NLS-2$ |
| else { |
| ArrayList argList = new ArrayList(); |
| String arg = null; |
| while ((arg = intp.nextArgument()) != null) |
| argList.add(arg); |
| String[] args = argList.size() == 0 ? null : (String[]) argList.toArray(new String[argList.size()]); |
| try { |
| HashMap launchArgs = new HashMap(1); |
| if (args != null) |
| launchArgs.put(IApplicationContext.APPLICATION_ARGS, args); |
| ApplicationDescriptor appDesc = ((ApplicationDescriptor) context.getService(application)); |
| ApplicationHandle handle = appDesc.launch(launchArgs); |
| intp.println("Launched application instance: " + handle.getInstanceId()); //$NON-NLS-1$ |
| } finally { |
| context.ungetService(application); |
| } |
| return; |
| } |
| } |
| |
| public void _stopApp(CommandInterpreter intp) throws Exception { |
| String appId = intp.nextArgument(); |
| // first search for the application instance id |
| ServiceReference application = getApplication(applicationHandles.getServiceReferences(), appId, ApplicationHandle.APPLICATION_PID, false); |
| if (application == null) |
| application = getApplication(applicationHandles.getServiceReferences(), appId, ApplicationHandle.APPLICATION_DESCRIPTOR, false); |
| if (application == null) |
| intp.println("\"" + appId + "\" does not exist, is not running or is ambigous."); //$NON-NLS-1$ //$NON-NLS-2$ |
| else { |
| if (activeApp.match(getServiceProps(application))) { |
| try { |
| ApplicationHandle appHandle = (ApplicationHandle) context.getService(application); |
| appHandle.destroy(); |
| intp.println("Stopped application instance: " + appHandle.getInstanceId()); //$NON-NLS-1$ |
| } finally { |
| context.ungetService(application); |
| } |
| } else { |
| intp.println("Application instance is already stopping: " + application.getProperty(ApplicationHandle.APPLICATION_PID)); //$NON-NLS-1$ |
| } |
| return; |
| } |
| } |
| |
| public void _lockApp(CommandInterpreter intp) throws Exception { |
| String appId = intp.nextArgument(); |
| ServiceReference application = getApplication(applicationDescriptors.getServiceReferences(), appId, ApplicationDescriptor.APPLICATION_PID, false); |
| if (application == null) |
| intp.println("\"" + appId + "\" does not exist or is ambigous."); //$NON-NLS-1$ //$NON-NLS-2$ |
| else { |
| try { |
| ApplicationDescriptor appDesc = (ApplicationDescriptor) context.getService(application); |
| appDesc.lock(); |
| intp.println("Locked application: " + appDesc.getApplicationId()); //$NON-NLS-1$ |
| } finally { |
| context.ungetService(application); |
| } |
| return; |
| } |
| } |
| |
| public void _unlockApp(CommandInterpreter intp) throws Exception { |
| String appId = intp.nextArgument(); |
| ServiceReference application = getApplication(applicationDescriptors.getServiceReferences(), appId, ApplicationDescriptor.APPLICATION_PID, false); |
| if (application == null) |
| intp.println("\"" + appId + "\" does not exist or is ambigous."); //$NON-NLS-1$ //$NON-NLS-2$ |
| else { |
| try { |
| ApplicationDescriptor appDesc = (ApplicationDescriptor) context.getService(application); |
| appDesc.unlock(); |
| intp.println("Unlocked application: " + appDesc.getApplicationId()); //$NON-NLS-1$ |
| } finally { |
| context.ungetService(application); |
| } |
| return; |
| } |
| } |
| |
| public void _schedApp(CommandInterpreter intp) throws Exception { |
| String appId = intp.nextArgument(); |
| ServiceReference application = getApplication(applicationDescriptors.getServiceReferences(), appId, ApplicationDescriptor.APPLICATION_PID, false); |
| if (application == null) |
| intp.println("\"" + appId + "\" does not exist or is ambigous."); //$NON-NLS-1$ //$NON-NLS-2$ |
| else { |
| try { |
| ApplicationDescriptor appDesc = (ApplicationDescriptor) context.getService(application); |
| String filter = intp.nextArgument(); |
| boolean recure = Boolean.valueOf(intp.nextArgument()).booleanValue(); |
| appDesc.schedule(null, null, "org/osgi/application/timer", filter, recure); //$NON-NLS-1$ |
| intp.println("Scheduled application: " + appDesc.getApplicationId()); //$NON-NLS-1$ |
| } finally { |
| context.ungetService(application); |
| } |
| return; |
| } |
| } |
| |
| public void _unschedApp(CommandInterpreter intp) throws Exception { |
| String appId = intp.nextArgument(); |
| ServiceReference application = getApplication(scheduledApplications.getServiceReferences(), appId, ScheduledApplication.APPLICATION_PID, false); |
| if (application == null) |
| intp.println("\"" + appId + "\" does not exist or is ambigous."); //$NON-NLS-1$ //$NON-NLS-2$ |
| else { |
| try { |
| ScheduledApplication schedApp = (ScheduledApplication) context.getService(application); |
| schedApp.remove(); |
| intp.println("Unscheduled application: " + application.getProperty(ApplicationDescriptor.APPLICATION_PID)); //$NON-NLS-1$ |
| } finally { |
| context.ungetService(application); |
| } |
| } |
| } |
| |
| /** |
| * Handles the help command |
| * |
| * @param intp |
| * @return description for a particular command or false if there is no command with the specified name |
| */ |
| public Object _help(CommandInterpreter intp) { |
| String commandName = intp.nextArgument(); |
| if (commandName == null) { |
| return Boolean.FALSE; |
| } |
| String help = getHelp(commandName); |
| |
| if (help.length() > 0) { |
| return help; |
| } |
| return Boolean.FALSE; |
| } |
| } |