diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-11 12:11:54 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-11 12:11:54 -0700 |
commit | 45aacc49a96e083eb68cda88ed0f7e262b7254d1 (patch) | |
tree | cda6eb191928e6e7332ef036e9c8bd7c2c234e67 /eclipse/plugins | |
parent | 67dc23a61d888ba1b39fe6ed23d9f4d1a3df80ee (diff) | |
download | sdk-45aacc49a96e083eb68cda88ed0f7e262b7254d1.zip sdk-45aacc49a96e083eb68cda88ed0f7e262b7254d1.tar.gz sdk-45aacc49a96e083eb68cda88ed0f7e262b7254d1.tar.bz2 |
auto import from //branches/cupcake/...@137873
Diffstat (limited to 'eclipse/plugins')
24 files changed, 615 insertions, 517 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml b/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml index 4dfcc07..f86f5b2 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml +++ b/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml @@ -474,15 +474,6 @@ label="Android Wizards" visible="true"> <action - class="com.android.ide.eclipse.adt.wizards.actions.NewProjectAction" - icon="icons/new_adt_project.png" - id="com.android.ide.eclipse.adt.wizards.actions.NewProjectAction" - label="New Android Project" - style="push" - toolbarPath="android_project" - tooltip="Opens a wizard to help create a new Android project"> - </action> - <action class="com.android.ide.eclipse.adt.wizards.actions.NewXmlFileAction" icon="icons/new_xml.png" id="com.android.ide.eclipse.adt.wizards.actions.NewXmlFileAction" @@ -491,6 +482,15 @@ toolbarPath="android_project" tooltip="Opens a wizard to help create a new Android XML file"> </action> + <action + class="com.android.ide.eclipse.adt.wizards.actions.NewProjectAction" + icon="icons/new_adt_project.png" + id="com.android.ide.eclipse.adt.wizards.actions.NewProjectAction" + label="New Android Project" + style="push" + toolbarPath="android_project" + tooltip="Opens a wizard to help create a new Android project"> + </action> </actionSet> </extension> <extension diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java index fb1608c..c508283 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java @@ -21,7 +21,6 @@ import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.project.FixLaunchConfig; import com.android.ide.eclipse.adt.sdk.Sdk; import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.common.project.AndroidManifestHelper; import com.android.ide.eclipse.common.project.AndroidManifestParser; import com.android.ide.eclipse.common.project.BaseProjectHelper; import com.android.ide.eclipse.common.project.XmlErrorHandler.BasicXmlErrorListener; @@ -272,7 +271,7 @@ public class PreCompilerBuilder extends BaseBuilder { // get the manifest file - IFile manifest = AndroidManifestHelper.getManifest(project); + IFile manifest = AndroidManifestParser.getManifest(project); if (manifest == null) { String msg = String.format(Messages.s_File_Missing, @@ -743,7 +742,7 @@ public class PreCompilerBuilder extends BaseBuilder { // create it if needed if (destinationFolder.exists() == false && createFolders) { destinationFolder.create(true /*force*/, true /*local*/, - new SubProgressMonitor(monitor, 10));; + new SubProgressMonitor(monitor, 10)); } // Build the Java file name from the aidl name. @@ -824,7 +823,7 @@ public class PreCompilerBuilder extends BaseBuilder { /** * Scans a folder and fills the list of aidl files to compile. * @param sourceFolder the root source folder. - * @param container The folder to scan. + * @param folder The folder to scan. */ private void scanFolderForAidl(IFolder sourceFolder, IFolder folder) { try { diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java index 0255f9f..035aa5b 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java @@ -176,6 +176,7 @@ public class ResourceManagerBuilder extends BaseBuilder { "Creating 'gen' source folder for generated Java files"); genFolder.create(true /* force */, true /* local */, new SubProgressMonitor(monitor, 10)); + genFolder.setDerived(true); } // add it to the source folder list, if needed only (or it will throw) diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchController.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchController.java index 9c5f09b..111d6b3 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchController.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchController.java @@ -31,7 +31,7 @@ import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.launch.DeviceChooserDialog.DeviceChooserResponse; import com.android.ide.eclipse.adt.project.ProjectHelper; import com.android.ide.eclipse.adt.sdk.Sdk; -import com.android.ide.eclipse.common.project.AndroidManifestHelper; +import com.android.ide.eclipse.common.project.AndroidManifestParser; import com.android.sdklib.IAndroidTarget; import com.android.sdklib.SdkManager; import com.android.sdklib.avd.AvdManager; @@ -584,8 +584,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener ArrayList<IResource> array = new ArrayList<IResource>(2); array.add(project); - AndroidManifestHelper helper = new AndroidManifestHelper(project); - IFile manifest = helper.getManifestIFile(); + IFile manifest = AndroidManifestParser.getManifest(project); if (manifest != null) { array.add(manifest); } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DeviceChooserDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DeviceChooserDialog.java index 275addf..a960bda 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DeviceChooserDialog.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DeviceChooserDialog.java @@ -36,12 +36,8 @@ import com.android.sdkuilib.AvdSelector; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.jface.viewers.DoubleClickEvent; -import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ILabelProviderListener; -import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; @@ -62,6 +58,12 @@ import org.eclipse.swt.widgets.Table; import java.util.ArrayList; +/** + * A dialog that lets the user choose a device to deploy an application. + * The user can either choose an exiting running device (including running emulators) + * or start a new emulator using an Android Virtual Device configuration that matches + * the current project. + */ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener { private final static int ICON_WIDTH = 16; @@ -373,15 +375,27 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener mViewer.setContentProvider(new ContentProvider()); mViewer.setLabelProvider(new LabelProvider()); mViewer.setInput(AndroidDebugBridge.getBridge()); - mViewer.addDoubleClickListener(new IDoubleClickListener() { - public void doubleClick(DoubleClickEvent event) { - ISelection selection = event.getSelection(); - if (selection instanceof IStructuredSelection) { - IStructuredSelection structuredSelection = (IStructuredSelection)selection; - Object object = structuredSelection.getFirstElement(); - if (object instanceof Device) { - mResponse.setDeviceToUse((Device)object); - } + + mDeviceTable.addSelectionListener(new SelectionAdapter() { + /** + * Handles single-click selection on the device selector. + * {@inheritDoc} + */ + @Override + public void widgetSelected(SelectionEvent e) { + handleDeviceSelection(); + } + + /** + * Handles double-click selection on the device selector. + * Note that the single-click handler will probably already have been called. + * {@inheritDoc} + */ + @Override + public void widgetDefaultSelected(SelectionEvent e) { + handleDeviceSelection(); + if (isOkButtonEnabled()) { + okPressed(); } } }); @@ -397,18 +411,14 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener layout.marginLeft = 30; offsetComp.setLayout(layout); - mPreferredAvdSelector = new AvdSelector(offsetComp, getNonRunningAvds(), mProjectTarget, - false /*allowMultipleSelection*/); + mPreferredAvdSelector = new AvdSelector(offsetComp, getNonRunningAvds(), mProjectTarget); mPreferredAvdSelector.setTableHeightHint(100); mPreferredAvdSelector.setEnabled(false); - mDeviceTable.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - handleDeviceSelection(); - } - }); - mPreferredAvdSelector.setSelectionListener(new SelectionAdapter() { + /** + * Handles single-click selection on the AVD selector. + * {@inheritDoc} + */ @Override public void widgetSelected(SelectionEvent e) { if (mDisableAvdSelectionChange == false) { @@ -416,6 +426,22 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener enableOkButton(); } } + + /** + * Handles double-click selection on the AVD selector. + * + * Note that the single-click handler will probably already have been called + * but the selected item can have changed in between. + * + * {@inheritDoc} + */ + @Override + public void widgetDefaultSelected(SelectionEvent e) { + widgetSelected(e); + if (isOkButtonEnabled()) { + okPressed(); + } + } }); AndroidDebugBridge.addDeviceChangeListener(this); @@ -586,6 +612,14 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener okButton.setEnabled(mResponse.getAvdToLaunch() != null); } } + + /** + * Returns true if the ok button is enabled. + */ + private boolean isOkButtonEnabled() { + Button okButton = getButton(IDialogConstants.OK_ID); + return okButton.isEnabled(); + } /** * Executes the {@link Runnable} in the UI thread. diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/EmulatorConfigTab.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/EmulatorConfigTab.java index 5b4cdbb..b898f63 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/EmulatorConfigTab.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/EmulatorConfigTab.java @@ -178,8 +178,7 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab { mPreferredAvdLabel = new Label(offsetComp, SWT.NONE); mPreferredAvdLabel.setText("Select a preferred Android Virtual Device:"); AvdInfo[] avds = new AvdInfo[0]; - mPreferredAvdSelector = new AvdSelector(offsetComp, avds, - false /*allowMultipleSelection*/); + mPreferredAvdSelector = new AvdSelector(offsetComp, avds); mPreferredAvdSelector.setTableHeightHint(100); mPreferredAvdSelector.setSelectionListener(new SelectionAdapter() { @Override diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ProjectHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ProjectHelper.java index b1f8ffc..fd0c045 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ProjectHelper.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ProjectHelper.java @@ -19,9 +19,9 @@ package com.android.ide.eclipse.adt.project; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.project.internal.AndroidClasspathContainerInitializer; import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.common.project.AndroidManifestHelper; import com.android.ide.eclipse.common.project.AndroidManifestParser; +import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; @@ -389,18 +389,16 @@ public final class ProjectHelper { continue; } - AndroidManifestHelper androidManifest = new AndroidManifestHelper(p); - // check that there is indeed a manifest file. - if (androidManifest.getManifestIFile() == null) { + IFile manifestFile = AndroidManifestParser.getManifest(p); + if (manifestFile == null) { // no file? skip this project. continue; } AndroidManifestParser parser = null; try { - parser = AndroidManifestParser.parseForData( - androidManifest.getManifestIFile()); + parser = AndroidManifestParser.parseForData(manifestFile); } catch (CoreException e) { // skip this project. continue; diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetData.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetData.java index a8852e7..34391c2 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetData.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetData.java @@ -44,7 +44,7 @@ public class AndroidTargetData { public final static int DESCRIPTOR_RESOURCES = 5; public final static int DESCRIPTOR_SEARCHABLE = 6; public final static int DESCRIPTOR_PREFERENCES = 7; - public final static int DESCRIPTOR_GADGET_PROVIDER = 8; + public final static int DESCRIPTOR_APPWIDGET_PROVIDER = 8; public final static class LayoutBridge { /** Link to the layout bridge */ @@ -158,8 +158,8 @@ public class AndroidTargetData { return ResourcesDescriptors.getInstance(); case DESCRIPTOR_PREFERENCES: return mXmlDescriptors.getPreferencesProvider(); - case DESCRIPTOR_GADGET_PROVIDER: - return mXmlDescriptors.getGadgetProvider(); + case DESCRIPTOR_APPWIDGET_PROVIDER: + return mXmlDescriptors.getAppWidgetProvider(); case DESCRIPTOR_SEARCHABLE: return mXmlDescriptors.getSearchableProvider(); default : diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetParser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetParser.java index 04baeba..67eec78 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetParser.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetParser.java @@ -203,9 +203,9 @@ public final class AndroidTargetParser { attrsManifestXmlParser); Map<String, Map<String, Integer>> enumValueMap = attrsXmlParser.getEnumFlagValues(); - Map<String, DeclareStyleableInfo> xmlGadgetMap = null; + Map<String, DeclareStyleableInfo> xmlAppWidgetMap = null; if (mAndroidTarget.getApiVersionNumber() >= 3) { - xmlGadgetMap = collectGadgetDefinitions(attrsXmlParser); + xmlAppWidgetMap = collectAppWidgetDefinitions(attrsXmlParser); } if (progress.isCanceled()) { @@ -241,7 +241,7 @@ public final class AndroidTargetParser { XmlDescriptors xmlDescriptors = new XmlDescriptors(); xmlDescriptors.updateDescriptors( xmlSearchableMap, - xmlGadgetMap, + xmlAppWidgetMap, preferencesInfo, preferenceGroupsInfo); progress.worked(1); @@ -611,23 +611,23 @@ public final class AndroidTargetParser { } /** - * Collects all gadgetProviderInfo definition information from the attrs.xml and returns it. + * Collects all appWidgetProviderInfo definition information from the attrs.xml and returns it. * * @param attrsXmlParser The parser of the attrs.xml file */ - private Map<String, DeclareStyleableInfo> collectGadgetDefinitions( + private Map<String, DeclareStyleableInfo> collectAppWidgetDefinitions( AttrsXmlParser attrsXmlParser) { Map<String, DeclareStyleableInfo> map = attrsXmlParser.getDeclareStyleableList(); Map<String, DeclareStyleableInfo> map2 = new HashMap<String, DeclareStyleableInfo>(); - for (String key : new String[] { "GadgetProviderInfo" }) { //$NON-NLS-1$ + for (String key : new String[] { "AppWidgetProviderInfo" }) { //$NON-NLS-1$ if (map.containsKey(key)) { map2.put(key, map.get(key)); } else { AdtPlugin.log(IStatus.WARNING, - "Gadget declare-styleable %1$s not found in file %2$s", //$NON-NLS-1$ + "AppWidget declare-styleable %1$s not found in file %2$s", //$NON-NLS-1$ key, attrsXmlParser.getOsAttrsXmlPath()); AdtPlugin.printErrorToConsole("Android Framework Parser", - String.format("Gadget declare-styleable %1$s not found in file %2$s", //$NON-NLS-1$ + String.format("AppWidget declare-styleable %1$s not found in file %2$s", //$NON-NLS-1$ key, attrsXmlParser.getOsAttrsXmlPath())); } } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectCreationPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectCreationPage.java index 33ec2bc..6c4f4ba 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectCreationPage.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectCreationPage.java @@ -24,7 +24,7 @@ package com.android.ide.eclipse.adt.wizards.newproject; import com.android.ide.eclipse.adt.sdk.Sdk; import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.common.project.AndroidManifestHelper; +import com.android.ide.eclipse.common.project.AndroidManifestParser; import com.android.sdklib.IAndroidTarget; import com.android.sdklib.SdkConstants; import com.android.sdklib.project.ProjectProperties; @@ -36,6 +36,7 @@ import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; @@ -821,26 +822,41 @@ public class NewProjectCreationPage extends WizardPage { Path path = new Path(f.getPath()); String osPath = path.append(AndroidConstants.FN_ANDROID_MANIFEST).toOSString(); - AndroidManifestHelper manifest = new AndroidManifestHelper(osPath); - if (!manifest.exists()) { + + AndroidManifestParser manifestData = null; + try { + manifestData = AndroidManifestParser.parseForData(osPath); + } catch (CoreException e1) { + // ignore any parsing issue + } + if (manifestData == null) { return; } String packageName = null; String activityName = null; - String minSdkVersion = null; + int minSdkVersion = 0; // 0 means no minSdkVersion provided in the manifest try { - packageName = manifest.getPackageName(); - activityName = manifest.getActivityName(1); - minSdkVersion = manifest.getMinSdkVersion(); + packageName = manifestData.getPackage(); + minSdkVersion = manifestData.getApiLevelRequirement(); + + // try to get the first launcher activity. If none, just take the first activity. + activityName = manifestData.getLauncherActivity(); + if (activityName == null) { + String[] activities = manifestData.getActivities(); + if (activities != null && activities.length > 0) { + activityName = activities[0]; + } + } } catch (Exception e) { // ignore exceptions } - if (packageName != null && packageName.length() > 0) { mPackageNameField.setText(packageName); } + + activityName = AndroidManifestParser.extractActivityName(activityName, packageName); if (activityName != null && activityName.length() > 0) { mInternalActivityNameUpdate = true; @@ -917,12 +933,10 @@ public class NewProjectCreationPage extends WizardPage { } } - if (!foundTarget && minSdkVersion != null) { + if (!foundTarget && minSdkVersion > 0) { try { - int sdkVersion = Integer.parseInt(minSdkVersion); - for (IAndroidTarget target : mSdkTargetSelector.getTargets()) { - if (target.getApiVersionNumber() == sdkVersion) { + if (target.getApiVersionNumber() == minSdkVersion) { mSdkTargetSelector.setSelection(target); foundTarget = true; break; @@ -945,7 +959,8 @@ public class NewProjectCreationPage extends WizardPage { if (!foundTarget) { mInternalMinSdkVersionUpdate = true; - mMinSdkVersionField.setText(minSdkVersion == null ? "" : minSdkVersion); //$NON-NLS-1$ + mMinSdkVersionField.setText( + minSdkVersion <= 0 ? "" : Integer.toString(minSdkVersion)); //$NON-NLS-1$ mInternalMinSdkVersionUpdate = false; } } @@ -1072,8 +1087,8 @@ public class NewProjectCreationPage extends WizardPage { // Check there's an android manifest in the directory String osPath = path.append(AndroidConstants.FN_ANDROID_MANIFEST).toOSString(); - AndroidManifestHelper manifest = new AndroidManifestHelper(osPath); - if (!manifest.exists()) { + File manifestFile = new File(osPath); + if (!manifestFile.isFile()) { return setStatus( String.format("File %1$s not found in %2$s.", AndroidConstants.FN_ANDROID_MANIFEST, f.getName()), @@ -1081,15 +1096,24 @@ public class NewProjectCreationPage extends WizardPage { } // Parse it and check the important fields. - String packageName = manifest.getPackageName(); + AndroidManifestParser manifestData; + try { + manifestData = AndroidManifestParser.parseForData(osPath); + } catch (CoreException e) { + return setStatus( + String.format("File %1$s could not be parsed.", osPath), + MSG_ERROR); + } + + String packageName = manifestData.getPackage(); if (packageName == null || packageName.length() == 0) { return setStatus( String.format("No package name defined in %1$s.", osPath), MSG_ERROR); } - String activityName = manifest.getActivityName(1); - if (activityName == null || activityName.length() == 0) { + String[] activities = manifestData.getActivities(); + if (activities == null || activities.length == 0) { // This is acceptable now as long as no activity needs to be created if (isCreateActivity()) { return setStatus( @@ -1097,7 +1121,7 @@ public class NewProjectCreationPage extends WizardPage { MSG_ERROR); } } - + // If there's already a .project, tell the user to use import instead. if (path.append(".project").toFile().exists()) { //$NON-NLS-1$ return setStatus("An Eclipse project already exists in this directory. Consider using File > Import > Existing Project instead.", diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestHelper.java deleted file mode 100644 index cd238d2..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestHelper.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright (C) 2007 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.common.project; - -import com.android.ide.eclipse.common.AndroidConstants; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; -import org.xml.sax.InputSource; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; - -import javax.xml.xpath.XPath; -import javax.xml.xpath.XPathExpressionException; - -/** - * Utility class that manages the AndroidManifest.xml file. - * <p/> - * All the get method work by XPath. Repeated calls to those may warrant using - * {@link AndroidManifestParser} instead. - */ -public class AndroidManifestHelper { - private IFile mManifestIFile; - private File mManifestFile; - private XPath mXPath; - - /** - * Creates an AndroidManifest based on an existing Eclipse {@link IProject} object. - * </p> - * Use {@link #exists()} to check if the manifest file really exists in the project. - * - * @param project The project to search for the manifest. - */ - public AndroidManifestHelper(IProject project) { - mXPath = AndroidXPathFactory.newXPath(); - mManifestIFile = getManifest(project); - } - - /** - * Creates an AndroidManifest based on a file path. - * <p/> - * Use {@link #exists()} to check if the manifest file really exists. - * - * @param osManifestFilePath the os path to the AndroidManifest.xml file. - */ - public AndroidManifestHelper(String osManifestFilePath) { - mXPath = AndroidXPathFactory.newXPath(); - mManifestFile = new File(osManifestFilePath); - } - - - /** - * Returns the underlying {@link IFile} for the android manifest XML file, if found in the - * given Eclipse project. - * - * Always return null if the constructor that takes an {@link IProject} was NOT called. - * - * @return The IFile for the androidManifest.xml or null if no such file could be found. - */ - public IFile getManifestIFile() { - return mManifestIFile; - } - - /** - * Returns the underlying {@link File} for the android manifest XML file. - */ - public File getManifestFile() { - if (mManifestIFile != null) { - return mManifestIFile.getLocation().toFile(); - } - - return mManifestFile; - } - - /** - * Returns the package name defined in the manifest file. - * - * @return A String object with the package or null if any error happened. - */ - public String getPackageName() { - try { - return mXPath.evaluate("/manifest/@package", getSource()); //$NON-NLS-1$ - } catch (XPathExpressionException e1) { - // If the XPath failed to evaluate, we'll return null. - } catch (Exception e) { - // if this happens this is due to the resource being out of sync. - // so we must refresh it and do it again - - // for any other kind of exception we must return null as well; - } - - return null; - } - - /** - * Returns the minSdkVersion defined in the manifest file. - * - * @return A String object with the package or null if any error happened. - */ - public String getMinSdkVersion() { - try { - return mXPath.evaluate("/manifest/uses-sdk/@" //$NON-NLS-1$ - + AndroidXPathFactory.DEFAULT_NS_PREFIX - + ":minSdkVersion", getSource()); //$NON-NLS-1$ - } catch (XPathExpressionException e1) { - // If the XPath failed to evaluate, we'll return null. - } catch (Exception e) { - // if this happens this is due to the resource being out of sync. - // so we must refresh it and do it again - - // for any other kind of exception we must return null as well; - } - - return null; - } - /** - * Returns the i-th activity defined in the manifest file. - * - * @param index The 1-based index of the activity to return. - * @return A String object with the activity or null if any error happened. - */ - public String getActivityName(int index) { - try { - return mXPath.evaluate("/manifest/application/activity[" //$NON-NLS-1$ - + index - + "]/@" //$NON-NLS-1$ - + AndroidXPathFactory.DEFAULT_NS_PREFIX +":name", //$NON-NLS-1$ - getSource()); - } catch (XPathExpressionException e1) { - // If the XPath failed to evaluate, we'll return null. - } catch (Exception e) { - // if this happens this is due to the resource being out of sync. - // so we must refresh it and do it again - - // for any other kind of exception we must return null as well; - } - return null; - } - - /** - * Returns an IFile object representing the manifest for the specified - * project. - * - * @param project The project containing the manifest file. - * @return An IFile object pointing to the manifest or null if the manifest - * is missing. - */ - public static IFile getManifest(IProject project) { - IResource r = project.findMember(AndroidConstants.WS_SEP - + AndroidConstants.FN_ANDROID_MANIFEST); - - if (r == null || r.exists() == false || (r instanceof IFile) == false) { - return null; - } - return (IFile) r; - } - - /** - * Combines a java package, with a class value from the manifest to make a fully qualified - * class name - * @param javaPackage the java package from the manifest. - * @param className the class name from the manifest. - * @return the fully qualified class name. - */ - public static String combinePackageAndClassName(String javaPackage, String className) { - if (className == null || className.length() == 0) { - return javaPackage; - } - if (javaPackage == null || javaPackage.length() == 0) { - return className; - } - - // the class name can be a subpackage (starts with a '.' - // char), a simple class name (no dot), or a full java package - boolean startWithDot = (className.charAt(0) == '.'); - boolean hasDot = (className.indexOf('.') != -1); - if (startWithDot || hasDot == false) { - - // add the concatenation of the package and class name - if (startWithDot) { - return javaPackage + className; - } else { - return javaPackage + '.' + className; - } - } else { - // just add the class as it should be a fully qualified java name. - return className; - } - } - - - - /** - * Returns true either if an androidManifest.xml file was found in the project - * or if the given file path exists. - */ - public boolean exists() { - if (mManifestIFile != null) { - return mManifestIFile.exists(); - } else if (mManifestFile != null) { - return mManifestFile.exists(); - } - - return false; - } - - /** - * Returns an InputSource for XPath. - * - * @throws FileNotFoundException if file does not exist. - * @throws CoreException if the {@link IFile} does not exist. - */ - private InputSource getSource() throws FileNotFoundException, CoreException { - if (mManifestIFile != null) { - return new InputSource(mManifestIFile.getContents()); - } else if (mManifestFile != null) { - return new InputSource(new FileReader(mManifestFile)); - } - - return null; - } - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java index 850c59d..b2817ff 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java @@ -22,6 +22,8 @@ import com.android.sdklib.SdkConstants; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.IJavaProject; import org.xml.sax.Attributes; @@ -30,6 +32,8 @@ import org.xml.sax.Locator; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; +import java.io.File; +import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.Set; @@ -56,6 +60,8 @@ public class AndroidManifestParser { private final static String NODE_ACTION = "action"; //$NON-NLS-1$ private final static String NODE_CATEGORY = "category"; //$NON-NLS-1$ private final static String NODE_USES_SDK = "uses-sdk"; //$NON-NLS-1$ + private final static String NODE_INSTRUMENTATION = "instrumentation"; //$NON-NLS-1$ + private final static String NODE_USES_LIBRARY = "uses-library"; //$NON-NLS-1$ private final static int LEVEL_MANIFEST = 0; private final static int LEVEL_APPLICATION = 1; @@ -66,6 +72,12 @@ public class AndroidManifestParser { private final static String ACTION_MAIN = "android.intent.action.MAIN"; //$NON-NLS-1$ private final static String CATEGORY_LAUNCHER = "android.intent.category.LAUNCHER"; //$NON-NLS-1$ + /** + * XML error & data handler used when parsing the AndroidManifest.xml file. + * <p/> + * This serves both as an {@link XmlErrorHandler} to report errors and as a data repository + * to collect data from the manifest. + */ private static class ManifestHandler extends XmlErrorHandler { //--- data read from the parsing @@ -82,6 +94,10 @@ public class AndroidManifestParser { private Boolean mDebuggable = null; /** API level requirement. if 0 the attribute was not present. */ private int mApiLevelRequirement = 0; + /** List of all instrumentations declared by the manifest */ + private final ArrayList<String> mInstrumentations = new ArrayList<String>(); + /** List of all libraries in use declared by the manifest */ + private final ArrayList<String> mLibraries = new ArrayList<String>(); //--- temporary data/flags used during parsing private IJavaProject mJavaProject; @@ -95,12 +111,13 @@ public class AndroidManifestParser { private Locator mLocator; /** - * - * @param manifestFile - * @param errorListener - * @param gatherData - * @param javaProject - * @param markErrors + * Creates a new {@link ManifestHandler}, which is also an {@link XmlErrorHandler}. + * + * @param manifestFile The manifest file being parsed. Can be null. + * @param errorListener An optional error listener. + * @param gatherData True if data should be gathered. + * @param javaProject The java project holding the manifest file. Can be null. + * @param markErrors True if errors should be marked as Eclipse Markers on the resource. */ ManifestHandler(IFile manifestFile, XmlErrorListener errorListener, boolean gatherData, IJavaProject javaProject, boolean markErrors) { @@ -160,6 +177,23 @@ public class AndroidManifestParser { return mApiLevelRequirement; } + /** + * Returns the list of instrumentations found in the manifest. + * @return An array of instrumentation names, or empty if no instrumentations were + * found. + */ + String[] getInstrumentations() { + return mInstrumentations.toArray(new String[mInstrumentations.size()]); + } + + /** + * Returns the list of libraries in use found in the manifest. + * @return An array of library names, or empty if no libraries were found. + */ + String[] getUsesLibraries() { + return mLibraries.toArray(new String[mLibraries.size()]); + } + /* (non-Javadoc) * @see org.xml.sax.helpers.DefaultHandler#setDocumentLocator(org.xml.sax.Locator) */ @@ -217,7 +251,13 @@ public class AndroidManifestParser { } catch (NumberFormatException e) { handleError(e, -1 /* lineNumber */); } - } + } else if (NODE_INSTRUMENTATION.equals(localName)) { + value = getAttributeValue(attributes, ATTRIBUTE_NAME, + true /* hasNamespace */); + if (value != null) { + mInstrumentations.add(value); + } + } break; case LEVEL_ACTIVITY: if (NODE_ACTIVITY.equals(localName)) { @@ -232,7 +272,13 @@ public class AndroidManifestParser { } else if (NODE_PROVIDER.equals(localName)) { processNode(attributes, AndroidConstants.CLASS_CONTENTPROVIDER); mValidLevel++; - } + } else if (NODE_USES_LIBRARY.equals(localName)) { + value = getAttributeValue(attributes, ATTRIBUTE_NAME, + true /* hasNamespace */); + if (value != null) { + mLibraries.add(value); + } + } break; case LEVEL_INTENT_FILTER: // only process this level if we are in an activity @@ -355,8 +401,7 @@ public class AndroidManifestParser { String activityName = getAttributeValue(attributes, ATTRIBUTE_NAME, true /* hasNamespace */); if (activityName != null) { - mCurrentActivity = AndroidManifestHelper.combinePackageAndClassName(mPackage, - activityName); + mCurrentActivity = combinePackageAndClassName(mPackage, activityName); mActivities.add(mCurrentActivity); if (mMarkErrors) { @@ -387,8 +432,7 @@ public class AndroidManifestParser { String serviceName = getAttributeValue(attributes, ATTRIBUTE_NAME, true /* hasNamespace */); if (serviceName != null) { - serviceName = AndroidManifestHelper.combinePackageAndClassName(mPackage, - serviceName); + serviceName = combinePackageAndClassName(mPackage, serviceName); if (mMarkErrors) { checkClass(serviceName, superClassName, false /* testVisibility */); @@ -412,6 +456,9 @@ public class AndroidManifestParser { * the class or of its constructors. */ private void checkClass(String className, String superClassName, boolean testVisibility) { + if (mJavaProject == null) { + return; + } // we need to check the validity of the activity. String result = BaseProjectHelper.testClassForManifest(mJavaProject, className, superClassName, testVisibility); @@ -477,6 +524,8 @@ public class AndroidManifestParser { private final String[] mProcesses; private final Boolean mDebuggable; private final int mApiLevelRequirement; + private final String[] mInstrumentations; + private final String[] mLibraries; static { sParserFactory = SAXParserFactory.newInstance(); @@ -484,8 +533,12 @@ public class AndroidManifestParser { } /** - * Parses the Android Manifest, and returns an object containing - * the result of the parsing. + * Parses the Android Manifest, and returns an object containing the result of the parsing. + * <p/> + * This method is useful to parse a specific {@link IFile} in a Java project. + * <p/> + * If you only want to gather data, consider {@link #parseForData(IFile)} instead. + * * @param javaProject The java project. * @param manifestFile the {@link IFile} representing the manifest file. * @param errorListener @@ -496,8 +549,12 @@ public class AndroidManifestParser { * @return an {@link AndroidManifestParser} or null if the parsing failed. * @throws CoreException */ - public static AndroidManifestParser parse(IJavaProject javaProject, IFile manifestFile, - XmlErrorListener errorListener, boolean gatherData, boolean markErrors) + public static AndroidManifestParser parse( + IJavaProject javaProject, + IFile manifestFile, + XmlErrorListener errorListener, + boolean gatherData, + boolean markErrors) throws CoreException { try { SAXParser parser = sParserFactory.newSAXParser(); @@ -512,7 +569,51 @@ public class AndroidManifestParser { return new AndroidManifestParser(manifestHandler.getPackage(), manifestHandler.getActivities(), manifestHandler.getLauncherActivity(), manifestHandler.getProcesses(), manifestHandler.getDebuggable(), - manifestHandler.getApiLevelRequirement()); + manifestHandler.getApiLevelRequirement(), manifestHandler.getInstrumentations(), + manifestHandler.getUsesLibraries()); + } catch (ParserConfigurationException e) { + } catch (SAXException e) { + } catch (IOException e) { + } finally { + } + + return null; + } + + /** + * Parses the Android Manifest, and returns an object containing the result of the parsing. + * <p/> + * This version parses a real {@link File} file given by an actual path, which is useful for + * parsing a file that is not part of an Eclipse Java project. + * <p/> + * It assumes errors cannot be marked on the file and that data gathering is enabled. + * + * @param manifestFile the manifest file to parse. + * @return an {@link AndroidManifestParser} or null if the parsing failed. + * @throws CoreException + */ + private static AndroidManifestParser parse(File manifestFile) + throws CoreException { + try { + SAXParser parser = sParserFactory.newSAXParser(); + + ManifestHandler manifestHandler = new ManifestHandler( + null, //manifestFile + null, //errorListener + true, //gatherData + null, //javaProject + false //markErrors + ); + + parser.parse(new InputSource(new FileReader(manifestFile)), manifestHandler); + + // get the result from the handler + + return new AndroidManifestParser(manifestHandler.getPackage(), + manifestHandler.getActivities(), manifestHandler.getLauncherActivity(), + manifestHandler.getProcesses(), manifestHandler.getDebuggable(), + manifestHandler.getApiLevelRequirement(), manifestHandler.getInstrumentations(), + manifestHandler.getUsesLibraries()); } catch (ParserConfigurationException e) { } catch (SAXException e) { } catch (IOException e) { @@ -535,13 +636,16 @@ public class AndroidManifestParser { * @return an {@link AndroidManifestParser} or null if the parsing failed. * @throws CoreException */ - public static AndroidManifestParser parse(IJavaProject javaProject, - XmlErrorListener errorListener, boolean gatherData, boolean markErrors) + public static AndroidManifestParser parse( + IJavaProject javaProject, + XmlErrorListener errorListener, + boolean gatherData, + boolean markErrors) throws CoreException { try { SAXParser parser = sParserFactory.newSAXParser(); - IFile manifestFile = AndroidManifestHelper.getManifest(javaProject.getProject()); + IFile manifestFile = getManifest(javaProject.getProject()); if (manifestFile != null) { ManifestHandler manifestHandler = new ManifestHandler(manifestFile, errorListener, gatherData, javaProject, markErrors); @@ -552,7 +656,8 @@ public class AndroidManifestParser { return new AndroidManifestParser(manifestHandler.getPackage(), manifestHandler.getActivities(), manifestHandler.getLauncherActivity(), manifestHandler.getProcesses(), manifestHandler.getDebuggable(), - manifestHandler.getApiLevelRequirement()); + manifestHandler.getApiLevelRequirement(), + manifestHandler.getInstrumentations(), manifestHandler.getUsesLibraries()); } } catch (ParserConfigurationException e) { } catch (SAXException e) { @@ -589,6 +694,18 @@ public class AndroidManifestParser { } /** + * Parses the manifest file, and collects data. + * + * @param osManifestFilePath The OS path of the manifest file to parse. + * @return an {@link AndroidManifestParser} or null if the parsing failed. + * @throws CoreException + */ + public static AndroidManifestParser parseForData(String osManifestFilePath) + throws CoreException { + return parse(new File(osManifestFilePath)); + } + + /** * Returns the package defined in the manifest, if found. * @return The package name or null if not found. */ @@ -633,6 +750,22 @@ public class AndroidManifestParser { public int getApiLevelRequirement() { return mApiLevelRequirement; } + + /** + * Returns the list of instrumentations found in the manifest. + * @return An array of fully qualified class names, or empty if no instrumentations were found. + */ + public String[] getInstrumentations() { + return mInstrumentations; + } + + /** + * Returns the list of libraries in use found in the manifest. + * @return An array of library names, or empty if no uses-library declarations were found. + */ + public String[] getUsesLibraries() { + return mLibraries; + } /** @@ -647,15 +780,92 @@ public class AndroidManifestParser { * @param processes the list of custom processes declared in the manifest. * @param debuggable the debuggable attribute, or null if not set. * @param apiLevelRequirement the minSdkVersion attribute value or 0 if not set. + * @param instrumentations the list of instrumentations parsed from the manifest. + * @param libraries the list of libraries in use parsed from the manifest. */ private AndroidManifestParser(String javaPackage, String[] activities, String launcherActivity, String[] processes, Boolean debuggable, - int apiLevelRequirement) { + int apiLevelRequirement, String[] instrumentations, String[] libraries) { mJavaPackage = javaPackage; mActivities = activities; mLauncherActivity = launcherActivity; mProcesses = processes; mDebuggable = debuggable; mApiLevelRequirement = apiLevelRequirement; + mInstrumentations = instrumentations; + mLibraries = libraries; + } + + /** + * Returns an IFile object representing the manifest for the specified + * project. + * + * @param project The project containing the manifest file. + * @return An IFile object pointing to the manifest or null if the manifest + * is missing. + */ + public static IFile getManifest(IProject project) { + IResource r = project.findMember(AndroidConstants.WS_SEP + + AndroidConstants.FN_ANDROID_MANIFEST); + + if (r == null || r.exists() == false || (r instanceof IFile) == false) { + return null; + } + return (IFile) r; + } + + /** + * Combines a java package, with a class value from the manifest to make a fully qualified + * class name + * @param javaPackage the java package from the manifest. + * @param className the class name from the manifest. + * @return the fully qualified class name. + */ + public static String combinePackageAndClassName(String javaPackage, String className) { + if (className == null || className.length() == 0) { + return javaPackage; + } + if (javaPackage == null || javaPackage.length() == 0) { + return className; + } + + // the class name can be a subpackage (starts with a '.' + // char), a simple class name (no dot), or a full java package + boolean startWithDot = (className.charAt(0) == '.'); + boolean hasDot = (className.indexOf('.') != -1); + if (startWithDot || hasDot == false) { + + // add the concatenation of the package and class name + if (startWithDot) { + return javaPackage + className; + } else { + return javaPackage + '.' + className; + } + } else { + // just add the class as it should be a fully qualified java name. + return className; + } + } + + /** + * Given a fully qualified activity name (e.g. com.foo.test.MyClass) and given a project + * package base name (e.g. com.foo), returns the relative activity name that would be used + * the "name" attribute of an "activity" element. + * + * @param fullActivityName a fully qualified activity class name, e.g. "com.foo.test.MyClass" + * @param packageName The project base package name, e.g. "com.foo" + * @return The relative activity name if it can be computed or the original fullActivityName. + */ + public static String extractActivityName(String fullActivityName, String packageName) { + if (packageName != null && fullActivityName != null) { + if (packageName.length() > 0 && fullActivityName.startsWith(packageName)) { + String name = fullActivityName.substring(packageName.length()); + if (name.length() > 0 && name.charAt(0) == '.') { + return name; + } + } + } + + return fullActivityName; } } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/XmlErrorHandler.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/XmlErrorHandler.java index fda55c4..1810ad2 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/XmlErrorHandler.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/XmlErrorHandler.java @@ -86,8 +86,13 @@ public class XmlErrorHandler extends DefaultHandler { */ @Override public void warning(SAXParseException exception) throws SAXException { - BaseProjectHelper.addMarker(mFile, AndroidConstants.MARKER_XML, exception.getMessage(), - exception.getLineNumber(), IMarker.SEVERITY_WARNING); + if (mFile != null) { + BaseProjectHelper.addMarker(mFile, + AndroidConstants.MARKER_XML, + exception.getMessage(), + exception.getLineNumber(), + IMarker.SEVERITY_WARNING); + } } protected final IFile getFile() { @@ -104,12 +109,19 @@ public class XmlErrorHandler extends DefaultHandler { mErrorListener.errorFound(); } - if (lineNumber != -1) { - BaseProjectHelper.addMarker(mFile, AndroidConstants.MARKER_XML, exception.getMessage(), - lineNumber, IMarker.SEVERITY_ERROR); - } else { - BaseProjectHelper.addMarker(mFile, AndroidConstants.MARKER_XML, exception.getMessage(), - IMarker.SEVERITY_ERROR); + if (mFile != null) { + if (lineNumber != -1) { + BaseProjectHelper.addMarker(mFile, + AndroidConstants.MARKER_XML, + exception.getMessage(), + lineNumber, + IMarker.SEVERITY_ERROR); + } else { + BaseProjectHelper.addMarker(mFile, + AndroidConstants.MARKER_XML, + exception.getMessage(), + IMarker.SEVERITY_ERROR); + } } } } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidContentAssist.java index 332ce6f..0d0883e 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidContentAssist.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidContentAssist.java @@ -442,11 +442,15 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor { tooltip = ((TextAttributeDescriptor) choice).getTooltip(); } + // Get the namespace URI for the attribute. Note that some attributes + // do not have a namespace and thus return null here. String nsUri = ((AttributeDescriptor)choice).getNamespaceUri(); - nsPrefix = nsUriMap.get(nsUri); - if (nsPrefix == null) { - nsPrefix = lookupNamespacePrefix(currentNode, nsUri); - nsUriMap.put(nsUri, nsPrefix); + if (nsUri != null) { + nsPrefix = nsUriMap.get(nsUri); + if (nsPrefix == null) { + nsPrefix = lookupNamespacePrefix(currentNode, nsUri); + nsUriMap.put(nsUri, nsPrefix); + } } if (nsPrefix != null) { nsPrefix += ":"; //$NON-NLS-1$ diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java index 81fd2ed..94ad87a 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java @@ -18,12 +18,14 @@ package com.android.ide.eclipse.editors.layout; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.common.project.AndroidManifestHelper; +import com.android.ide.eclipse.common.project.AndroidManifestParser; import com.android.ide.eclipse.editors.resources.manager.ProjectClassLoader; import com.android.ide.eclipse.editors.resources.manager.ProjectResources; import com.android.layoutlib.api.IProjectCallback; +import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; import java.lang.reflect.Constructor; import java.util.HashMap; @@ -83,17 +85,20 @@ public final class ProjectCallback implements IProjectCallback { } /** - * {@inheritDoc} - * * Returns the namespace for the project. The namespace contains a standard part + the * application package. + * + * @return The package namespace of the project or null in case of error. */ public String getNamespace() { if (mNamespace == null) { - AndroidManifestHelper manifest = new AndroidManifestHelper(mProject); - String javaPackage = manifest.getPackageName(); - - mNamespace = String.format(AndroidConstants.NS_CUSTOM_RESOURCES, javaPackage); + IFile manifestFile = AndroidManifestParser.getManifest(mProject); + try { + AndroidManifestParser data = AndroidManifestParser.parseForData(manifestFile); + String javaPackage = data.getPackage(); + mNamespace = String.format(AndroidConstants.NS_CUSTOM_RESOURCES, javaPackage); + } catch (CoreException e) { + } } return mNamespace; diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java index 7caa50f..c3f4dd8 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java @@ -17,6 +17,8 @@ package com.android.ide.eclipse.editors.layout.descriptors; import com.android.ide.eclipse.common.AndroidConstants; +import com.android.ide.eclipse.common.resources.DeclareStyleableInfo; +import com.android.ide.eclipse.common.resources.ResourceType; import com.android.ide.eclipse.common.resources.ViewClassInfo; import com.android.ide.eclipse.common.resources.DeclareStyleableInfo.AttributeInfo; import com.android.ide.eclipse.common.resources.ViewClassInfo.LayoutParamsInfo; @@ -25,6 +27,7 @@ import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils; import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor; import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider; +import com.android.ide.eclipse.editors.descriptors.ReferenceAttributeDescriptor; import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor; import com.android.sdklib.SdkConstants; @@ -131,8 +134,23 @@ public final class LayoutDescriptors implements IDescriptorProvider { String xml_name = info.getShortClassName(); String tooltip = info.getJavaDoc(); - // Process all View attributes ArrayList<AttributeDescriptor> attributes = new ArrayList<AttributeDescriptor>(); + + // All views and groups have an implicit "style" attribute which is a reference. + AttributeInfo styleInfo = new DeclareStyleableInfo.AttributeInfo( + "style", //$NON-NLS-1$ xmlLocalName + new DeclareStyleableInfo.AttributeInfo.Format[] { + DeclareStyleableInfo.AttributeInfo.Format.REFERENCE + }); + styleInfo.setJavaDoc("A reference to a custom style"); //tooltip + DescriptorsUtils.appendAttribute(attributes, + "style", //$NON-NLS-1$ + null, //nsUri + styleInfo, + false, //required + null); // overrides + + // Process all View attributes DescriptorsUtils.appendAttributes(attributes, null, // elementName SdkConstants.NS_RESOURCES, @@ -155,7 +173,7 @@ public final class LayoutDescriptors implements IDescriptorProvider { null /* overrides */); } } - + // Process all LayoutParams attributes ArrayList<AttributeDescriptor> layoutAttributes = new ArrayList<AttributeDescriptor>(); LayoutParamsInfo layoutParams = info.getLayoutData(); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java index f886080..e32be86 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java @@ -17,7 +17,7 @@ package com.android.ide.eclipse.editors.manifest.model; import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.common.project.AndroidManifestHelper; +import com.android.ide.eclipse.common.project.AndroidManifestParser; import com.android.ide.eclipse.common.project.BaseProjectHelper; import com.android.ide.eclipse.editors.AndroidEditor; import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; @@ -251,8 +251,8 @@ public class UiClassAttributeNode extends UiTextAttributeNode { String javaPackage = getManifestPackage(); // build the fully qualified name of the class - String className = AndroidManifestHelper.combinePackageAndClassName(javaPackage, - textValue); + String className = AndroidManifestParser.combinePackageAndClassName( + javaPackage, textValue); // only test the vilibility for activities. boolean testVisibility = AndroidConstants.CLASS_ACTIVITY.equals( diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java index 455c825..fa09305 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java @@ -18,7 +18,7 @@ package com.android.ide.eclipse.editors.resources.manager; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.common.project.AndroidManifestHelper; +import com.android.ide.eclipse.common.project.AndroidManifestParser; import com.android.ide.eclipse.common.resources.ResourceType; import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IFileListener; import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IProjectListener; @@ -28,6 +28,7 @@ import org.eclipse.core.resources.IMarkerDelta; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; import java.lang.reflect.Field; import java.lang.reflect.Modifier; @@ -120,7 +121,14 @@ public final class CompiledResourcesMonitor implements IFileListener, IProjectLi if (projectResources != null) { // create the classname String className = getRClassName(project); - + if (className == null) { + // We need to abort. + AdtPlugin.log(IStatus.ERROR, + "loadAndParseRClass: failed to find manifest package for project %1$s", //$NON-NLS-1$ + project.getName()); + return; + } + // create a temporary class loader to load it. ProjectClassLoader loader = new ProjectClassLoader(null /* parentClassLoader */, project); @@ -199,13 +207,28 @@ public final class CompiledResourcesMonitor implements IFileListener, IProjectLi } return false; } - + + /** + * Returns the class name of the R class, based on the project's manifest's package. + * + * @return A class name (e.g. "my.app.R") or null if there's no valid package in the manifest. + */ private String getRClassName(IProject project) { - // create the classname - AndroidManifestHelper manifest = new AndroidManifestHelper(project); - String javaPackage = manifest.getPackageName(); - - return javaPackage + ".R"; //$NON-NLS-1$ + try { + IFile manifestFile = AndroidManifestParser.getManifest(project); + AndroidManifestParser data = AndroidManifestParser.parseForData(manifestFile); + String javaPackage = data.getPackage(); + return javaPackage + ".R"; //$NON-NLS-1$ + } catch (CoreException e) { + // This will typically happen either because the manifest file is not present + // and/or the workspace needs to be refreshed. + AdtPlugin.logAndPrintError(e, + "Android Resources", + "Failed to find the package of the AndroidManifest of project %1$s. Reason: %2$s", + project.getName(), + e.getMessage()); + return null; + } } } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java index 5781938..e84c051 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java @@ -222,10 +222,10 @@ class NewXmlFileCreationPage extends WizardPage { null, // default attributes 1 // target API level ), - new TypeInfo("Gadget Provider", // UI name - "An XML file that describes a gadget provider.", // tooltip + new TypeInfo("AppWidget Provider", // UI name + "An XML file that describes a widget provider.", // tooltip ResourceFolderType.XML, // folder type - AndroidTargetData.DESCRIPTOR_GADGET_PROVIDER, // root seed + AndroidTargetData.DESCRIPTOR_APPWIDGET_PROVIDER, // root seed null, // default root SdkConstants.NS_RESOURCES, // xmlns null, // default attributes @@ -1109,7 +1109,7 @@ class NewXmlFileCreationPage extends WizardPage { TypeInfo type = getSelectedType(); if (type.getTargetApiLevel() > currentApiLevel) { - error = "The API level of the selected type (e.g. gadget, etc.) is not " + + error = "The API level of the selected type (e.g. AppWidget, etc.) is not " + "compatible with the API level of the project."; } } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java index 7929b5a..144b7ac 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java @@ -53,8 +53,8 @@ public final class XmlDescriptors implements IDescriptorProvider { /** The root document descriptor for preferences. */ private DocumentDescriptor mPrefDescriptor = new DocumentDescriptor("xml_doc", null /* children */); //$NON-NLS-1$ - /** The root document descriptor for gadget provider. */ - private DocumentDescriptor mGadgetDescriptor = new DocumentDescriptor("xml_doc", null /* children */); //$NON-NLS-1$ + /** The root document descriptor for widget provider. */ + private DocumentDescriptor mAppWidgetDescriptor = new DocumentDescriptor("xml_doc", null /* children */); //$NON-NLS-1$ /** @return the root descriptor for both searchable and preferences. */ public DocumentDescriptor getDescriptor() { @@ -75,9 +75,9 @@ public final class XmlDescriptors implements IDescriptorProvider { return mPrefDescriptor; } - /** @return the root descriptor for gadget providers. */ - public DocumentDescriptor getGadgetDescriptor() { - return mGadgetDescriptor; + /** @return the root descriptor for widget providers. */ + public DocumentDescriptor getAppWidgetDescriptor() { + return mAppWidgetDescriptor; } public IDescriptorProvider getSearchableProvider() { @@ -104,14 +104,14 @@ public final class XmlDescriptors implements IDescriptorProvider { }; } - public IDescriptorProvider getGadgetProvider() { + public IDescriptorProvider getAppWidgetProvider() { return new IDescriptorProvider() { public ElementDescriptor getDescriptor() { - return mGadgetDescriptor; + return mAppWidgetDescriptor; } public ElementDescriptor[] getRootElementDescriptors() { - return mGadgetDescriptor.getChildren(); + return mAppWidgetDescriptor.getChildren(); } }; } @@ -123,13 +123,13 @@ public final class XmlDescriptors implements IDescriptorProvider { * all at once. * * @param searchableStyleMap The map style=>attributes for <searchable> from the attrs.xml file - * @param gadgetStyleMap The map style=>attributes for <gadget-provider> from the attrs.xml file + * @param appWidgetStyleMap The map style=>attributes for <appwidget-provider> from the attrs.xml file * @param prefs The list of non-group preference descriptions * @param prefGroups The list of preference group descriptions */ public synchronized void updateDescriptors( Map<String, DeclareStyleableInfo> searchableStyleMap, - Map<String, DeclareStyleableInfo> gadgetStyleMap, + Map<String, DeclareStyleableInfo> appWidgetStyleMap, ViewClassInfo[] prefs, ViewClassInfo[] prefGroups) { XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor( @@ -137,16 +137,16 @@ public final class XmlDescriptors implements IDescriptorProvider { SdkConstants.NS_RESOURCES); ElementDescriptor searchable = createSearchable(searchableStyleMap, xmlns); - ElementDescriptor gadget = createGadgetProviderInfo(gadgetStyleMap, xmlns); + ElementDescriptor appWidget = createAppWidgetProviderInfo(appWidgetStyleMap, xmlns); ElementDescriptor preferences = createPreference(prefs, prefGroups, xmlns); ArrayList<ElementDescriptor> list = new ArrayList<ElementDescriptor>(); if (searchable != null) { list.add(searchable); mSearchDescriptor.setChildren(new ElementDescriptor[]{ searchable }); } - if (gadget != null) { - list.add(gadget); - mGadgetDescriptor.setChildren(new ElementDescriptor[]{ gadget }); + if (appWidget != null) { + list.add(appWidget); + mAppWidgetDescriptor.setChildren(new ElementDescriptor[]{ appWidget }); } if (preferences != null) { list.add(preferences); @@ -190,25 +190,25 @@ public final class XmlDescriptors implements IDescriptorProvider { } /** - * Returns the new ElementDescriptor for <gadget-provider> + * Returns the new ElementDescriptor for <appwidget-provider> */ - private ElementDescriptor createGadgetProviderInfo( - Map<String, DeclareStyleableInfo> gadgetStyleMap, + private ElementDescriptor createAppWidgetProviderInfo( + Map<String, DeclareStyleableInfo> appWidgetStyleMap, XmlnsAttributeDescriptor xmlns) { - if (gadgetStyleMap == null) { + if (appWidgetStyleMap == null) { return null; } - ElementDescriptor gadget = createElement(gadgetStyleMap, - "GadgetProviderInfo", //$NON-NLS-1$ styleName - "gadget-provider", //$NON-NLS-1$ xmlName - "Gadget Provider", // uiName + ElementDescriptor appWidget = createElement(appWidgetStyleMap, + "AppWidgetProviderInfo", //$NON-NLS-1$ styleName + "appwidget-provider", //$NON-NLS-1$ xmlName + "AppWidget Provider", // uiName null, // sdk url xmlns, // extraAttribute null, // childrenElements false /* mandatory */ ); - return gadget; + return appWidget; } /** diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/.classpath b/eclipse/plugins/com.android.ide.eclipse.tests/.classpath index 4088683..6f2a534 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/.classpath +++ b/eclipse/plugins/com.android.ide.eclipse.tests/.classpath @@ -5,6 +5,6 @@ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> <classpathentry kind="lib" path="kxml2-2.3.0.jar"/> - <classpathentry combineaccessrules="false" kind="src" path="/SdkLib"/> + <classpathentry kind="lib" path="/adt/sdklib.jar" sourcepath="/SdkLib"/> <classpathentry kind="output" path="bin"/> </classpath> diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/common/project/AndroidManifestHelperTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/common/project/AndroidManifestHelperTest.java deleted file mode 100644 index 6604264..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/common/project/AndroidManifestHelperTest.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2007 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.common.project; - -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; - -import junit.framework.TestCase; - -public class AndroidManifestHelperTest extends TestCase { - private File mFile; - private AndroidManifestHelper mManifest; - - @Override - protected void setUp() throws Exception { - super.setUp(); - mFile = File.createTempFile("androidManifest", "xml"); //$NON-NLS-1$ //$NON-NLS-2$ - assertNotNull(mFile); - - FileWriter fw = new FileWriter(mFile); - fw.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); //$NON-NLS-1$ - fw.write("<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"); //$NON-NLS-1$ - fw.write(" package=\"com.android.testapp\">\n"); //$NON-NLS-1$ - fw.write(" <application android:icon=\"@drawable/icon\">\n"); //$NON-NLS-1$ - fw.write(" <activity android:name=\".MainActivity\" android:label=\"@string/app_name\">\n"); //$NON-NLS-1$ - fw.write(" <intent-filter>\n"); //$NON-NLS-1$ - fw.write(" <action android:name=\"android.intent.action.MAIN\" />\n"); //$NON-NLS-1$ - fw.write(" <category android:name=\"android.intent.category.LAUNCHER\" />\"\n"); //$NON-NLS-1$ - fw.write(" <category android:name=\"android.intent.category.DEFAULT\" />\n"); //$NON-NLS-1$ - fw.write(" </intent-filter>\n"); //$NON-NLS-1$ - fw.write(" </activity>\n"); //$NON-NLS-1$ - fw.write(" <activity android:name=\".OptionsActivity\" android:label=\"@string/options\"\n"); //$NON-NLS-1$ - fw.write(" android:theme=\"@style/Theme.Floating\">\n"); //$NON-NLS-1$ - fw.write(" <intent-filter>\n"); //$NON-NLS-1$ - fw.write(" <action android:name=\"com.android.mandelbrot.action.EDIT_OPTIONS\" />\n"); //$NON-NLS-1$ - fw.write(" <category android:name=\"android.intent.category.PREFERENCE_CATEGORY\" />\n"); //$NON-NLS-1$ - fw.write(" </intent-filter>\n"); //$NON-NLS-1$ - fw.write(" </activity>\n"); //$NON-NLS-1$ - fw.write(" <activity android:name=\".InfoActivity\" android:label=\"@string/options\"\n"); //$NON-NLS-1$ - fw.write(" android:theme=\"@style/Theme.Floating\">\n"); //$NON-NLS-1$ - fw.write(" <intent-filter>\n"); //$NON-NLS-1$ - fw.write(" <action android:name=\"com.android.mandelbrot.action.DISPLAY_INFO\" />\n"); //$NON-NLS-1$ - fw.write(" </intent-filter>\n"); //$NON-NLS-1$ - fw.write(" </activity>\n"); //$NON-NLS-1$ - fw.write(" </application>\n"); //$NON-NLS-1$ - fw.write("</manifest>\n"); //$NON-NLS-1$ - fw.flush(); - fw.close(); - - mManifest = new AndroidManifestHelper(mFile.getAbsolutePath()); - } - - @Override - protected void tearDown() throws Exception { - assertTrue(mFile.delete()); - super.tearDown(); - } - - public void testExists() { - assertTrue(mManifest.exists()); - } - - public void testNotExists() throws IOException { - File f = File.createTempFile("androidManifest2", "xml"); //$NON-NLS-1$ //$NON-NLS-2$ - assertTrue(f.delete()); - AndroidManifestHelper manifest = new AndroidManifestHelper(f.getAbsolutePath()); - assertFalse(manifest.exists()); - } - - public void testGetPackageName() { - assertEquals("com.android.testapp", mManifest.getPackageName()); - } - - public void testGetActivityName() { - assertEquals("", mManifest.getActivityName(0)); //$NON-NLS-1$ - assertEquals(".MainActivity", mManifest.getActivityName(1)); //$NON-NLS-1$ - assertEquals(".OptionsActivity", mManifest.getActivityName(2)); //$NON-NLS-1$ - assertEquals(".InfoActivity", mManifest.getActivityName(3)); //$NON-NLS-1$ - assertEquals("", mManifest.getActivityName(4)); //$NON-NLS-1$ - } - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/common/project/AndroidManifestParserTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/common/project/AndroidManifestParserTest.java new file mode 100644 index 0000000..516e448 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/common/project/AndroidManifestParserTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2007 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.common.project; + +import junit.framework.TestCase; + +import com.android.ide.eclipse.mock.FileMock; + +/** + * Tests for {@link AndroidManifestParser} + */ +public class AndroidManifestParserTest extends TestCase { + private AndroidManifestParser mManifest; + + private static final String PACKAGE_NAME = "com.android.testapp"; //$NON-NLS-1$ + private static final String ACTIVITY_NAME = "com.android.testapp.MainActivity"; //$NON-NLS-1$ + private static final String LIBRARY_NAME = "android.test.runner"; //$NON-NLS-1$ + private static final String INSTRUMENTATION_NAME = "android.test.InstrumentationTestRunner"; //$NON-NLS-1$ + + @Override + protected void setUp() throws Exception { + super.setUp(); + + // create the test data + StringBuilder sb = new StringBuilder(); + sb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); //$NON-NLS-1$ + sb.append("<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"); //$NON-NLS-1$ + sb.append(" package=\""); //$NON-NLS-1$ + sb.append(PACKAGE_NAME); + sb.append("\">\n"); //$NON-NLS-1$ + sb.append(" <application android:icon=\"@drawable/icon\">\n"); //$NON-NLS-1$ + sb.append(" <activity android:name=\""); //$NON-NLS-1$ + sb.append(ACTIVITY_NAME); + sb.append("\" android:label=\"@string/app_name\">\n"); //$NON-NLS-1$ + sb.append(" <intent-filter>\n"); //$NON-NLS-1$ + sb.append(" <action android:name=\"android.intent.action.MAIN\" />\n"); //$NON-NLS-1$ + sb.append(" <category android:name=\"android.intent.category.LAUNCHER\" />\"\n"); //$NON-NLS-1$ + sb.append(" <category android:name=\"android.intent.category.DEFAULT\" />\n"); //$NON-NLS-1$ + sb.append(" </intent-filter>\n"); //$NON-NLS-1$ + sb.append(" </activity>\n"); //$NON-NLS-1$ + sb.append(" <uses-library android:name=\""); //$NON-NLS-1$ + sb.append(LIBRARY_NAME); + sb.append("\" />\n"); //$NON-NLS-1$ + sb.append(" </application>"); //$NON-NLS-1$ + sb.append(" <instrumentation android:name=\""); //$NON-NLS-1$ + sb.append(INSTRUMENTATION_NAME); + sb.append("\"\n"); + sb.append(" android:targetPackage=\"com.example.android.apis\"\n"); + sb.append(" android:label=\"Tests for Api Demos.\"/>\n"); + sb.append("</manifest>\n"); //$NON-NLS-1$ + + FileMock mockFile = new FileMock("AndroidManifest.xml", sb.toString().getBytes()); + + mManifest = AndroidManifestParser.parseForData(mockFile); + assertNotNull(mManifest); + } + + public void testGetPackage() { + assertEquals("com.android.testapp", mManifest.getPackage()); + } + + public void testGetActivities() { + assertEquals(1, mManifest.getActivities().length); + assertEquals(ACTIVITY_NAME, mManifest.getActivities()[0]); + } + + public void testGetLauncherActivity() { + assertEquals(ACTIVITY_NAME, mManifest.getLauncherActivity()); + } + + public void testGetUsesLibraries() { + assertEquals(1, mManifest.getUsesLibraries().length); + assertEquals(LIBRARY_NAME, mManifest.getUsesLibraries()[0]); + } + + public void testGetInstrumentations() { + assertEquals(1, mManifest.getInstrumentations().length); + assertEquals(INSTRUMENTATION_NAME, mManifest.getInstrumentations()[0]); + } +} diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/FileMock.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/FileMock.java index 2220ed1..987ea92 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/FileMock.java +++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/FileMock.java @@ -37,6 +37,7 @@ import org.eclipse.core.runtime.jobs.ISchedulingRule; import sun.reflect.generics.reflectiveObjects.NotImplementedException; +import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.Reader; import java.net.URI; @@ -44,16 +45,28 @@ import java.util.Map; /** * Mock implementation of {@link IFile}. + * + * Optionally backed by an in-memory byte array + * * <p/>Supported methods: * <ul> + * <li>getName()</li> + * <li>getContents()</li> + * <li>getContents(boolean force)</li> * </ul> */ public class FileMock implements IFile { private String mName; + private byte[] mContentData; public FileMock(String name) { + this(name, new byte[0]); + } + + public FileMock(String name, byte[] fileData) { mName = name; + mContentData = fileData; } // -------- MOCKED METHODS ---------------- @@ -62,6 +75,15 @@ public class FileMock implements IFile { return mName; } + public InputStream getContents() throws CoreException { + return new ByteArrayInputStream(mContentData); + } + + public InputStream getContents(boolean force) throws CoreException { + // ignore force + return getContents(); + } + // -------- UNIMPLEMENTED METHODS ---------------- public void appendContents(InputStream source, int updateFlags, IProgressMonitor monitor) @@ -115,14 +137,6 @@ public class FileMock implements IFile { throw new NotImplementedException(); } - public InputStream getContents() throws CoreException { - throw new NotImplementedException(); - } - - public InputStream getContents(boolean force) throws CoreException { - throw new NotImplementedException(); - } - public int getEncoding() throws CoreException { throw new NotImplementedException(); } @@ -139,7 +153,8 @@ public class FileMock implements IFile { throw new NotImplementedException(); } - public void move(IPath destination, boolean force, boolean keepHistory, IProgressMonitor monitor) + public void move(IPath destination, boolean force, boolean keepHistory, + IProgressMonitor monitor) throws CoreException { throw new NotImplementedException(); } @@ -229,7 +244,8 @@ public class FileMock implements IFile { throw new NotImplementedException(); } - public void deleteMarkers(String type, boolean includeSubtypes, int depth) throws CoreException { + public void deleteMarkers(String type, boolean includeSubtypes, int depth) + throws CoreException { throw new NotImplementedException(); } @@ -424,26 +440,26 @@ public class FileMock implements IFile { throw new NotImplementedException(); } - @SuppressWarnings("unchecked") + @SuppressWarnings("unchecked") public Map getPersistentProperties() throws CoreException { throw new NotImplementedException(); - } + } - @SuppressWarnings("unchecked") + @SuppressWarnings("unchecked") public Map getSessionProperties() throws CoreException { throw new NotImplementedException(); - } + } - public boolean isDerived(int options) { + public boolean isDerived(int options) { throw new NotImplementedException(); - } + } - public boolean isHidden() { + public boolean isHidden() { throw new NotImplementedException(); - } + } - public void setHidden(boolean isHidden) throws CoreException { + public void setHidden(boolean isHidden) throws CoreException { throw new NotImplementedException(); - } - + } } + |