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.common.rendering.LayoutLibrary; 20 import com.android.ide.common.rendering.api.LayoutLog; 21 import com.android.ide.common.resources.ResourceRepository; 22 import com.android.ide.common.sdk.LoadStatus; 23 import com.android.ide.eclipse.adt.AdtPlugin; 24 import com.android.ide.eclipse.adt.internal.editors.animator.AnimDescriptors; 25 import com.android.ide.eclipse.adt.internal.editors.animator.AnimatorDescriptors; 26 import com.android.ide.eclipse.adt.internal.editors.color.ColorDescriptors; 27 import com.android.ide.eclipse.adt.internal.editors.descriptors.IDescriptorProvider; 28 import com.android.ide.eclipse.adt.internal.editors.drawable.DrawableDescriptors; 29 import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.LayoutDescriptors; 30 import com.android.ide.eclipse.adt.internal.editors.manifest.descriptors.AndroidManifestDescriptors; 31 import com.android.ide.eclipse.adt.internal.editors.menu.descriptors.MenuDescriptors; 32 import com.android.ide.eclipse.adt.internal.editors.otherxml.descriptors.OtherXmlDescriptors; 33 import com.android.ide.eclipse.adt.internal.editors.values.descriptors.ValuesDescriptors; 34 import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources; 35 import com.android.sdklib.IAndroidTarget; 36 import com.android.sdklib.IAndroidTarget.IOptionalLibrary; 37 38 import org.eclipse.core.runtime.IStatus; 39 40 import java.io.File; 41 import java.util.ArrayList; 42 import java.util.Hashtable; 43 import java.util.Map; 44 45 /** 46 * This class contains the data of an Android Target as loaded from the SDK. 47 */ 48 public class AndroidTargetData { 49 50 public final static int DESCRIPTOR_MANIFEST = 1; 51 public final static int DESCRIPTOR_LAYOUT = 2; 52 public final static int DESCRIPTOR_MENU = 3; 53 public final static int DESCRIPTOR_OTHER_XML = 4; 54 public final static int DESCRIPTOR_RESOURCES = 5; 55 public final static int DESCRIPTOR_SEARCHABLE = 6; 56 public final static int DESCRIPTOR_PREFERENCES = 7; 57 public final static int DESCRIPTOR_APPWIDGET_PROVIDER = 8; 58 public final static int DESCRIPTOR_DRAWABLE = 9; 59 public final static int DESCRIPTOR_ANIMATOR = 10; 60 public final static int DESCRIPTOR_ANIM = 11; 61 public final static int DESCRIPTOR_COLOR = 12; 62 63 private final IAndroidTarget mTarget; 64 65 /** 66 * mAttributeValues is a map { key => list [ values ] }. 67 * The key for the map is "(element-xml-name,attribute-namespace:attribute-xml-local-name)". 68 * The attribute namespace prefix must be: 69 * - "android" for AndroidConstants.NS_RESOURCES 70 * - "xmlns" for the XMLNS URI. 71 * 72 * This is used for attributes that do not have a unique name, but still need to be populated 73 * with values in the UI. Uniquely named attributes have their values in {@link #mEnumValueMap}. 74 */ 75 private Hashtable<String, String[]> mAttributeValues = new Hashtable<String, String[]>(); 76 77 private AndroidManifestDescriptors mManifestDescriptors; 78 private DrawableDescriptors mDrawableDescriptors; 79 private AnimatorDescriptors mAnimatorDescriptors; 80 private AnimDescriptors mAnimDescriptors; 81 private ColorDescriptors mColorDescriptors; 82 private LayoutDescriptors mLayoutDescriptors; 83 private MenuDescriptors mMenuDescriptors; 84 private OtherXmlDescriptors mOtherXmlDescriptors; 85 86 private Map<String, Map<String, Integer>> mEnumValueMap; 87 88 private ResourceRepository mFrameworkResources; 89 private LayoutLibrary mLayoutLibrary; 90 91 private boolean mLayoutBridgeInit = false; 92 AndroidTargetData(IAndroidTarget androidTarget)93 AndroidTargetData(IAndroidTarget androidTarget) { 94 mTarget = androidTarget; 95 } 96 97 /** 98 * Creates an AndroidTargetData object. 99 */ setExtraData( AndroidManifestDescriptors manifestDescriptors, LayoutDescriptors layoutDescriptors, MenuDescriptors menuDescriptors, OtherXmlDescriptors otherXmlDescriptors, DrawableDescriptors drawableDescriptors, AnimatorDescriptors animatorDescriptors, AnimDescriptors animDescriptors, ColorDescriptors colorDescriptors, Map<String, Map<String, Integer>> enumValueMap, String[] permissionValues, String[] activityIntentActionValues, String[] broadcastIntentActionValues, String[] serviceIntentActionValues, String[] intentCategoryValues, String[] platformLibraries, IOptionalLibrary[] optionalLibraries, ResourceRepository frameworkResources, LayoutLibrary layoutLibrary)100 void setExtraData( 101 AndroidManifestDescriptors manifestDescriptors, 102 LayoutDescriptors layoutDescriptors, 103 MenuDescriptors menuDescriptors, 104 OtherXmlDescriptors otherXmlDescriptors, 105 DrawableDescriptors drawableDescriptors, 106 AnimatorDescriptors animatorDescriptors, 107 AnimDescriptors animDescriptors, 108 ColorDescriptors colorDescriptors, 109 Map<String, Map<String, Integer>> enumValueMap, 110 String[] permissionValues, 111 String[] activityIntentActionValues, 112 String[] broadcastIntentActionValues, 113 String[] serviceIntentActionValues, 114 String[] intentCategoryValues, 115 String[] platformLibraries, 116 IOptionalLibrary[] optionalLibraries, 117 ResourceRepository frameworkResources, 118 LayoutLibrary layoutLibrary) { 119 120 mManifestDescriptors = manifestDescriptors; 121 mDrawableDescriptors = drawableDescriptors; 122 mAnimatorDescriptors = animatorDescriptors; 123 mAnimDescriptors = animDescriptors; 124 mColorDescriptors = colorDescriptors; 125 mLayoutDescriptors = layoutDescriptors; 126 mMenuDescriptors = menuDescriptors; 127 mOtherXmlDescriptors = otherXmlDescriptors; 128 mEnumValueMap = enumValueMap; 129 mFrameworkResources = frameworkResources; 130 mLayoutLibrary = layoutLibrary; 131 132 setPermissions(permissionValues); 133 setIntentFilterActionsAndCategories(activityIntentActionValues, broadcastIntentActionValues, 134 serviceIntentActionValues, intentCategoryValues); 135 setOptionalLibraries(platformLibraries, optionalLibraries); 136 } 137 138 /** 139 * Returns an {@link IDescriptorProvider} from a given Id. 140 * The Id can be one of {@link #DESCRIPTOR_MANIFEST}, {@link #DESCRIPTOR_LAYOUT}, 141 * {@link #DESCRIPTOR_MENU}, or {@link #DESCRIPTOR_OTHER_XML}. 142 * All other values will throw an {@link IllegalArgumentException}. 143 */ getDescriptorProvider(int descriptorId)144 public IDescriptorProvider getDescriptorProvider(int descriptorId) { 145 switch (descriptorId) { 146 case DESCRIPTOR_MANIFEST: 147 return mManifestDescriptors; 148 case DESCRIPTOR_LAYOUT: 149 return mLayoutDescriptors; 150 case DESCRIPTOR_MENU: 151 return mMenuDescriptors; 152 case DESCRIPTOR_OTHER_XML: 153 return mOtherXmlDescriptors; 154 case DESCRIPTOR_RESOURCES: 155 // FIXME: since it's hard-coded the Resources Descriptors are not platform dependent. 156 return ValuesDescriptors.getInstance(); 157 case DESCRIPTOR_PREFERENCES: 158 return mOtherXmlDescriptors.getPreferencesProvider(); 159 case DESCRIPTOR_APPWIDGET_PROVIDER: 160 return mOtherXmlDescriptors.getAppWidgetProvider(); 161 case DESCRIPTOR_SEARCHABLE: 162 return mOtherXmlDescriptors.getSearchableProvider(); 163 case DESCRIPTOR_DRAWABLE: 164 return mDrawableDescriptors; 165 case DESCRIPTOR_ANIMATOR: 166 return mAnimatorDescriptors; 167 case DESCRIPTOR_ANIM: 168 return mAnimDescriptors; 169 case DESCRIPTOR_COLOR: 170 return mColorDescriptors; 171 default : 172 throw new IllegalArgumentException(); 173 } 174 } 175 176 /** 177 * Returns the manifest descriptors. 178 */ getManifestDescriptors()179 public AndroidManifestDescriptors getManifestDescriptors() { 180 return mManifestDescriptors; 181 } 182 183 /** 184 * Returns the drawable descriptors 185 */ getDrawableDescriptors()186 public DrawableDescriptors getDrawableDescriptors() { 187 return mDrawableDescriptors; 188 } 189 190 /** 191 * Returns the animation descriptors 192 */ getAnimDescriptors()193 public AnimDescriptors getAnimDescriptors() { 194 return mAnimDescriptors; 195 } 196 197 /** 198 * Returns the color descriptors 199 */ getColorDescriptors()200 public ColorDescriptors getColorDescriptors() { 201 return mColorDescriptors; 202 } 203 204 /** 205 * Returns the animator descriptors 206 */ getAnimatorDescriptors()207 public AnimatorDescriptors getAnimatorDescriptors() { 208 return mAnimatorDescriptors; 209 } 210 211 /** 212 * Returns the layout Descriptors. 213 */ getLayoutDescriptors()214 public LayoutDescriptors getLayoutDescriptors() { 215 return mLayoutDescriptors; 216 } 217 218 /** 219 * Returns the menu descriptors. 220 */ getMenuDescriptors()221 public MenuDescriptors getMenuDescriptors() { 222 return mMenuDescriptors; 223 } 224 225 /** 226 * Returns the XML descriptors 227 */ getXmlDescriptors()228 public OtherXmlDescriptors getXmlDescriptors() { 229 return mOtherXmlDescriptors; 230 } 231 232 /** 233 * Returns this list of possible values for an XML attribute. 234 * <p/>This should only be called for attributes for which possible values depend on the 235 * parent element node. 236 * <p/>For attributes that have the same values no matter the parent node, use 237 * {@link #getEnumValueMap()}. 238 * @param elementName the name of the element containing the attribute. 239 * @param attributeName the name of the attribute 240 * @return an array of String with the possible values, or <code>null</code> if no values were 241 * found. 242 */ getAttributeValues(String elementName, String attributeName)243 public String[] getAttributeValues(String elementName, String attributeName) { 244 String key = String.format("(%1$s,%2$s)", elementName, attributeName); //$NON-NLS-1$ 245 return mAttributeValues.get(key); 246 } 247 248 /** 249 * Returns this list of possible values for an XML attribute. 250 * <p/>This should only be called for attributes for which possible values depend on the 251 * parent and great-grand-parent element node. 252 * <p/>The typical example of this is for the 'name' attribute under 253 * activity/intent-filter/action 254 * <p/>For attributes that have the same values no matter the parent node, use 255 * {@link #getEnumValueMap()}. 256 * @param elementName the name of the element containing the attribute. 257 * @param attributeName the name of the attribute 258 * @param greatGrandParentElementName the great-grand-parent node. 259 * @return an array of String with the possible values, or <code>null</code> if no values were 260 * found. 261 */ getAttributeValues(String elementName, String attributeName, String greatGrandParentElementName)262 public String[] getAttributeValues(String elementName, String attributeName, 263 String greatGrandParentElementName) { 264 if (greatGrandParentElementName != null) { 265 String key = String.format("(%1$s,%2$s,%3$s)", //$NON-NLS-1$ 266 greatGrandParentElementName, elementName, attributeName); 267 String[] values = mAttributeValues.get(key); 268 if (values != null) { 269 return values; 270 } 271 } 272 273 return getAttributeValues(elementName, attributeName); 274 } 275 276 /** 277 * Returns the enum values map. 278 * <p/>The map defines the possible values for XML attributes. The key is the attribute name 279 * and the value is a map of (string, integer) in which the key (string) is the name of 280 * the value, and the Integer is the numerical value in the compiled binary XML files. 281 */ getEnumValueMap()282 public Map<String, Map<String, Integer>> getEnumValueMap() { 283 return mEnumValueMap; 284 } 285 286 /** 287 * Returns the {@link ProjectResources} containing the Framework Resources. 288 */ getFrameworkResources()289 public ResourceRepository getFrameworkResources() { 290 return mFrameworkResources; 291 } 292 293 /** 294 * Returns a {@link LayoutLibrary} object possibly containing a {@link LayoutBridge} object. 295 * <p/>If {@link LayoutLibrary#getBridge()} is <code>null</code>, 296 * {@link LayoutBridge#getStatus()} will contain the reason (either {@link LoadStatus#LOADING} 297 * or {@link LoadStatus#FAILED}). 298 * <p/>Valid {@link LayoutBridge} objects are always initialized before being returned. 299 */ getLayoutLibrary()300 public synchronized LayoutLibrary getLayoutLibrary() { 301 if (mLayoutBridgeInit == false && mLayoutLibrary.getStatus() == LoadStatus.LOADED) { 302 boolean ok = mLayoutLibrary.init( 303 mTarget.getProperties(), 304 new File(mTarget.getPath(IAndroidTarget.FONTS)), 305 getEnumValueMap(), 306 new LayoutLog() { 307 308 @Override 309 public void error(String tag, String message, Throwable throwable, 310 Object data) { 311 AdtPlugin.log(throwable, message); 312 } 313 314 @Override 315 public void error(String tag, String message, Object data) { 316 AdtPlugin.log(IStatus.ERROR, message); 317 } 318 319 @Override 320 public void warning(String tag, String message, Object data) { 321 AdtPlugin.log(IStatus.WARNING, message); 322 } 323 }); 324 if (!ok) { 325 AdtPlugin.log(IStatus.ERROR, 326 "LayoutLibrary initialization failed"); 327 } 328 mLayoutBridgeInit = true; 329 } 330 331 return mLayoutLibrary; 332 } 333 334 /** 335 * Sets the permission values 336 * @param permissionValues the list of permissions 337 */ setPermissions(String[] permissionValues)338 private void setPermissions(String[] permissionValues) { 339 setValues("(uses-permission,android:name)", permissionValues); //$NON-NLS-1$ 340 setValues("(application,android:permission)", permissionValues); //$NON-NLS-1$ 341 setValues("(activity,android:permission)", permissionValues); //$NON-NLS-1$ 342 setValues("(receiver,android:permission)", permissionValues); //$NON-NLS-1$ 343 setValues("(service,android:permission)", permissionValues); //$NON-NLS-1$ 344 setValues("(provider,android:permission)", permissionValues); //$NON-NLS-1$ 345 } 346 setIntentFilterActionsAndCategories(String[] activityIntentActions, String[] broadcastIntentActions, String[] serviceIntentActions, String[] intentCategoryValues)347 private void setIntentFilterActionsAndCategories(String[] activityIntentActions, 348 String[] broadcastIntentActions, String[] serviceIntentActions, 349 String[] intentCategoryValues) { 350 setValues("(activity,action,android:name)", activityIntentActions); //$NON-NLS-1$ 351 setValues("(receiver,action,android:name)", broadcastIntentActions); //$NON-NLS-1$ 352 setValues("(service,action,android:name)", serviceIntentActions); //$NON-NLS-1$ 353 setValues("(category,android:name)", intentCategoryValues); //$NON-NLS-1$ 354 } 355 setOptionalLibraries(String[] platformLibraries, IOptionalLibrary[] optionalLibraries)356 private void setOptionalLibraries(String[] platformLibraries, 357 IOptionalLibrary[] optionalLibraries) { 358 359 ArrayList<String> libs = new ArrayList<String>(); 360 361 if (platformLibraries != null) { 362 for (String name : platformLibraries) { 363 libs.add(name); 364 } 365 } 366 367 if (optionalLibraries != null) { 368 for (int i = 0; i < optionalLibraries.length; i++) { 369 libs.add(optionalLibraries[i].getName()); 370 } 371 } 372 setValues("(uses-library,android:name)", libs.toArray(new String[libs.size()])); 373 } 374 375 /** 376 * Sets a (name, values) pair in the hash map. 377 * <p/> 378 * If the name is already present in the map, it is first removed. 379 * @param name the name associated with the values. 380 * @param values The values to add. 381 */ setValues(String name, String[] values)382 private void setValues(String name, String[] values) { 383 mAttributeValues.remove(name); 384 mAttributeValues.put(name, values); 385 } 386 dispose()387 public void dispose() { 388 if (mLayoutLibrary != null) { 389 mLayoutLibrary.dispose(); 390 } 391 } 392 } 393