• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.editors.layout;
18 
19 import com.android.ide.eclipse.adt.AdtPlugin;
20 import com.android.ide.eclipse.adt.AndroidConstants;
21 import com.android.ide.eclipse.adt.internal.project.AndroidManifestParser;
22 import com.android.ide.eclipse.adt.internal.resources.manager.ProjectClassLoader;
23 import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
24 import com.android.layoutlib.api.IProjectCallback;
25 
26 import org.eclipse.core.resources.IFile;
27 import org.eclipse.core.resources.IProject;
28 import org.eclipse.core.runtime.CoreException;
29 
30 import java.lang.reflect.Constructor;
31 import java.util.HashMap;
32 
33 /**
34  * Loader for Android Project class in order to use them in the layout editor.
35  */
36 public final class ProjectCallback implements IProjectCallback {
37 
38     private final HashMap<String, Class<?>> mLoadedClasses = new HashMap<String, Class<?>>();
39     private final IProject mProject;
40     private final ClassLoader mParentClassLoader;
41     private final ProjectResources mProjectRes;
42     private boolean mUsed = false;
43     private String mNamespace;
44 
ProjectCallback(ClassLoader classLoader, ProjectResources projectRes, IProject project)45     ProjectCallback(ClassLoader classLoader, ProjectResources projectRes, IProject project) {
46         mParentClassLoader = classLoader;
47         mProjectRes = projectRes;
48         mProject = project;
49     }
50 
51 
52     /**
53      * {@inheritDoc}
54      *
55      * This implementation goes through the output directory of the Eclipse project and loads the
56      * <code>.class</code> file directly.
57      */
58     @SuppressWarnings("unchecked")
loadView(String className, Class[] constructorSignature, Object[] constructorParameters)59     public Object loadView(String className, Class[] constructorSignature,
60             Object[] constructorParameters)
61             throws ClassNotFoundException, Exception {
62 
63         // look for a cached version
64         Class<?> clazz = mLoadedClasses.get(className);
65         if (clazz != null) {
66             return instantiateClass(clazz, constructorSignature, constructorParameters);
67         }
68 
69         // load the class.
70         ProjectClassLoader loader = new ProjectClassLoader(mParentClassLoader, mProject);
71         try {
72             clazz = loader.loadClass(className);
73 
74             if (clazz != null) {
75                 mUsed = true;
76                 mLoadedClasses.put(className, clazz);
77                 return instantiateClass(clazz, constructorSignature, constructorParameters);
78             }
79         } catch (Error e) {
80             // Log this error with the class name we're trying to load and abort.
81             AdtPlugin.log(e, "ProjectCallback.loadView failed to find class %1$s", className); //$NON-NLS-1$
82         }
83 
84         return null;
85     }
86 
87     /**
88      * Returns the namespace for the project. The namespace contains a standard part + the
89      * application package.
90      *
91      * @return The package namespace of the project or null in case of error.
92      */
getNamespace()93     public String getNamespace() {
94         if (mNamespace == null) {
95             IFile manifestFile = AndroidManifestParser.getManifest(mProject);
96             try {
97                 AndroidManifestParser data = AndroidManifestParser.parseForData(manifestFile);
98                 String javaPackage = data.getPackage();
99                 mNamespace = String.format(AndroidConstants.NS_CUSTOM_RESOURCES, javaPackage);
100             } catch (CoreException e) {
101             }
102         }
103 
104         return mNamespace;
105     }
106 
107     /*
108      * (non-Javadoc)
109      * @see com.android.layoutlib.api.IProjectCallback#resolveResourceValue(int)
110      */
resolveResourceValue(int id)111     public String[] resolveResourceValue(int id) {
112         if (mProjectRes != null) {
113             return mProjectRes.resolveResourceValue(id);
114         }
115 
116         return null;
117     }
118 
119     /*
120      * (non-Javadoc)
121      * @see com.android.layoutlib.api.IProjectCallback#resolveResourceValue(int[])
122      */
resolveResourceValue(int[] id)123     public String resolveResourceValue(int[] id) {
124         if (mProjectRes != null) {
125             return mProjectRes.resolveResourceValue(id);
126         }
127 
128         return null;
129     }
130 
131     /*
132      * (non-Javadoc)
133      * @see com.android.layoutlib.api.IProjectCallback#getResourceValue(java.lang.String, java.lang.String)
134      */
getResourceValue(String type, String name)135     public Integer getResourceValue(String type, String name) {
136         if (mProjectRes != null) {
137             return mProjectRes.getResourceValue(type, name);
138         }
139 
140         return null;
141     }
142 
143     /**
144      * Returns whether the loader has received requests to load custom views.
145      * <p/>This allows to efficiently only recreate when needed upon code change in the project.
146      */
isUsed()147     boolean isUsed() {
148         return mUsed;
149     }
150 
151     /**
152      * Instantiate a class object, using a specific constructor and parameters.
153      * @param clazz the class to instantiate
154      * @param constructorSignature the signature of the constructor to use
155      * @param constructorParameters the parameters to use in the constructor.
156      * @return A new class object, created using a specific constructor and parameters.
157      * @throws Exception
158      */
159     @SuppressWarnings("unchecked")
instantiateClass(Class<?> clazz, Class[] constructorSignature, Object[] constructorParameters)160     private Object instantiateClass(Class<?> clazz, Class[] constructorSignature,
161             Object[] constructorParameters) throws Exception {
162         Constructor<?> constructor = clazz.getConstructor(constructorSignature);
163         constructor.setAccessible(true);
164         return constructor.newInstance(constructorParameters);
165     }
166 }
167