AndroidTargetParserpublic final class AndroidTargetParser extends Object Parser for the platform data in an SDK.
This gather the following information:
- Resource ID from
android.R
- The list of permissions values from
android.Manifest$permission
|
Fields Summary |
---|
private static final String | TAG | private final com.android.sdklib.IAndroidTarget | mAndroidTarget |
Methods Summary |
---|
private java.util.Map | collectAppWidgetDefinitions(com.android.ide.eclipse.common.resources.AttrsXmlParser attrsXmlParser)Collects all appWidgetProviderInfo definition information from the attrs.xml and returns it.
Map<String, DeclareStyleableInfo> map = attrsXmlParser.getDeclareStyleableList();
Map<String, DeclareStyleableInfo> map2 = new HashMap<String, DeclareStyleableInfo>();
for (String key : new String[] { "AppWidgetProviderInfo" }) { //$NON-NLS-1$
if (map.containsKey(key)) {
map2.put(key, map.get(key));
} else {
AdtPlugin.log(IStatus.WARNING,
"AppWidget declare-styleable %1$s not found in file %2$s", //$NON-NLS-1$
key, attrsXmlParser.getOsAttrsXmlPath());
AdtPlugin.printErrorToConsole("Android Framework Parser",
String.format("AppWidget declare-styleable %1$s not found in file %2$s", //$NON-NLS-1$
key, attrsXmlParser.getOsAttrsXmlPath()));
}
}
return Collections.unmodifiableMap(map2);
| private void | collectIntentFilterActionsAndCategories(java.util.ArrayList activityActions, java.util.ArrayList broadcastActions, java.util.ArrayList serviceActions, java.util.ArrayList categories)Loads and collects the action and category default values from the framework.
The values are added to the actions and categories lists.
collectValues(mAndroidTarget.getPath(IAndroidTarget.ACTIONS_ACTIVITY),
activityActions);
collectValues(mAndroidTarget.getPath(IAndroidTarget.ACTIONS_BROADCAST),
broadcastActions);
collectValues(mAndroidTarget.getPath(IAndroidTarget.ACTIONS_SERVICE),
serviceActions);
collectValues(mAndroidTarget.getPath(IAndroidTarget.CATEGORIES),
categories);
| private void | collectLayoutClasses(AndroidJarLoader classLoader, com.android.ide.eclipse.common.resources.AttrsXmlParser attrsXmlParser, java.util.Collection mainList, java.util.Collection groupList, org.eclipse.core.runtime.IProgressMonitor monitor)Collects all layout classes information from the class loader and the
attrs.xml and sets the corresponding structures in the resource manager.
LayoutParamsParser ldp = null;
try {
WidgetClassLoader loader = new WidgetClassLoader(
mAndroidTarget.getPath(IAndroidTarget.WIDGETS));
if (loader.parseWidgetList(monitor)) {
ldp = new LayoutParamsParser(loader, attrsXmlParser);
}
// if the parsing failed, we'll use the old loader below.
} catch (FileNotFoundException e) {
AdtPlugin.log(e, "Android Framework Parser"); //$NON-NLS-1$
// the file does not exist, we'll use the old loader below.
}
if (ldp == null) {
ldp = new LayoutParamsParser(classLoader, attrsXmlParser);
}
ldp.parseLayoutClasses(monitor);
List<ViewClassInfo> views = ldp.getViews();
List<ViewClassInfo> groups = ldp.getGroups();
if (views != null && groups != null) {
mainList.addAll(views);
groupList.addAll(groups);
}
| private java.util.Map | collectManifestDefinitions(com.android.ide.eclipse.common.resources.AttrsXmlParser attrsXmlParser)Collects all manifest definition information from the attrs_manifest.xml and returns it.
return attrsXmlParser.getDeclareStyleableList();
| private java.util.Map | collectMenuDefinitions(com.android.ide.eclipse.common.resources.AttrsXmlParser attrsXmlParser)Collects all menu definition information from the attrs.xml and returns it.
Map<String, DeclareStyleableInfo> map = attrsXmlParser.getDeclareStyleableList();
Map<String, DeclareStyleableInfo> map2 = new HashMap<String, DeclareStyleableInfo>();
for (String key : new String[] { "Menu", //$NON-NLS-1$
"MenuItem", //$NON-NLS-1$
"MenuGroup" }) { //$NON-NLS-1$
if (map.containsKey(key)) {
map2.put(key, map.get(key));
} else {
AdtPlugin.log(IStatus.WARNING,
"Menu declare-styleable %1$s not found in file %2$s", //$NON-NLS-1$
key, attrsXmlParser.getOsAttrsXmlPath());
AdtPlugin.printErrorToConsole("Android Framework Parser",
String.format("Menu declare-styleable %1$s not found in file %2$s", //$NON-NLS-1$
key, attrsXmlParser.getOsAttrsXmlPath()));
}
}
return Collections.unmodifiableMap(map2);
| private java.lang.String[] | collectPermissions(AndroidJarLoader classLoader)Loads, collects and returns the list of default permissions from the framework.
try {
Class<?> permissionClass =
classLoader.loadClass(AndroidConstants.CLASS_MANIFEST_PERMISSION);
if (permissionClass != null) {
ArrayList<String> list = new ArrayList<String>();
Field[] fields = permissionClass.getFields();
for (Field f : fields) {
int modifiers = f.getModifiers();
if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers) &&
Modifier.isPublic(modifiers)) {
try {
Object value = f.get(null);
if (value instanceof String) {
list.add((String)value);
}
} catch (IllegalArgumentException e) {
// since we provide null this should not happen
} catch (IllegalAccessException e) {
// if the field is inaccessible we ignore it.
} catch (NullPointerException npe) {
// looks like this is not a static field. we can ignore.
} catch (ExceptionInInitializerError eiie) {
// lets just ignore the field again
}
}
}
return list.toArray(new String[list.size()]);
}
} catch (ClassNotFoundException e) {
AdtPlugin.logAndPrintError(e, TAG,
"Collect permissions failed, class %1$s not found in %2$s", //$NON-NLS-1$
AndroidConstants.CLASS_MANIFEST_PERMISSION,
mAndroidTarget.getPath(IAndroidTarget.ANDROID_JAR));
}
return new String[0];
| private void | collectPreferenceClasses(AndroidJarLoader classLoader, com.android.ide.eclipse.common.resources.AttrsXmlParser attrsXmlParser, java.util.Collection mainList, java.util.Collection groupList, org.eclipse.core.runtime.IProgressMonitor monitor)Collects all preferences definition information from the attrs.xml and
sets the corresponding structures in the resource manager.
LayoutParamsParser ldp = new LayoutParamsParser(classLoader, attrsXmlParser);
try {
ldp.parsePreferencesClasses(monitor);
List<ViewClassInfo> prefs = ldp.getViews();
List<ViewClassInfo> groups = ldp.getGroups();
if (prefs != null && groups != null) {
mainList.addAll(prefs);
groupList.addAll(groups);
}
} catch (NoClassDefFoundError e) {
AdtPlugin.logAndPrintError(e, TAG,
"Collect preferences failed, class %1$s not found in %2$s",
e.getMessage(),
classLoader.getSource());
} catch (Throwable e) {
AdtPlugin.log(e, "Android Framework Parser: failed to collect preference classes"); //$NON-NLS-1$
AdtPlugin.printErrorToConsole("Android Framework Parser",
"failed to collect preference classes");
}
| private com.android.ide.eclipse.common.resources.IResourceRepository | collectResourceIds(AndroidJarLoader classLoader)Creates an IResourceRepository for the framework resources.
try {
Class<?> r = classLoader.loadClass(AndroidConstants.CLASS_R);
if (r != null) {
Map<ResourceType, List<ResourceItem>> map = parseRClass(r);
if (map != null) {
return new FrameworkResourceRepository(map);
}
}
} catch (ClassNotFoundException e) {
AdtPlugin.logAndPrintError(e, TAG,
"Collect resource IDs failed, class %1$s not found in %2$s", //$NON-NLS-1$
AndroidConstants.CLASS_R,
mAndroidTarget.getPath(IAndroidTarget.ANDROID_JAR));
}
return null;
| private java.util.Map | collectSearchableDefinitions(com.android.ide.eclipse.common.resources.AttrsXmlParser attrsXmlParser)Collects all searchable definition information from the attrs.xml and returns it.
Map<String, DeclareStyleableInfo> map = attrsXmlParser.getDeclareStyleableList();
Map<String, DeclareStyleableInfo> map2 = new HashMap<String, DeclareStyleableInfo>();
for (String key : new String[] { "Searchable", //$NON-NLS-1$
"SearchableActionKey" }) { //$NON-NLS-1$
if (map.containsKey(key)) {
map2.put(key, map.get(key));
} else {
AdtPlugin.log(IStatus.WARNING,
"Searchable declare-styleable %1$s not found in file %2$s", //$NON-NLS-1$
key, attrsXmlParser.getOsAttrsXmlPath());
AdtPlugin.printErrorToConsole("Android Framework Parser",
String.format("Searchable declare-styleable %1$s not found in file %2$s", //$NON-NLS-1$
key, attrsXmlParser.getOsAttrsXmlPath()));
}
}
return Collections.unmodifiableMap(map2);
| private void | collectValues(java.lang.String osFilePath, java.util.ArrayList values)Collects values from a text file located in the SDK
FileReader fr = null;
BufferedReader reader = null;
try {
fr = new FileReader(osFilePath);
reader = new BufferedReader(fr);
String line;
while ((line = reader.readLine()) != null) {
line = line.trim();
if (line.length() > 0 && line.startsWith("#") == false) { //$NON-NLS-1$
values.add(line);
}
}
} catch (IOException e) {
AdtPlugin.log(e, "Failed to read SDK values"); //$NON-NLS-1$
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
AdtPlugin.log(e, "Failed to read SDK values"); //$NON-NLS-1$
}
try {
if (fr != null) {
fr.close();
}
} catch (IOException e) {
AdtPlugin.log(e, "Failed to read SDK values"); //$NON-NLS-1$
}
}
| private com.android.ide.eclipse.adt.sdk.AndroidTargetData.LayoutBridge | loadLayoutBridge()Loads the layout bridge from the dynamically loaded layoutlib.jar
LayoutBridge layoutBridge = new LayoutBridge();
try {
// get the URL for the file.
File f = new File(mAndroidTarget.getPath(IAndroidTarget.LAYOUT_LIB));
if (f.isFile() == false) {
AdtPlugin.log(IStatus.ERROR, "layoutlib.jar is missing!"); //$NON-NLS-1$
} else {
URL url = f.toURL();
// create a class loader. Because this jar reference interfaces
// that are in the editors plugin, it's important to provide
// a parent class loader.
layoutBridge.classLoader = new URLClassLoader(new URL[] { url },
this.getClass().getClassLoader());
// load the class
Class<?> clazz = layoutBridge.classLoader.loadClass(AndroidConstants.CLASS_BRIDGE);
if (clazz != null) {
// instantiate an object of the class.
Constructor<?> constructor = clazz.getConstructor();
if (constructor != null) {
Object bridge = constructor.newInstance();
if (bridge instanceof ILayoutBridge) {
layoutBridge.bridge = (ILayoutBridge)bridge;
}
}
}
if (layoutBridge.bridge == null) {
layoutBridge.status = LoadStatus.FAILED;
AdtPlugin.log(IStatus.ERROR, "Failed to load " + AndroidConstants.CLASS_BRIDGE); //$NON-NLS-1$
} else {
// get the api level
try {
layoutBridge.apiLevel = layoutBridge.bridge.getApiLevel();
} catch (AbstractMethodError e) {
// the first version of the api did not have this method
layoutBridge.apiLevel = 1;
}
// and mark the lib as loaded.
layoutBridge.status = LoadStatus.LOADED;
}
}
} catch (Throwable t) {
layoutBridge.status = LoadStatus.FAILED;
// log the error.
AdtPlugin.log(t, "Failed to load the LayoutLib");
}
return layoutBridge;
| private java.util.Map | parseRClass(java.lang.Class rClass)Parse the R class and build the resource map.
// get the sub classes.
Class<?>[] classes = rClass.getClasses();
if (classes.length > 0) {
HashMap<ResourceType, List<ResourceItem>> map =
new HashMap<ResourceType, List<ResourceItem>>();
// get the fields of each class.
for (int c = 0 ; c < classes.length ; c++) {
Class<?> subClass = classes[c];
String name = subClass.getSimpleName();
// get the matching ResourceType
ResourceType type = ResourceType.getEnum(name);
if (type != null) {
List<ResourceItem> list = new ArrayList<ResourceItem>();
map.put(type, list);
Field[] fields = subClass.getFields();
for (Field f : fields) {
list.add(new ResourceItem(f.getName()));
}
}
}
return map;
}
return null;
| private void | preload(AndroidJarLoader classLoader, org.eclipse.core.runtime.IProgressMonitor monitor)Preloads all "interesting" classes from the framework SDK jar.
Currently this preloads all classes from the framework jar
try {
classLoader.preLoadClasses("" /* all classes */, //$NON-NLS-1$
mAndroidTarget.getName(), // monitor task label
monitor);
} catch (InvalidAttributeValueException e) {
AdtPlugin.log(e, "Problem preloading classes"); //$NON-NLS-1$
} catch (IOException e) {
AdtPlugin.log(e, "Problem preloading classes"); //$NON-NLS-1$
}
| public org.eclipse.core.runtime.IStatus | run(org.eclipse.core.runtime.IProgressMonitor monitor)Parses the framework, collects all interesting information and stores them in the
{@link IAndroidTarget} given to the constructor.
try {
SubMonitor progress = SubMonitor.convert(monitor,
String.format("Parsing SDK %1$s", mAndroidTarget.getName()),
14);
AndroidTargetData targetData = new AndroidTargetData(mAndroidTarget);
// load DX.
DexWrapper dexWrapper = new DexWrapper();
IStatus res = dexWrapper.loadDex(mAndroidTarget.getPath(IAndroidTarget.DX_JAR));
if (res != Status.OK_STATUS) {
return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
String.format("dx.jar loading failed for target '%1$s'",
mAndroidTarget.getFullName()));
}
// we have loaded dx.
targetData.setDexWrapper(dexWrapper);
progress.worked(1);
// parse the rest of the data.
AndroidJarLoader classLoader =
new AndroidJarLoader(mAndroidTarget.getPath(IAndroidTarget.ANDROID_JAR));
preload(classLoader, progress.newChild(40, SubMonitor.SUPPRESS_NONE));
if (progress.isCanceled()) {
return Status.CANCEL_STATUS;
}
// get the resource Ids.
progress.subTask("Resource IDs");
IResourceRepository frameworkRepository = collectResourceIds(classLoader);
progress.worked(1);
if (progress.isCanceled()) {
return Status.CANCEL_STATUS;
}
// get the permissions
progress.subTask("Permissions");
String[] permissionValues = collectPermissions(classLoader);
progress.worked(1);
if (progress.isCanceled()) {
return Status.CANCEL_STATUS;
}
// get the action and category values for the Intents.
progress.subTask("Intents");
ArrayList<String> activity_actions = new ArrayList<String>();
ArrayList<String> broadcast_actions = new ArrayList<String>();
ArrayList<String> service_actions = new ArrayList<String>();
ArrayList<String> categories = new ArrayList<String>();
collectIntentFilterActionsAndCategories(activity_actions, broadcast_actions,
service_actions, categories);
progress.worked(1);
if (progress.isCanceled()) {
return Status.CANCEL_STATUS;
}
// gather the attribute definition
progress.subTask("Attributes definitions");
AttrsXmlParser attrsXmlParser = new AttrsXmlParser(
mAndroidTarget.getPath(IAndroidTarget.ATTRIBUTES));
attrsXmlParser.preload();
progress.worked(1);
progress.subTask("Manifest definitions");
AttrsXmlParser attrsManifestXmlParser = new AttrsXmlParser(
mAndroidTarget.getPath(IAndroidTarget.MANIFEST_ATTRIBUTES),
attrsXmlParser);
attrsManifestXmlParser.preload();
progress.worked(1);
Collection<ViewClassInfo> mainList = new ArrayList<ViewClassInfo>();
Collection<ViewClassInfo> groupList = new ArrayList<ViewClassInfo>();
// collect the layout/widgets classes
progress.subTask("Widgets and layouts");
collectLayoutClasses(classLoader, attrsXmlParser, mainList, groupList,
progress.newChild(1));
if (progress.isCanceled()) {
return Status.CANCEL_STATUS;
}
ViewClassInfo[] layoutViewsInfo = mainList.toArray(new ViewClassInfo[mainList.size()]);
ViewClassInfo[] layoutGroupsInfo = groupList.toArray(
new ViewClassInfo[groupList.size()]);
// collect the preferences classes.
mainList.clear();
groupList.clear();
collectPreferenceClasses(classLoader, attrsXmlParser, mainList, groupList,
progress.newChild(1));
if (progress.isCanceled()) {
return Status.CANCEL_STATUS;
}
ViewClassInfo[] preferencesInfo = mainList.toArray(new ViewClassInfo[mainList.size()]);
ViewClassInfo[] preferenceGroupsInfo = groupList.toArray(
new ViewClassInfo[groupList.size()]);
Map<String, DeclareStyleableInfo> xmlMenuMap = collectMenuDefinitions(attrsXmlParser);
Map<String, DeclareStyleableInfo> xmlSearchableMap = collectSearchableDefinitions(
attrsXmlParser);
Map<String, DeclareStyleableInfo> manifestMap = collectManifestDefinitions(
attrsManifestXmlParser);
Map<String, Map<String, Integer>> enumValueMap = attrsXmlParser.getEnumFlagValues();
Map<String, DeclareStyleableInfo> xmlAppWidgetMap = null;
if (mAndroidTarget.getApiVersionNumber() >= 3) {
xmlAppWidgetMap = collectAppWidgetDefinitions(attrsXmlParser);
}
if (progress.isCanceled()) {
return Status.CANCEL_STATUS;
}
// From the information that was collected, create the pieces that will be put in
// the PlatformData object.
AndroidManifestDescriptors manifestDescriptors = new AndroidManifestDescriptors();
manifestDescriptors.updateDescriptors(manifestMap);
progress.worked(1);
if (progress.isCanceled()) {
return Status.CANCEL_STATUS;
}
LayoutDescriptors layoutDescriptors = new LayoutDescriptors();
layoutDescriptors.updateDescriptors(layoutViewsInfo, layoutGroupsInfo);
progress.worked(1);
if (progress.isCanceled()) {
return Status.CANCEL_STATUS;
}
MenuDescriptors menuDescriptors = new MenuDescriptors();
menuDescriptors.updateDescriptors(xmlMenuMap);
progress.worked(1);
if (progress.isCanceled()) {
return Status.CANCEL_STATUS;
}
XmlDescriptors xmlDescriptors = new XmlDescriptors();
xmlDescriptors.updateDescriptors(
xmlSearchableMap,
xmlAppWidgetMap,
preferencesInfo,
preferenceGroupsInfo);
progress.worked(1);
// load the framework resources.
ProjectResources resources = ResourceManager.getInstance().loadFrameworkResources(
mAndroidTarget);
progress.worked(1);
// now load the layout lib bridge
LayoutBridge layoutBridge = loadLayoutBridge();
progress.worked(1);
// and finally create the PlatformData with all that we loaded.
targetData.setExtraData(frameworkRepository,
manifestDescriptors,
layoutDescriptors,
menuDescriptors,
xmlDescriptors,
enumValueMap,
permissionValues,
activity_actions.toArray(new String[activity_actions.size()]),
broadcast_actions.toArray(new String[broadcast_actions.size()]),
service_actions.toArray(new String[service_actions.size()]),
categories.toArray(new String[categories.size()]),
mAndroidTarget.getOptionalLibraries(),
resources,
layoutBridge);
Sdk.getCurrent().setTargetData(mAndroidTarget, targetData);
return Status.OK_STATUS;
} catch (Exception e) {
AdtPlugin.logAndPrintError(e, TAG, "SDK parser failed"); //$NON-NLS-1$
AdtPlugin.printToConsole("SDK parser failed", e.getMessage());
return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, "SDK parser failed", e);
}
|
|