Home | History | Annotate | Download | only in sdk
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.eclipse.org/org/documents/epl-v10.php
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.ide.eclipse.adt.internal.sdk;
     18 
     19 import com.android.SdkConstants;
     20 import com.android.ide.common.rendering.LayoutLibrary;
     21 import com.android.ide.common.resources.ResourceRepository;
     22 import com.android.ide.common.resources.platform.AttrsXmlParser;
     23 import com.android.ide.common.resources.platform.DeclareStyleableInfo;
     24 import com.android.ide.common.resources.platform.ViewClassInfo;
     25 import com.android.ide.eclipse.adt.AdtPlugin;
     26 import com.android.ide.eclipse.adt.internal.editors.animator.AnimDescriptors;
     27 import com.android.ide.eclipse.adt.internal.editors.animator.AnimatorDescriptors;
     28 import com.android.ide.eclipse.adt.internal.editors.color.ColorDescriptors;
     29 import com.android.ide.eclipse.adt.internal.editors.drawable.DrawableDescriptors;
     30 import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.LayoutDescriptors;
     31 import com.android.ide.eclipse.adt.internal.editors.manifest.descriptors.AndroidManifestDescriptors;
     32 import com.android.ide.eclipse.adt.internal.editors.menu.descriptors.MenuDescriptors;
     33 import com.android.ide.eclipse.adt.internal.editors.otherxml.descriptors.OtherXmlDescriptors;
     34 import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
     35 import com.android.sdklib.IAndroidTarget;
     36 
     37 import org.eclipse.core.runtime.IProgressMonitor;
     38 import org.eclipse.core.runtime.IStatus;
     39 import org.eclipse.core.runtime.Status;
     40 import org.eclipse.core.runtime.SubMonitor;
     41 
     42 import java.io.BufferedReader;
     43 import java.io.FileNotFoundException;
     44 import java.io.FileReader;
     45 import java.io.IOException;
     46 import java.lang.reflect.Field;
     47 import java.lang.reflect.Modifier;
     48 import java.util.ArrayList;
     49 import java.util.Collection;
     50 import java.util.Collections;
     51 import java.util.HashMap;
     52 import java.util.List;
     53 import java.util.Map;
     54 
     55 import javax.management.InvalidAttributeValueException;
     56 
     57 /**
     58  * Parser for the platform data in an SDK.
     59  * <p/>
     60  * This gather the following information:
     61  * <ul>
     62  * <li>Resource ID from <code>android.R</code></li>
     63  * <li>The list of permissions values from <code>android.Manifest$permission</code></li>
     64  * <li></li>
     65  * </ul>
     66  */
     67 public final class AndroidTargetParser {
     68 
     69     private static final String TAG = "Framework Resource Parser";
     70     private final IAndroidTarget mAndroidTarget;
     71 
     72     /**
     73      * Creates a platform data parser.
     74      */
     75     public AndroidTargetParser(IAndroidTarget platformTarget) {
     76         mAndroidTarget = platformTarget;
     77     }
     78 
     79     /**
     80      * Parses the framework, collects all interesting information and stores them in the
     81      * {@link IAndroidTarget} given to the constructor.
     82      *
     83      * @param monitor A progress monitor. Can be null. Caller is responsible for calling done.
     84      * @return True if the SDK path was valid and parsing has been attempted.
     85      */
     86     public IStatus run(IProgressMonitor monitor) {
     87         try {
     88             SubMonitor progress = SubMonitor.convert(monitor,
     89                     String.format("Parsing SDK %1$s", mAndroidTarget.getName()),
     90                     16);
     91 
     92             AndroidTargetData targetData = new AndroidTargetData(mAndroidTarget);
     93 
     94             // parse the rest of the data.
     95 
     96             AndroidJarLoader classLoader =
     97                 new AndroidJarLoader(mAndroidTarget.getPath(IAndroidTarget.ANDROID_JAR));
     98 
     99             preload(classLoader, progress.newChild(40, SubMonitor.SUPPRESS_NONE));
    100 
    101             if (progress.isCanceled()) {
    102                 return Status.CANCEL_STATUS;
    103             }
    104 
    105             // get the permissions
    106             progress.subTask("Permissions");
    107             String[] permissionValues = collectPermissions(classLoader);
    108             progress.worked(1);
    109 
    110             if (progress.isCanceled()) {
    111                 return Status.CANCEL_STATUS;
    112             }
    113 
    114             // get the action and category values for the Intents.
    115             progress.subTask("Intents");
    116             ArrayList<String> activity_actions = new ArrayList<String>();
    117             ArrayList<String> broadcast_actions = new ArrayList<String>();
    118             ArrayList<String> service_actions = new ArrayList<String>();
    119             ArrayList<String> categories = new ArrayList<String>();
    120             collectIntentFilterActionsAndCategories(activity_actions, broadcast_actions,
    121                     service_actions, categories);
    122             progress.worked(1);
    123 
    124             if (progress.isCanceled()) {
    125                 return Status.CANCEL_STATUS;
    126             }
    127 
    128             // gather the attribute definition
    129             progress.subTask("Attributes definitions");
    130             AttrsXmlParser attrsXmlParser = new AttrsXmlParser(
    131                     mAndroidTarget.getPath(IAndroidTarget.ATTRIBUTES),
    132                     AdtPlugin.getDefault(),
    133                     1000);
    134             attrsXmlParser.preload();
    135 
    136             progress.worked(1);
    137 
    138             progress.subTask("Manifest definitions");
    139             AttrsXmlParser attrsManifestXmlParser = new AttrsXmlParser(
    140                     mAndroidTarget.getPath(IAndroidTarget.MANIFEST_ATTRIBUTES),
    141                     attrsXmlParser,
    142                     AdtPlugin.getDefault(), 1100);
    143             attrsManifestXmlParser.preload();
    144             progress.worked(1);
    145 
    146             Collection<ViewClassInfo> mainList = new ArrayList<ViewClassInfo>();
    147             Collection<ViewClassInfo> groupList = new ArrayList<ViewClassInfo>();
    148 
    149             // collect the layout/widgets classes
    150             progress.subTask("Widgets and layouts");
    151             collectLayoutClasses(classLoader, attrsXmlParser, mainList, groupList,
    152                     progress.newChild(1));
    153 
    154             if (progress.isCanceled()) {
    155                 return Status.CANCEL_STATUS;
    156             }
    157 
    158             ViewClassInfo[] layoutViewsInfo = mainList.toArray(
    159                     new ViewClassInfo[mainList.size()]);
    160             ViewClassInfo[] layoutGroupsInfo = groupList.toArray(
    161                     new ViewClassInfo[groupList.size()]);
    162             mainList.clear();
    163             groupList.clear();
    164 
    165             // collect the preferences classes.
    166             collectPreferenceClasses(classLoader, attrsXmlParser, mainList, groupList,
    167                     progress.newChild(1));
    168 
    169             if (progress.isCanceled()) {
    170                 return Status.CANCEL_STATUS;
    171             }
    172 
    173             ViewClassInfo[] preferencesInfo = mainList.toArray(new ViewClassInfo[mainList.size()]);
    174             ViewClassInfo[] preferenceGroupsInfo = groupList.toArray(
    175                     new ViewClassInfo[groupList.size()]);
    176 
    177             Map<String, DeclareStyleableInfo> xmlMenuMap = collectMenuDefinitions(attrsXmlParser);
    178             Map<String, DeclareStyleableInfo> xmlSearchableMap = collectSearchableDefinitions(
    179                     attrsXmlParser);
    180             Map<String, DeclareStyleableInfo> manifestMap = collectManifestDefinitions(
    181                                                                             attrsManifestXmlParser);
    182             Map<String, Map<String, Integer>> enumValueMap = attrsXmlParser.getEnumFlagValues();
    183 
    184             Map<String, DeclareStyleableInfo> xmlAppWidgetMap = null;
    185             if (mAndroidTarget.getVersion().getApiLevel() >= 3) {
    186                 xmlAppWidgetMap = collectAppWidgetDefinitions(attrsXmlParser);
    187             }
    188 
    189             if (progress.isCanceled()) {
    190                 return Status.CANCEL_STATUS;
    191             }
    192 
    193             // From the information that was collected, create the pieces that will be put in
    194             // the PlatformData object.
    195             AndroidManifestDescriptors manifestDescriptors = new AndroidManifestDescriptors();
    196             manifestDescriptors.updateDescriptors(manifestMap);
    197             progress.worked(1);
    198 
    199             if (progress.isCanceled()) {
    200                 return Status.CANCEL_STATUS;
    201             }
    202 
    203             LayoutDescriptors layoutDescriptors = new LayoutDescriptors();
    204             layoutDescriptors.updateDescriptors(layoutViewsInfo, layoutGroupsInfo,
    205                     attrsXmlParser.getDeclareStyleableList(), mAndroidTarget);
    206             progress.worked(1);
    207 
    208             if (progress.isCanceled()) {
    209                 return Status.CANCEL_STATUS;
    210             }
    211 
    212             MenuDescriptors menuDescriptors = new MenuDescriptors();
    213             menuDescriptors.updateDescriptors(xmlMenuMap);
    214             progress.worked(1);
    215 
    216             if (progress.isCanceled()) {
    217                 return Status.CANCEL_STATUS;
    218             }
    219 
    220             OtherXmlDescriptors otherXmlDescriptors = new OtherXmlDescriptors();
    221             otherXmlDescriptors.updateDescriptors(
    222                     xmlSearchableMap,
    223                     xmlAppWidgetMap,
    224                     preferencesInfo,
    225                     preferenceGroupsInfo);
    226             progress.worked(1);
    227 
    228             if (progress.isCanceled()) {
    229                 return Status.CANCEL_STATUS;
    230             }
    231 
    232             DrawableDescriptors drawableDescriptors = new DrawableDescriptors();
    233             Map<String, DeclareStyleableInfo> map = attrsXmlParser.getDeclareStyleableList();
    234             drawableDescriptors.updateDescriptors(map);
    235             progress.worked(1);
    236 
    237             if (progress.isCanceled()) {
    238                 return Status.CANCEL_STATUS;
    239             }
    240 
    241             AnimatorDescriptors animatorDescriptors = new AnimatorDescriptors();
    242             animatorDescriptors.updateDescriptors(map);
    243             progress.worked(1);
    244 
    245             if (progress.isCanceled()) {
    246                 return Status.CANCEL_STATUS;
    247             }
    248 
    249             AnimDescriptors animDescriptors = new AnimDescriptors();
    250             animDescriptors.updateDescriptors(map);
    251             progress.worked(1);
    252 
    253             if (progress.isCanceled()) {
    254                 return Status.CANCEL_STATUS;
    255             }
    256 
    257             ColorDescriptors colorDescriptors = new ColorDescriptors();
    258             colorDescriptors.updateDescriptors(map);
    259             progress.worked(1);
    260 
    261             // load the framework resources.
    262             ResourceRepository frameworkResources =
    263                     ResourceManager.getInstance().loadFrameworkResources(mAndroidTarget);
    264             progress.worked(1);
    265 
    266             // now load the layout lib bridge
    267             LayoutLibrary layoutBridge =  LayoutLibrary.load(
    268                     mAndroidTarget.getPath(IAndroidTarget.LAYOUT_LIB),
    269                     AdtPlugin.getDefault(),
    270                     "ADT plug-in");
    271 
    272             progress.worked(1);
    273 
    274             // and finally create the PlatformData with all that we loaded.
    275             targetData.setExtraData(
    276                     manifestDescriptors,
    277                     layoutDescriptors,
    278                     menuDescriptors,
    279                     otherXmlDescriptors,
    280                     drawableDescriptors,
    281                     animatorDescriptors,
    282                     animDescriptors,
    283                     colorDescriptors,
    284                     enumValueMap,
    285                     permissionValues,
    286                     activity_actions.toArray(new String[activity_actions.size()]),
    287                     broadcast_actions.toArray(new String[broadcast_actions.size()]),
    288                     service_actions.toArray(new String[service_actions.size()]),
    289                     categories.toArray(new String[categories.size()]),
    290                     mAndroidTarget.getPlatformLibraries(),
    291                     mAndroidTarget.getOptionalLibraries(),
    292                     frameworkResources,
    293                     layoutBridge);
    294 
    295             targetData.setAttributeMap(attrsXmlParser.getAttributeMap());
    296 
    297             Sdk.getCurrent().setTargetData(mAndroidTarget, targetData);
    298 
    299             return Status.OK_STATUS;
    300         } catch (Exception e) {
    301             AdtPlugin.logAndPrintError(e, TAG, "SDK parser failed"); //$NON-NLS-1$
    302             AdtPlugin.printToConsole("SDK parser failed", e.getMessage());
    303             return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, "SDK parser failed", e);
    304         }
    305     }
    306 
    307     /**
    308      * Preloads all "interesting" classes from the framework SDK jar.
    309      * <p/>
    310      * Currently this preloads all classes from the framework jar
    311      *
    312      * @param classLoader The framework SDK jar classloader
    313      * @param monitor A progress monitor. Can be null. Caller is responsible for calling done.
    314      */
    315     private void preload(AndroidJarLoader classLoader, IProgressMonitor monitor) {
    316         try {
    317             classLoader.preLoadClasses("" /* all classes */,        //$NON-NLS-1$
    318                     mAndroidTarget.getName(),                       // monitor task label
    319                     monitor);
    320         } catch (InvalidAttributeValueException e) {
    321             AdtPlugin.log(e, "Problem preloading classes"); //$NON-NLS-1$
    322         } catch (IOException e) {
    323             AdtPlugin.log(e, "Problem preloading classes"); //$NON-NLS-1$
    324         }
    325     }
    326 
    327     /**
    328      * Loads, collects and returns the list of default permissions from the framework.
    329      *
    330      * @param classLoader The framework SDK jar classloader
    331      * @return a non null (but possibly empty) array containing the permission values.
    332      */
    333     private String[] collectPermissions(AndroidJarLoader classLoader) {
    334         try {
    335             Class<?> permissionClass =
    336                 classLoader.loadClass(SdkConstants.CLASS_MANIFEST_PERMISSION);
    337 
    338             if (permissionClass != null) {
    339                 ArrayList<String> list = new ArrayList<String>();
    340 
    341                 Field[] fields = permissionClass.getFields();
    342 
    343                 for (Field f : fields) {
    344                     int modifiers = f.getModifiers();
    345                     if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers) &&
    346                             Modifier.isPublic(modifiers)) {
    347                         try {
    348                             Object value = f.get(null);
    349                             if (value instanceof String) {
    350                                 list.add((String)value);
    351                             }
    352                         } catch (IllegalArgumentException e) {
    353                             // since we provide null this should not happen
    354                         } catch (IllegalAccessException e) {
    355                             // if the field is inaccessible we ignore it.
    356                         } catch (NullPointerException npe) {
    357                             // looks like this is not a static field. we can ignore.
    358                         } catch (ExceptionInInitializerError  eiie) {
    359                             // lets just ignore the field again
    360                         }
    361                     }
    362                 }
    363 
    364                 return list.toArray(new String[list.size()]);
    365             }
    366         } catch (ClassNotFoundException e) {
    367             AdtPlugin.logAndPrintError(e, TAG,
    368                     "Collect permissions failed, class %1$s not found in %2$s", //$NON-NLS-1$
    369                     SdkConstants.CLASS_MANIFEST_PERMISSION,
    370                     mAndroidTarget.getPath(IAndroidTarget.ANDROID_JAR));
    371         }
    372 
    373         return new String[0];
    374     }
    375 
    376     /**
    377      * Loads and collects the action and category default values from the framework.
    378      * The values are added to the <code>actions</code> and <code>categories</code> lists.
    379      *
    380      * @param activityActions the list which will receive the activity action values.
    381      * @param broadcastActions the list which will receive the broadcast action values.
    382      * @param serviceActions the list which will receive the service action values.
    383      * @param categories the list which will receive the category values.
    384      */
    385     private void collectIntentFilterActionsAndCategories(ArrayList<String> activityActions,
    386             ArrayList<String> broadcastActions,
    387             ArrayList<String> serviceActions, ArrayList<String> categories)  {
    388         collectValues(mAndroidTarget.getPath(IAndroidTarget.ACTIONS_ACTIVITY),
    389                 activityActions);
    390         collectValues(mAndroidTarget.getPath(IAndroidTarget.ACTIONS_BROADCAST),
    391                 broadcastActions);
    392         collectValues(mAndroidTarget.getPath(IAndroidTarget.ACTIONS_SERVICE),
    393                 serviceActions);
    394         collectValues(mAndroidTarget.getPath(IAndroidTarget.CATEGORIES),
    395                 categories);
    396     }
    397 
    398     /**
    399      * Collects values from a text file located in the SDK
    400      * @param osFilePath The path to the text file.
    401      * @param values the {@link ArrayList} to fill with the values.
    402      */
    403     private void collectValues(String osFilePath, ArrayList<String> values) {
    404         FileReader fr = null;
    405         BufferedReader reader = null;
    406         try {
    407             fr = new FileReader(osFilePath);
    408             reader = new BufferedReader(fr);
    409 
    410             String line;
    411             while ((line = reader.readLine()) != null) {
    412                 line = line.trim();
    413                 if (line.length() > 0 && line.startsWith("#") == false) { //$NON-NLS-1$
    414                     values.add(line);
    415                 }
    416             }
    417         } catch (IOException e) {
    418             AdtPlugin.log(e, "Failed to read SDK values"); //$NON-NLS-1$
    419         } finally {
    420             try {
    421                 if (reader != null) {
    422                     reader.close();
    423                 }
    424             } catch (IOException e) {
    425                 AdtPlugin.log(e, "Failed to read SDK values"); //$NON-NLS-1$
    426             }
    427 
    428             try {
    429                 if (fr != null) {
    430                     fr.close();
    431                 }
    432             } catch (IOException e) {
    433                 AdtPlugin.log(e, "Failed to read SDK values"); //$NON-NLS-1$
    434             }
    435         }
    436     }
    437 
    438     /**
    439      * Collects all layout classes information from the class loader and the
    440      * attrs.xml and sets the corresponding structures in the resource manager.
    441      *
    442      * @param classLoader The framework SDK jar classloader in case we cannot get the widget from
    443      * the platform directly
    444      * @param attrsXmlParser The parser of the attrs.xml file
    445      * @param mainList the Collection to receive the main list of {@link ViewClassInfo}.
    446      * @param groupList the Collection to receive the group list of {@link ViewClassInfo}.
    447      * @param monitor A progress monitor. Can be null. Caller is responsible for calling done.
    448      */
    449     private void collectLayoutClasses(AndroidJarLoader classLoader,
    450             AttrsXmlParser attrsXmlParser,
    451             Collection<ViewClassInfo> mainList,
    452             Collection<ViewClassInfo> groupList,
    453             IProgressMonitor monitor) {
    454         LayoutParamsParser ldp = null;
    455         try {
    456             WidgetClassLoader loader = new WidgetClassLoader(
    457                     mAndroidTarget.getPath(IAndroidTarget.WIDGETS));
    458             if (loader.parseWidgetList(monitor)) {
    459                 ldp = new LayoutParamsParser(loader, attrsXmlParser);
    460             }
    461             // if the parsing failed, we'll use the old loader below.
    462         } catch (FileNotFoundException e) {
    463             AdtPlugin.log(e, "Android Framework Parser"); //$NON-NLS-1$
    464             // the file does not exist, we'll use the old loader below.
    465         }
    466 
    467         if (ldp == null) {
    468             ldp = new LayoutParamsParser(classLoader, attrsXmlParser);
    469         }
    470         ldp.parseLayoutClasses(monitor);
    471 
    472         List<ViewClassInfo> views = ldp.getViews();
    473         List<ViewClassInfo> groups = ldp.getGroups();
    474 
    475         if (views != null && groups != null) {
    476             mainList.addAll(views);
    477             groupList.addAll(groups);
    478         }
    479     }
    480 
    481     /**
    482      * Collects all preferences definition information from the attrs.xml and
    483      * sets the corresponding structures in the resource manager.
    484      *
    485      * @param classLoader The framework SDK jar classloader
    486      * @param attrsXmlParser The parser of the attrs.xml file
    487      * @param mainList the Collection to receive the main list of {@link ViewClassInfo}.
    488      * @param groupList the Collection to receive the group list of {@link ViewClassInfo}.
    489      * @param monitor A progress monitor. Can be null. Caller is responsible for calling done.
    490      */
    491     private void collectPreferenceClasses(AndroidJarLoader classLoader,
    492             AttrsXmlParser attrsXmlParser, Collection<ViewClassInfo> mainList,
    493             Collection<ViewClassInfo> groupList, IProgressMonitor monitor) {
    494         LayoutParamsParser ldp = new LayoutParamsParser(classLoader, attrsXmlParser);
    495 
    496         try {
    497             ldp.parsePreferencesClasses(monitor);
    498 
    499             List<ViewClassInfo> prefs = ldp.getViews();
    500             List<ViewClassInfo> groups = ldp.getGroups();
    501 
    502             if (prefs != null && groups != null) {
    503                 mainList.addAll(prefs);
    504                 groupList.addAll(groups);
    505             }
    506         } catch (NoClassDefFoundError e) {
    507             AdtPlugin.logAndPrintError(e, TAG,
    508                     "Collect preferences failed, class %1$s not found in %2$s",
    509                     e.getMessage(),
    510                     classLoader.getSource());
    511         } catch (Throwable e) {
    512             AdtPlugin.log(e, "Android Framework Parser: failed to collect preference classes"); //$NON-NLS-1$
    513             AdtPlugin.printErrorToConsole("Android Framework Parser",
    514                     "failed to collect preference classes");
    515         }
    516     }
    517 
    518     /**
    519      * Collects all menu definition information from the attrs.xml and returns it.
    520      *
    521      * @param attrsXmlParser The parser of the attrs.xml file
    522      */
    523     private Map<String, DeclareStyleableInfo> collectMenuDefinitions(
    524             AttrsXmlParser attrsXmlParser) {
    525         Map<String, DeclareStyleableInfo> map = attrsXmlParser.getDeclareStyleableList();
    526         Map<String, DeclareStyleableInfo> map2 = new HashMap<String, DeclareStyleableInfo>();
    527         for (String key : new String[] { "Menu",        //$NON-NLS-1$
    528                                          "MenuItem",        //$NON-NLS-1$
    529                                          "MenuGroup" }) {   //$NON-NLS-1$
    530             if (map.containsKey(key)) {
    531                 map2.put(key, map.get(key));
    532             } else {
    533                 AdtPlugin.log(IStatus.WARNING,
    534                         "Menu declare-styleable %1$s not found in file %2$s", //$NON-NLS-1$
    535                         key, attrsXmlParser.getOsAttrsXmlPath());
    536                 AdtPlugin.printErrorToConsole("Android Framework Parser",
    537                         String.format("Menu declare-styleable %1$s not found in file %2$s", //$NON-NLS-1$
    538                         key, attrsXmlParser.getOsAttrsXmlPath()));
    539             }
    540         }
    541 
    542         return Collections.unmodifiableMap(map2);
    543     }
    544 
    545     /**
    546      * Collects all searchable definition information from the attrs.xml and returns it.
    547      *
    548      * @param attrsXmlParser The parser of the attrs.xml file
    549      */
    550     private Map<String, DeclareStyleableInfo> collectSearchableDefinitions(
    551             AttrsXmlParser attrsXmlParser) {
    552         Map<String, DeclareStyleableInfo> map = attrsXmlParser.getDeclareStyleableList();
    553         Map<String, DeclareStyleableInfo> map2 = new HashMap<String, DeclareStyleableInfo>();
    554         for (String key : new String[] { "Searchable",              //$NON-NLS-1$
    555                                          "SearchableActionKey" }) { //$NON-NLS-1$
    556             if (map.containsKey(key)) {
    557                 map2.put(key, map.get(key));
    558             } else {
    559                 AdtPlugin.log(IStatus.WARNING,
    560                         "Searchable declare-styleable %1$s not found in file %2$s", //$NON-NLS-1$
    561                         key, attrsXmlParser.getOsAttrsXmlPath());
    562                 AdtPlugin.printErrorToConsole("Android Framework Parser",
    563                         String.format("Searchable declare-styleable %1$s not found in file %2$s", //$NON-NLS-1$
    564                         key, attrsXmlParser.getOsAttrsXmlPath()));
    565             }
    566         }
    567 
    568         return Collections.unmodifiableMap(map2);
    569     }
    570 
    571     /**
    572      * Collects all appWidgetProviderInfo definition information from the attrs.xml and returns it.
    573      *
    574      * @param attrsXmlParser The parser of the attrs.xml file
    575      */
    576     private Map<String, DeclareStyleableInfo> collectAppWidgetDefinitions(
    577             AttrsXmlParser attrsXmlParser) {
    578         Map<String, DeclareStyleableInfo> map = attrsXmlParser.getDeclareStyleableList();
    579         Map<String, DeclareStyleableInfo> map2 = new HashMap<String, DeclareStyleableInfo>();
    580         for (String key : new String[] { "AppWidgetProviderInfo" }) {  //$NON-NLS-1$
    581             if (map.containsKey(key)) {
    582                 map2.put(key, map.get(key));
    583             } else {
    584                 AdtPlugin.log(IStatus.WARNING,
    585                         "AppWidget declare-styleable %1$s not found in file %2$s", //$NON-NLS-1$
    586                         key, attrsXmlParser.getOsAttrsXmlPath());
    587                 AdtPlugin.printErrorToConsole("Android Framework Parser",
    588                         String.format("AppWidget declare-styleable %1$s not found in file %2$s", //$NON-NLS-1$
    589                         key, attrsXmlParser.getOsAttrsXmlPath()));
    590             }
    591         }
    592 
    593         return Collections.unmodifiableMap(map2);
    594     }
    595 
    596     /**
    597      * Collects all manifest definition information from the attrs_manifest.xml and returns it.
    598      */
    599     private Map<String, DeclareStyleableInfo> collectManifestDefinitions(
    600             AttrsXmlParser attrsXmlParser) {
    601 
    602         return attrsXmlParser.getDeclareStyleableList();
    603     }
    604 
    605 }
    606