diff options
15 files changed, 570 insertions, 148 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml b/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml index bb30ec0..e6a5e82 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml +++ b/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml @@ -771,4 +771,16 @@ class="com.android.ide.eclipse.adt.AdbLocator"> </locator> </extension> + <extension + point="com.android.ide.eclipse.ddms.debuggerConnector"> + <connector + class="com.android.ide.eclipse.adt.DebuggerConnector"> + </connector> + </extension> + <extension + point="com.android.ide.eclipse.ddms.sourceRevealer"> + <revealer + class="com.android.ide.eclipse.adt.SourceRevealer"> + </revealer> + </extension> </plugin> diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdbLocator.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdbLocator.java index b45b192..9c87f26 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdbLocator.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdbLocator.java @@ -18,6 +18,10 @@ package com.android.ide.eclipse.adt; import com.android.ide.eclipse.ddms.IAdbLocator; +/** + * Implementation of the com.android.ide.ddms.adbLocator extension point. + * + */ public class AdbLocator implements IAdbLocator { public String getAdbLocation() { diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java index eee0bf1..c2088df 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java @@ -26,7 +26,6 @@ import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditor; import com.android.ide.eclipse.adt.internal.editors.menu.MenuEditor; import com.android.ide.eclipse.adt.internal.editors.resources.ResourcesEditor; import com.android.ide.eclipse.adt.internal.editors.xml.XmlEditor; -import com.android.ide.eclipse.adt.internal.launch.AndroidLaunchController; import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs.BuildVerbosity; import com.android.ide.eclipse.adt.internal.project.AndroidClasspathContainerInitializer; @@ -247,50 +246,6 @@ public class AdtPlugin extends AbstractUIPlugin { // check the location of SDK final boolean isSdkLocationValid = checkSdkLocationAndId(); - // and give it the debug launcher for android projects - DdmsPlugin.setRunningAppDebugLauncher(new DdmsPlugin.IDebugLauncher() { - public boolean debug(String appName, int port) { - // search for an android project matching the process name - IProject project = ProjectHelper.findAndroidProjectByAppName(appName); - if (project != null) { - AndroidLaunchController.debugRunningApp(project, port); - return true; - } else { - // check to see if there's a platform project defined by an env var. - String var = System.getenv("ANDROID_PLATFORM_PROJECT"); //$NON-NLS-1$ - if (var != null && var.length() > 0) { - boolean auto = "AUTO".equals(var); //$NON-NLS-1$ - - // Get the list of project for the current workspace - IWorkspace workspace = ResourcesPlugin.getWorkspace(); - IProject[] projects = workspace.getRoot().getProjects(); - - // look for a project that matches the env var or take the first - // one if in automatic mode. - for (IProject p : projects) { - if (p.isOpen()) { - if (auto || p.getName().equals(var)) { - AndroidLaunchController.debugRunningApp(p, port); - return true; - } - } - } - - } - return false; - } - } - }); - - StackTracePanel.setSourceRevealer(new ISourceRevealer() { - public void reveal(String applicationName, String className, int line) { - IProject project = ProjectHelper.findAndroidProjectByAppName(applicationName); - if (project != null) { - BaseProjectHelper.revealSource(project, className, line); - } - } - }); - // initialize editors startEditors(); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/DebuggerConnector.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/DebuggerConnector.java new file mode 100644 index 0000000..35da340 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/DebuggerConnector.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Eclipse Public License, Version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.eclipse.org/org/documents/epl-v10.php + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.ide.eclipse.adt; + +import com.android.ide.eclipse.adt.internal.launch.AndroidLaunchController; +import com.android.ide.eclipse.adt.internal.project.ProjectHelper; +import com.android.ide.eclipse.ddms.IDebuggerConnector; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; + +/** + * Implementation of the com.android.ide.ddms.debuggerConnector extension point. + */ +public class DebuggerConnector implements IDebuggerConnector { + + public boolean connectDebugger(String appName, int port) { + // search for an android project matching the process name + IProject project = ProjectHelper.findAndroidProjectByAppName(appName); + if (project != null) { + AndroidLaunchController.debugRunningApp(project, port); + return true; + } else { + // check to see if there's a platform project defined by an env var. + String var = System.getenv("ANDROID_PLATFORM_PROJECT"); //$NON-NLS-1$ + if (var != null && var.length() > 0) { + boolean auto = "AUTO".equals(var); //$NON-NLS-1$ + + // Get the list of project for the current workspace + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + IProject[] projects = workspace.getRoot().getProjects(); + + // look for a project that matches the env var or take the first + // one if in automatic mode. + for (IProject p : projects) { + if (p.isOpen()) { + if (auto || p.getName().equals(var)) { + AndroidLaunchController.debugRunningApp(p, port); + return true; + } + } + } + + } + return false; + } + } +} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/SourceRevealer.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/SourceRevealer.java new file mode 100644 index 0000000..2e2924c --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/SourceRevealer.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Eclipse Public License, Version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.eclipse.org/org/documents/epl-v10.php + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.ide.eclipse.adt; + +import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; +import com.android.ide.eclipse.adt.internal.project.ProjectHelper; +import com.android.ide.eclipse.ddms.ISourceRevealer; + +import org.eclipse.core.resources.IProject; + +/** + * Implementation of the com.android.ide.ddms.sourceRevealer extension point. + * + */ +public class SourceRevealer implements ISourceRevealer { + + public boolean reveal(String applicationName, String className, int line) { + IProject project = ProjectHelper.findAndroidProjectByAppName(applicationName); + if (project != null) { + return BaseProjectHelper.revealSource(project, className, line); + } + + return false; + } +} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/BaseProjectHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/BaseProjectHelper.java index 2eb5dd2..49a44d6 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/BaseProjectHelper.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/BaseProjectHelper.java @@ -305,10 +305,17 @@ public final class BaseProjectHelper { * @param project * @param className * @param line + * @return true if the source was revealed */ - public static void revealSource(IProject project, String className, int line) { - // in case the type is enclosed, we need to replace the $ with . - className = className.replaceAll("\\$", "\\."); //$NON-NLS-1$ //$NON-NLS2$ + public static boolean revealSource(IProject project, String className, int line) { + // Inner classes are pointless: All we need is the enclosing type to find the file, and the + // line number. + // Since the anonymous ones will cause IJavaProject#findType to fail, we remove + // all of them. + int pos = className.indexOf('$'); + if (pos != -1) { + className = className.substring(0, pos); + } // get the java project IJavaProject javaProject = JavaCore.create(project); @@ -342,11 +349,15 @@ public final class BaseProjectHelper { // select and reveal the line. textEditor.selectAndReveal(lineInfo.getOffset(), lineInfo.getLength()); } + + return true; } } catch (JavaModelException e) { } catch (PartInitException e) { } catch (BadLocationException e) { } + + return false; } /** diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/plugin.xml b/eclipse/plugins/com.android.ide.eclipse.ddms/plugin.xml index d0fe8af..4fe6786 100644 --- a/eclipse/plugins/com.android.ide.eclipse.ddms/plugin.xml +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/plugin.xml @@ -2,6 +2,9 @@ <?eclipse version="3.2"?> <plugin> <extension-point id="adbLocator" name="ADB Locator" schema="schema/adbLocator.exsd"/> + <extension-point id="debuggerConnector" name="Debugger Connector" schema="schema/debuggerConnector.exsd"/> + <extension-point id="sourceRevealer" name="Source Revealer" schema="schema/sourceRevealer.exsd"/> + <extension point="org.eclipse.ui.views"> <category diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/schema/adbLocator.exsd b/eclipse/plugins/com.android.ide.eclipse.ddms/schema/adbLocator.exsd index 6292ec1..e2c246c 100644 --- a/eclipse/plugins/com.android.ide.eclipse.ddms/schema/adbLocator.exsd +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/schema/adbLocator.exsd @@ -6,7 +6,7 @@ <meta.schema plugin="com.android.ide.eclipse.ddms" id="adbLocator" name="ADB Locator"/> </appInfo> <documentation> - Extension to provide the location of adb to DDMS. + Extension Point to provide the location of adb to DDMS. </documentation> </annotation> diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/schema/debuggerConnector.exsd b/eclipse/plugins/com.android.ide.eclipse.ddms/schema/debuggerConnector.exsd new file mode 100644 index 0000000..515713a --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/schema/debuggerConnector.exsd @@ -0,0 +1,104 @@ +<?xml version='1.0' encoding='UTF-8'?> +<!-- Schema file written by PDE --> +<schema targetNamespace="com.android.ide.eclipse.ddms" xmlns="http://www.w3.org/2001/XMLSchema"> +<annotation> + <appInfo> + <meta.schema plugin="com.android.ide.eclipse.ddms" id="debuggerConnector" name="Debugger Connector"/> + </appInfo> + <documentation> + Extension Point to provide a way to connect a debugger to a VM running on a connected device. + +The goal of the extension is to identify which project in the workspace matches the running application to properly setup a launch configuration. + </documentation> + </annotation> + + <element name="connector"> + <complexType> + <attribute name="class" type="string" use="required"> + <annotation> + <documentation> + + </documentation> + <appInfo> + <meta.attribute kind="java" basedOn=":com.android.ide.eclipse.ddms.IDebuggerConnector"/> + </appInfo> + </annotation> + </attribute> + </complexType> + </element> + + <element name="extension"> + <annotation> + <appInfo> + <meta.element /> + </appInfo> + </annotation> + <complexType> + <sequence> + <element ref="connector"/> + </sequence> + <attribute name="point" type="string" use="required"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="id" type="string"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="name" type="string"> + <annotation> + <documentation> + + </documentation> + <appInfo> + <meta.attribute translatable="true"/> + </appInfo> + </annotation> + </attribute> + </complexType> + </element> + + <annotation> + <appInfo> + <meta.section type="since"/> + </appInfo> + <documentation> + 8.0.0 + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="examples"/> + </appInfo> + <documentation> + [Enter extension point usage example here.] + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="apiinfo"/> + </appInfo> + <documentation> + The class must implement com.android.ide.ddms.IDebuggerConnector. + </documentation> + </annotation> + + + <annotation> + <appInfo> + <meta.section type="copyright"/> + </appInfo> + <documentation> + Copyright (C) 2010 The Android Open Source Project + </documentation> + </annotation> + +</schema> diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/schema/sourceRevealer.exsd b/eclipse/plugins/com.android.ide.eclipse.ddms/schema/sourceRevealer.exsd new file mode 100644 index 0000000..9f2cf9c --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/schema/sourceRevealer.exsd @@ -0,0 +1,96 @@ +<?xml version='1.0' encoding='UTF-8'?> +<!-- Schema file written by PDE --> +<schema targetNamespace="com.android.ide.eclipse.ddms" xmlns="http://www.w3.org/2001/XMLSchema"> +<annotation> + <appInfo> + <meta.schema plugin="com.android.ide.eclipse.ddms" id="sourceRevealer" name="Source Revealer"/> + </appInfo> + <documentation> + Extension Point to provide a way to display the source code of a VM running on a connected device. + +The goal of the extension is to identify which project in the workspace matches the running application to properly identify the source file to open. + </documentation> + </annotation> + + <element name="revealer"> + <complexType> + <attribute name="class" type="string" use="required"> + <annotation> + <documentation> + + </documentation> + <appInfo> + <meta.attribute kind="java" basedOn=":com.android.ide.eclipse.ddms.ISourceRevealer"/> + </appInfo> + </annotation> + </attribute> + </complexType> + </element> + + <element name="extension"> + <annotation> + <appInfo> + <meta.element /> + </appInfo> + </annotation> + <complexType> + <sequence> + <element ref="revealer"/> + </sequence> + <attribute name="point" type="string" use="required"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="id" type="string"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="name" type="string"> + <annotation> + <documentation> + + </documentation> + <appInfo> + <meta.attribute translatable="true"/> + </appInfo> + </annotation> + </attribute> + </complexType> + </element> + + <annotation> + <appInfo> + <meta.section type="since"/> + </appInfo> + <documentation> + 8.0.0 + </documentation> + </annotation> + + + <annotation> + <appInfo> + <meta.section type="apiinfo"/> + </appInfo> + <documentation> + The class must implement com.android.ide.ddms.ISourceRevealer. + </documentation> + </annotation> + + + <annotation> + <appInfo> + <meta.section type="copyright"/> + </appInfo> + <documentation> + Copyright (C) 2010 The Android Open Source Project + </documentation> + </annotation> + +</schema> diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/DdmsPlugin.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/DdmsPlugin.java index 3a99459..26ccbe8 100644 --- a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/DdmsPlugin.java +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/DdmsPlugin.java @@ -26,9 +26,9 @@ import com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener; import com.android.ddmlib.Log.ILogOutput; import com.android.ddmlib.Log.LogLevel; import com.android.ddmuilib.DdmUiPreferences; +import com.android.ddmuilib.StackTracePanel; import com.android.ddmuilib.DevicePanel.IUiSelectionListener; import com.android.ide.eclipse.ddms.preferences.PreferenceInitializer; -import com.android.ide.eclipse.ddms.views.DeviceView; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; @@ -63,7 +63,7 @@ import java.util.Calendar; * The activator class controls the plug-in life cycle */ public final class DdmsPlugin extends AbstractUIPlugin implements IDeviceChangeListener, - IUiSelectionListener { + IUiSelectionListener, com.android.ddmuilib.StackTracePanel.ISourceRevealer { // The plug-in ID @@ -77,10 +77,11 @@ public final class DdmsPlugin extends AbstractUIPlugin implements IDeviceChangeL private static String sToolsFolder; private static String sHprofConverter; - /** - * Debug Launcher for already running apps + /** debugger connectors for already running apps. + * Initialized from an extension point. */ - private static IDebugLauncher sRunningAppDebugLauncher; + private IDebuggerConnector[] mDebuggerConnectors; + private ISourceRevealer[] mSourceRevealers; /** Console for DDMS log message */ @@ -94,12 +95,6 @@ public final class DdmsPlugin extends AbstractUIPlugin implements IDeviceChangeL private Color mRed; - /** - * Interface to provide debugger launcher for running apps. - */ - public interface IDebugLauncher { - public boolean debug(String packageName, int port); - } /** * Classes which implement this interface provide methods that deals @@ -221,47 +216,136 @@ public final class DdmsPlugin extends AbstractUIPlugin implements IDeviceChangeL } }); - // start it in a thread to return from start() asap. - new Job("ADB location resolution") { + // do some last initializations + + // set the preferences. + PreferenceInitializer.setupPreferences(); + + // init the lib + AndroidDebugBridge.init(true /* debugger support */); + + // get the available adb locators + final IAdbLocator[] locators = findAdbLocators(); + + // Find the location of ADB. + // Because the running the locators will initialize their plug-in, we do this in a job + // to make sure that the init of the DDMS plug-in is finished. Otherwise, if another + // plug-in uses DDMS classes in their start() method, this would fail since DDMS would not + // be loaded yet. + // The job is scheduled at the end of the + Job adbLocatorJob = new Job("ADB Location resolution") { @Override protected IStatus run(IProgressMonitor monitor) { - // set the preferences. - PreferenceInitializer.setupPreferences(); - - // init the lib - AndroidDebugBridge.init(true /* debugger support */); - - // get the adb location from an implementation of the ADB Locator extension point. - IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); - IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint( - "com.android.ide.eclipse.ddms.adbLocator"); //$NON-NLS-1$ - IConfigurationElement[] configElements = extensionPoint.getConfigurationElements(); - if (configElements.length > 0) { - // only use the first one, ignore the others. - IConfigurationElement configElement = configElements[0]; - - // instantiate the clas - try { - Object obj = configElement.createExecutableExtension("class"); //$NON-NLS-1$ - if (obj instanceof IAdbLocator) { - String adbLocation = ((IAdbLocator) obj).getAdbLocation(); - if (adbLocation != null) { - if (setAdbLocation(adbLocation)) { - AndroidDebugBridge.createBridge(sAdbLocation, - true /* forceNewBridge */); - } + for (IAdbLocator locator : locators) { + String adbLocation = locator.getAdbLocation(); + if (adbLocation != null) { + // checks if the location is valid. + if (setAdbLocation(adbLocation)) { + AndroidDebugBridge.createBridge(sAdbLocation, + true /* forceNewBridge */); - } + // no need to look at the other locators. + break; } - } catch (CoreException e) { - return e.getStatus(); } } - return Status.OK_STATUS; } + }; + + // get the available debugger connectors + mDebuggerConnectors = findDebuggerConnectors(); + + // get the available source revealer + mSourceRevealers = findSourceRevealers(); + // this class is set as the main source revealer and will look at all the implementations + // of the extension point. see #reveal(String, String, int) + StackTracePanel.setSourceRevealer(this); + + // finish the method with the schedule of the adbLocator job since it must run after + // this method ends. + adbLocatorJob.schedule(); + } + + /** + * Finds if any other plug-in is extending the exposed Extension Point called adbLocator. + * + * @return an array of all locators found, or an empty array if none were found. + */ + private IAdbLocator[] findAdbLocators() throws CoreException { + ArrayList<IAdbLocator> list = new ArrayList<IAdbLocator>(); + + // get the adb location from an implementation of the ADB Locator extension point. + IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); + IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint( + "com.android.ide.eclipse.ddms.adbLocator"); //$NON-NLS-1$ + IConfigurationElement[] configElements = extensionPoint.getConfigurationElements(); + if (configElements.length > 0) { + // only use the first one, ignore the others. + IConfigurationElement configElement = configElements[0]; + + // instantiate the clas + Object obj = configElement.createExecutableExtension("class"); //$NON-NLS-1$ + if (obj instanceof IAdbLocator) { + list.add((IAdbLocator) obj); + } + } + + return list.toArray(new IAdbLocator[list.size()]); + } + + /** + * Finds if any other plug-in is extending the exposed Extension Point called debuggerConnector. + * + * @return an array of all locators found, or an empty array if none were found. + */ + private IDebuggerConnector[] findDebuggerConnectors() throws CoreException { + ArrayList<IDebuggerConnector> list = new ArrayList<IDebuggerConnector>(); + + // get the adb location from an implementation of the ADB Locator extension point. + IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); + IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint( + "com.android.ide.eclipse.ddms.debuggerConnector"); //$NON-NLS-1$ + IConfigurationElement[] configElements = extensionPoint.getConfigurationElements(); + if (configElements.length > 0) { + // only use the first one, ignore the others. + IConfigurationElement configElement = configElements[0]; + + // instantiate the clas + Object obj = configElement.createExecutableExtension("class"); //$NON-NLS-1$ + if (obj instanceof IDebuggerConnector) { + list.add((IDebuggerConnector) obj); + } + } + + return list.toArray(new IDebuggerConnector[list.size()]); + } + + /** + * Finds if any other plug-in is extending the exposed Extension Point called sourceRevealer. + * + * @return an array of all locators found, or an empty array if none were found. + */ + private ISourceRevealer[] findSourceRevealers() throws CoreException { + ArrayList<ISourceRevealer> list = new ArrayList<ISourceRevealer>(); + + // get the adb location from an implementation of the ADB Locator extension point. + IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); + IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint( + "com.android.ide.eclipse.ddms.sourceRevealer"); //$NON-NLS-1$ + IConfigurationElement[] configElements = extensionPoint.getConfigurationElements(); + if (configElements.length > 0) { + // only use the first one, ignore the others. + IConfigurationElement configElement = configElements[0]; + + // instantiate the clas + Object obj = configElement.createExecutableExtension("class"); //$NON-NLS-1$ + if (obj instanceof ISourceRevealer) { + list.add((ISourceRevealer) obj); + } + } - }.schedule(); + return list.toArray(new ISourceRevealer[list.size()]); } public static Display getDisplay() { @@ -357,31 +441,8 @@ public final class DdmsPlugin extends AbstractUIPlugin implements IDeviceChangeL } } - /** - * Sets the launcher responsible for connecting the debugger to running applications. - * @param launcher The launcher. - */ - public static void setRunningAppDebugLauncher(IDebugLauncher launcher) { - sRunningAppDebugLauncher = launcher; - - // if the process view is already running, give it the launcher. - // This method could be called from a non ui thread, so we make sure to do that - // in the ui thread. - Display display = getDisplay(); - if (display != null && display.isDisposed() == false) { - display.asyncExec(new Runnable() { - public void run() { - DeviceView dv = DeviceView.getInstance(); - if (dv != null) { - dv.setDebugLauncher(sRunningAppDebugLauncher); - } - } - }); - } - } - - public static IDebugLauncher getRunningAppDebugLauncher() { - return sRunningAppDebugLauncher; + public IDebuggerConnector[] getDebuggerConnectors() { + return mDebuggerConnectors; } public synchronized void addSelectionListener(ISelectionListener listener) { @@ -601,4 +662,16 @@ public final class DdmsPlugin extends AbstractUIPlugin implements IDeviceChangeL return String.format("[%1$tF %1$tT - %2$s]", c, tag); } + + /** + * Implementation of com.android.ddmuilib.StackTracePanel.ISourceRevealer. + */ + public void reveal(String applicationName, String className, int line) { + // loop on all source revealer till one succeeds + for (ISourceRevealer revealer : mSourceRevealers) { + if (revealer.reveal(applicationName, className, line)) { + break; + } + } + } } diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/IDebuggerConnector.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/IDebuggerConnector.java new file mode 100644 index 0000000..c50ba30 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/IDebuggerConnector.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.ide.eclipse.ddms; + +/** + * Classes which implement this interface provides a way to connect a debugger to a VM running + * on a connected device. + */ +public interface IDebuggerConnector { + + /** + * Connects a debugger to a VM identified by its appName. + * <p/> + * The given port is tied to the application and should be used if possible. However the + * "selected" port can also be used if needed. + * @param appName the name of the application. Usually the application's package but this + * can be different if the component was setup to run in it's own process. + * @param port the preferred connection port. + * @return true if success. + */ + boolean connectDebugger(String appName, int port); + +} diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/ISourceRevealer.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/ISourceRevealer.java new file mode 100644 index 0000000..18bed4c --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/ISourceRevealer.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.ide.eclipse.ddms; + +/** + * Classes which implement this interface are able to open a source file based on the name + * of a running Android application on a connected device. + */ +public interface ISourceRevealer { + + /** + * Sent to reveal a particular line in a source editor + * @param applicationName the name of the application running the source. + * @param className the fully qualified class name + * @param line the line to reveal + * @return true if the source was revealed. + */ + public boolean reveal(String applicationName, String className, int line); + +} diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/DeviceView.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/DeviceView.java index f7728f5..f2033de 100644 --- a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/DeviceView.java +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/DeviceView.java @@ -37,7 +37,7 @@ import com.android.ddmuilib.SyncProgressHelper.SyncRunnable; import com.android.ddmuilib.handler.BaseFileHandler; import com.android.ddmuilib.handler.MethodProfilingHandler; import com.android.ide.eclipse.ddms.DdmsPlugin; -import com.android.ide.eclipse.ddms.DdmsPlugin.IDebugLauncher; +import com.android.ide.eclipse.ddms.IDebuggerConnector; import com.android.ide.eclipse.ddms.preferences.PreferenceInitializer; import org.eclipse.core.filesystem.EFS; @@ -85,7 +85,7 @@ public class DeviceView extends ViewPart implements IUiSelectionListener, IClien private Action mDebugAction; private Action mHprofAction; private Action mTracingAction; - private IDebugLauncher mDebugLauncher; + private IDebuggerConnector[] mDebuggerConnectors; private ImageDescriptor mTracingStartImage; private ImageDescriptor mTracingStopImage; @@ -246,20 +246,6 @@ public class DeviceView extends ViewPart implements IUiSelectionListener, IClien return sThis; } - /** - * Sets the {@link IDebugLauncher}. - * @param debugLauncher - */ - public void setDebugLauncher(DdmsPlugin.IDebugLauncher debugLauncher) { - mDebugLauncher = debugLauncher; - if (mDebugAction != null && mDeviceList != null) { - Client currentClient = mDeviceList.getSelectedClient(); - if (currentClient != null) { - mDebugAction.setEnabled(true); - } - } - } - @Override public void createPartControl(Composite parent) { mParentShell = parent.getShell(); @@ -377,12 +363,12 @@ public class DeviceView extends ViewPart implements IUiSelectionListener, IClien mTracingAction.setImageDescriptor(mTracingStartImage); // check if there's already a debug launcher set up in the plugin class - mDebugLauncher = DdmsPlugin.getRunningAppDebugLauncher(); + mDebuggerConnectors = DdmsPlugin.getDefault().getDebuggerConnectors(); mDebugAction = new Action("Debug Process") { @Override public void run() { - if (mDebugLauncher != null) { + if (mDebuggerConnectors.length != 0) { Client currentClient = mDeviceList.getSelectedClient(); if (currentClient != null) { ClientData clientData = currentClient.getClientData(); @@ -408,18 +394,23 @@ public class DeviceView extends ViewPart implements IUiSelectionListener, IClien // get the name of the client String packageName = clientData.getClientDescription(); if (packageName != null) { - if (mDebugLauncher.debug(packageName, - currentClient.getDebuggerListenPort()) == false) { - // if we get to this point, then we failed to find a project - // that matched the application to debug - Display display = DdmsPlugin.getDisplay(); - Shell shell = display.getActiveShell(); - MessageDialog.openError(shell, "Process Debug", - String.format( - "No opened project found for %1$s. Debug session failed!", - packageName)); + // try all connectors till one returns true. + for (IDebuggerConnector connector : mDebuggerConnectors) { + if (connector.connectDebugger(packageName, + currentClient.getDebuggerListenPort())) { + return; + } } + + // if we get to this point, then we failed to find a project + // that matched the application to debug + Display display = DdmsPlugin.getDisplay(); + Shell shell = display.getActiveShell(); + MessageDialog.openError(shell, "Process Debug", + String.format( + "No opened project found for %1$s. Debug session failed!", + packageName)); } } } @@ -427,7 +418,7 @@ public class DeviceView extends ViewPart implements IUiSelectionListener, IClien }; mDebugAction.setToolTipText("Debug the selected process, provided its source project is present and opened in the workspace."); mDebugAction.setImageDescriptor(loader.loadDescriptor("debug-attach.png")); //$NON-NLS-1$ - if (mDebugLauncher == null) { + if (mDebuggerConnectors.length == 0) { mDebugAction.setEnabled(false); } @@ -462,7 +453,7 @@ public class DeviceView extends ViewPart implements IUiSelectionListener, IClien selectedClient.setAsSelectedClient(); } - mDebugAction.setEnabled(mDebugLauncher != null); + mDebugAction.setEnabled(mDebuggerConnectors.length != 0); mKillAppAction.setEnabled(true); mGcAction.setEnabled(true); diff --git a/testapps/basicProject/res/layout/main.xml b/testapps/basicProject/res/layout/main.xml index b79cddb..783e4a0 100644 --- a/testapps/basicProject/res/layout/main.xml +++ b/testapps/basicProject/res/layout/main.xml @@ -7,7 +7,7 @@ <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" - android:text="Hello World, Main" + android:text="Basic Project" /> </LinearLayout> |