1 /* 2 * Copyright (C) 2007 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.ide.eclipse.adt.internal.editors.descriptors.IDescriptorProvider; 20 import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.LayoutDescriptors; 21 import com.android.ide.eclipse.adt.internal.editors.manifest.descriptors.AndroidManifestDescriptors; 22 import com.android.ide.eclipse.adt.internal.editors.menu.descriptors.MenuDescriptors; 23 import com.android.ide.eclipse.adt.internal.editors.resources.descriptors.ResourcesDescriptors; 24 import com.android.ide.eclipse.adt.internal.editors.xml.descriptors.XmlDescriptors; 25 import com.android.ide.eclipse.adt.internal.resources.IResourceRepository; 26 import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources; 27 import com.android.layoutlib.api.ILayoutBridge; 28 import com.android.sdklib.IAndroidTarget; 29 import com.android.sdklib.IAndroidTarget.IOptionalLibrary; 30 31 import java.util.ArrayList; 32 import java.util.Hashtable; 33 import java.util.Map; 34 35 /** 36 * This class contains the data of an Android Target as loaded from the SDK. 37 */ 38 public class AndroidTargetData { 39 40 public final static int DESCRIPTOR_MANIFEST = 1; 41 public final static int DESCRIPTOR_LAYOUT = 2; 42 public final static int DESCRIPTOR_MENU = 3; 43 public final static int DESCRIPTOR_XML = 4; 44 public final static int DESCRIPTOR_RESOURCES = 5; 45 public final static int DESCRIPTOR_SEARCHABLE = 6; 46 public final static int DESCRIPTOR_PREFERENCES = 7; 47 public final static int DESCRIPTOR_APPWIDGET_PROVIDER = 8; 48 49 public final static class LayoutBridge { 50 /** Link to the layout bridge */ 51 public ILayoutBridge bridge; 52 53 public LoadStatus status = LoadStatus.LOADING; 54 55 public ClassLoader classLoader; 56 57 public int apiLevel; 58 } 59 60 private final IAndroidTarget mTarget; 61 62 private DexWrapper mDexWrapper; 63 64 /** 65 * mAttributeValues is a map { key => list [ values ] }. 66 * The key for the map is "(element-xml-name,attribute-namespace:attribute-xml-local-name)". 67 * The attribute namespace prefix must be: 68 * - "android" for AndroidConstants.NS_RESOURCES 69 * - "xmlns" for the XMLNS URI. 70 * 71 * This is used for attributes that do not have a unique name, but still need to be populated 72 * with values in the UI. Uniquely named attributes have their values in {@link #mEnumValueMap}. 73 */ 74 private Hashtable<String, String[]> mAttributeValues = new Hashtable<String, String[]>(); 75 76 private IResourceRepository mSystemResourceRepository; 77 78 private AndroidManifestDescriptors mManifestDescriptors; 79 private LayoutDescriptors mLayoutDescriptors; 80 private MenuDescriptors mMenuDescriptors; 81 private XmlDescriptors mXmlDescriptors; 82 83 private Map<String, Map<String, Integer>> mEnumValueMap; 84 85 private ProjectResources mFrameworkResources; 86 private LayoutBridge mLayoutBridge; 87 88 private boolean mLayoutBridgeInit = false; 89 AndroidTargetData(IAndroidTarget androidTarget)90 AndroidTargetData(IAndroidTarget androidTarget) { 91 mTarget = androidTarget; 92 } 93 setDexWrapper(DexWrapper wrapper)94 void setDexWrapper(DexWrapper wrapper) { 95 mDexWrapper = wrapper; 96 } 97 98 /** 99 * Creates an AndroidTargetData object. 100 * @param platformLibraries 101 * @param optionalLibraries 102 */ setExtraData(IResourceRepository systemResourceRepository, AndroidManifestDescriptors manifestDescriptors, LayoutDescriptors layoutDescriptors, MenuDescriptors menuDescriptors, XmlDescriptors xmlDescriptors, Map<String, Map<String, Integer>> enumValueMap, String[] permissionValues, String[] activityIntentActionValues, String[] broadcastIntentActionValues, String[] serviceIntentActionValues, String[] intentCategoryValues, String[] platformLibraries, IOptionalLibrary[] optionalLibraries, ProjectResources resources, LayoutBridge layoutBridge)103 void setExtraData(IResourceRepository systemResourceRepository, 104 AndroidManifestDescriptors manifestDescriptors, 105 LayoutDescriptors layoutDescriptors, 106 MenuDescriptors menuDescriptors, 107 XmlDescriptors xmlDescriptors, 108 Map<String, Map<String, Integer>> enumValueMap, 109 String[] permissionValues, 110 String[] activityIntentActionValues, 111 String[] broadcastIntentActionValues, 112 String[] serviceIntentActionValues, 113 String[] intentCategoryValues, 114 String[] platformLibraries, 115 IOptionalLibrary[] optionalLibraries, 116 ProjectResources resources, 117 LayoutBridge layoutBridge) { 118 119 mSystemResourceRepository = systemResourceRepository; 120 mManifestDescriptors = manifestDescriptors; 121 mLayoutDescriptors = layoutDescriptors; 122 mMenuDescriptors = menuDescriptors; 123 mXmlDescriptors = xmlDescriptors; 124 mEnumValueMap = enumValueMap; 125 mFrameworkResources = resources; 126 mLayoutBridge = layoutBridge; 127 128 setPermissions(permissionValues); 129 setIntentFilterActionsAndCategories(activityIntentActionValues, broadcastIntentActionValues, 130 serviceIntentActionValues, intentCategoryValues); 131 setOptionalLibraries(platformLibraries, optionalLibraries); 132 } 133 getDexWrapper()134 public DexWrapper getDexWrapper() { 135 return mDexWrapper; 136 } 137 getSystemResources()138 public IResourceRepository getSystemResources() { 139 return mSystemResourceRepository; 140 } 141 142 /** 143 * Returns an {@link IDescriptorProvider} from a given Id. 144 * The Id can be one of {@link #DESCRIPTOR_MANIFEST}, {@link #DESCRIPTOR_LAYOUT}, 145 * {@link #DESCRIPTOR_MENU}, or {@link #DESCRIPTOR_XML}. 146 * All other values will throw an {@link IllegalArgumentException}. 147 */ getDescriptorProvider(int descriptorId)148 public IDescriptorProvider getDescriptorProvider(int descriptorId) { 149 switch (descriptorId) { 150 case DESCRIPTOR_MANIFEST: 151 return mManifestDescriptors; 152 case DESCRIPTOR_LAYOUT: 153 return mLayoutDescriptors; 154 case DESCRIPTOR_MENU: 155 return mMenuDescriptors; 156 case DESCRIPTOR_XML: 157 return mXmlDescriptors; 158 case DESCRIPTOR_RESOURCES: 159 // FIXME: since it's hard-coded the Resources Descriptors are not platform dependent. 160 return ResourcesDescriptors.getInstance(); 161 case DESCRIPTOR_PREFERENCES: 162 return mXmlDescriptors.getPreferencesProvider(); 163 case DESCRIPTOR_APPWIDGET_PROVIDER: 164 return mXmlDescriptors.getAppWidgetProvider(); 165 case DESCRIPTOR_SEARCHABLE: 166 return mXmlDescriptors.getSearchableProvider(); 167 default : 168 throw new IllegalArgumentException(); 169 } 170 } 171 172 /** 173 * Returns the manifest descriptors. 174 */ getManifestDescriptors()175 public AndroidManifestDescriptors getManifestDescriptors() { 176 return mManifestDescriptors; 177 } 178 179 /** 180 * Returns the layout Descriptors. 181 */ getLayoutDescriptors()182 public LayoutDescriptors getLayoutDescriptors() { 183 return mLayoutDescriptors; 184 } 185 186 /** 187 * Returns the menu descriptors. 188 */ getMenuDescriptors()189 public MenuDescriptors getMenuDescriptors() { 190 return mMenuDescriptors; 191 } 192 193 /** 194 * Returns the XML descriptors 195 */ getXmlDescriptors()196 public XmlDescriptors getXmlDescriptors() { 197 return mXmlDescriptors; 198 } 199 200 /** 201 * Returns this list of possible values for an XML attribute. 202 * <p/>This should only be called for attributes for which possible values depend on the 203 * parent element node. 204 * <p/>For attributes that have the same values no matter the parent node, use 205 * {@link #getEnumValueMap()}. 206 * @param elementName the name of the element containing the attribute. 207 * @param attributeName the name of the attribute 208 * @return an array of String with the possible values, or <code>null</code> if no values were 209 * found. 210 */ getAttributeValues(String elementName, String attributeName)211 public String[] getAttributeValues(String elementName, String attributeName) { 212 String key = String.format("(%1$s,%2$s)", elementName, attributeName); //$NON-NLS-1$ 213 return mAttributeValues.get(key); 214 } 215 216 /** 217 * Returns this list of possible values for an XML attribute. 218 * <p/>This should only be called for attributes for which possible values depend on the 219 * parent and great-grand-parent element node. 220 * <p/>The typical example of this is for the 'name' attribute under 221 * activity/intent-filter/action 222 * <p/>For attributes that have the same values no matter the parent node, use 223 * {@link #getEnumValueMap()}. 224 * @param elementName the name of the element containing the attribute. 225 * @param attributeName the name of the attribute 226 * @param greatGrandParentElementName the great-grand-parent node. 227 * @return an array of String with the possible values, or <code>null</code> if no values were 228 * found. 229 */ getAttributeValues(String elementName, String attributeName, String greatGrandParentElementName)230 public String[] getAttributeValues(String elementName, String attributeName, 231 String greatGrandParentElementName) { 232 if (greatGrandParentElementName != null) { 233 String key = String.format("(%1$s,%2$s,%3$s)", //$NON-NLS-1$ 234 greatGrandParentElementName, elementName, attributeName); 235 String[] values = mAttributeValues.get(key); 236 if (values != null) { 237 return values; 238 } 239 } 240 241 return getAttributeValues(elementName, attributeName); 242 } 243 244 /** 245 * Returns the enum values map. 246 * <p/>The map defines the possible values for XML attributes. The key is the attribute name 247 * and the value is a map of (string, integer) in which the key (string) is the name of 248 * the value, and the Integer is the numerical value in the compiled binary XML files. 249 */ getEnumValueMap()250 public Map<String, Map<String, Integer>> getEnumValueMap() { 251 return mEnumValueMap; 252 } 253 254 /** 255 * Returns the {@link ProjectResources} containing the Framework Resources. 256 */ getFrameworkResources()257 public ProjectResources getFrameworkResources() { 258 return mFrameworkResources; 259 } 260 261 /** 262 * Returns a {@link LayoutBridge} object possibly containing a {@link ILayoutBridge} object. 263 * <p/>If {@link LayoutBridge#bridge} is <code>null</code>, {@link LayoutBridge#status} will 264 * contain the reason (either {@link LoadStatus#LOADING} or {@link LoadStatus#FAILED}). 265 * <p/>Valid {@link ILayoutBridge} objects are always initialized before being returned. 266 */ getLayoutBridge()267 public synchronized LayoutBridge getLayoutBridge() { 268 if (mLayoutBridgeInit == false && mLayoutBridge.bridge != null) { 269 mLayoutBridge.bridge.init(mTarget.getPath(IAndroidTarget.FONTS), 270 getEnumValueMap()); 271 mLayoutBridgeInit = true; 272 } 273 return mLayoutBridge; 274 } 275 276 /** 277 * Sets the permission values 278 * @param permissionValues the list of permissions 279 */ setPermissions(String[] permissionValues)280 private void setPermissions(String[] permissionValues) { 281 setValues("(uses-permission,android:name)", permissionValues); //$NON-NLS-1$ 282 setValues("(application,android:permission)", permissionValues); //$NON-NLS-1$ 283 setValues("(activity,android:permission)", permissionValues); //$NON-NLS-1$ 284 setValues("(receiver,android:permission)", permissionValues); //$NON-NLS-1$ 285 setValues("(service,android:permission)", permissionValues); //$NON-NLS-1$ 286 setValues("(provider,android:permission)", permissionValues); //$NON-NLS-1$ 287 } 288 setIntentFilterActionsAndCategories(String[] activityIntentActions, String[] broadcastIntentActions, String[] serviceIntentActions, String[] intentCategoryValues)289 private void setIntentFilterActionsAndCategories(String[] activityIntentActions, 290 String[] broadcastIntentActions, String[] serviceIntentActions, 291 String[] intentCategoryValues) { 292 setValues("(activity,action,android:name)", activityIntentActions); //$NON-NLS-1$ 293 setValues("(receiver,action,android:name)", broadcastIntentActions); //$NON-NLS-1$ 294 setValues("(service,action,android:name)", serviceIntentActions); //$NON-NLS-1$ 295 setValues("(category,android:name)", intentCategoryValues); //$NON-NLS-1$ 296 } 297 setOptionalLibraries(String[] platformLibraries, IOptionalLibrary[] optionalLibraries)298 private void setOptionalLibraries(String[] platformLibraries, 299 IOptionalLibrary[] optionalLibraries) { 300 301 ArrayList<String> libs = new ArrayList<String>(); 302 303 if (platformLibraries != null) { 304 for (String name : platformLibraries) { 305 libs.add(name); 306 } 307 } 308 309 if (optionalLibraries != null) { 310 for (int i = 0; i < optionalLibraries.length; i++) { 311 libs.add(optionalLibraries[i].getName()); 312 } 313 } 314 setValues("(uses-library,android:name)", libs.toArray(new String[libs.size()])); 315 } 316 317 /** 318 * Sets a (name, values) pair in the hash map. 319 * <p/> 320 * If the name is already present in the map, it is first removed. 321 * @param name the name associated with the values. 322 * @param values The values to add. 323 */ setValues(String name, String[] values)324 private void setValues(String name, String[] values) { 325 mAttributeValues.remove(name); 326 mAttributeValues.put(name, values); 327 } 328 } 329