001 /*
002 GRANITE DATA SERVICES
003 Copyright (C) 2007-2010 ADEQUATE SYSTEMS SARL
004
005 This file is part of Granite Data Services.
006
007 Granite Data Services is free software; you can redistribute it and/or modify
008 it under the terms of the GNU Library General Public License as published by
009 the Free Software Foundation; either version 2 of the License, or (at your
010 option) any later version.
011
012 Granite Data Services is distributed in the hope that it will be useful, but
013 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015 for more details.
016
017 You should have received a copy of the GNU Library General Public License
018 along with this library; if not, see <http://www.gnu.org/licenses/>.
019 */
020
021 package org.granite.builder;
022
023 import java.io.File;
024 import java.io.IOException;
025 import java.net.MalformedURLException;
026 import java.net.URL;
027 import java.net.URLClassLoader;
028 import java.util.ArrayList;
029 import java.util.Collections;
030 import java.util.HashMap;
031 import java.util.List;
032 import java.util.Map;
033
034 import org.eclipse.core.resources.IProject;
035 import org.eclipse.core.runtime.CoreException;
036 import org.eclipse.jdt.core.IJavaProject;
037 import org.eclipse.jdt.core.JavaCore;
038 import org.granite.builder.properties.Gas3Classpath;
039 import org.granite.builder.properties.Gas3Project;
040 import org.granite.builder.properties.Gas3Source;
041 import org.granite.builder.properties.Gas3Translator;
042 import org.granite.builder.properties.GraniteProperties;
043 import org.granite.builder.properties.GranitePropertiesLoader;
044 import org.granite.builder.util.BuilderUtil;
045 import org.granite.builder.util.JavaClassInfo;
046 import org.granite.builder.util.ProjectUtil;
047 import org.granite.builder.util.ProjectUtil.CpEntry;
048 import org.granite.builder.util.ProjectUtil.CpEntry.CpeKind;
049 import org.granite.generator.Listener;
050 import org.granite.generator.TemplateUri;
051 import org.granite.generator.as3.As3TypeFactory;
052 import org.granite.generator.as3.DefaultAs3TypeFactory;
053 import org.granite.generator.as3.DefaultEntityFactory;
054 import org.granite.generator.as3.EntityFactory;
055 import org.granite.generator.as3.JavaAs3GroovyConfiguration;
056 import org.granite.generator.as3.JavaAs3Input;
057 import org.granite.generator.as3.PackageTranslator;
058 import org.granite.generator.as3.RemoteDestinationFactory;
059 import org.granite.generator.as3.reflect.JavaType.Kind;
060 import org.granite.generator.gsp.GroovyTemplateFactory;
061
062 /**
063 * @author Franck WOLFF
064 */
065 public class BuilderConfiguration implements JavaAs3GroovyConfiguration {
066
067 private final IProject project;
068 private final Map<Class<?>, Boolean> generatedClassCache = new HashMap<Class<?>, Boolean>();
069 private final Map<String, BuilderConfiguration> dependentProjectConfigurations = new HashMap<String, BuilderConfiguration>();
070
071 private IJavaProject javaProject = null;
072 private GraniteProperties properties = null;
073 private As3TypeFactory as3TypeFactory = null;
074 private EntityFactory entityFactory = null;
075 private RemoteDestinationFactory remoteDestinationFactory = null;
076 private GroovyTemplateFactory groovyTemplateFactory = null;
077 private ClassLoader loader = null;
078 private List<PackageTranslator> translators = null;
079 private Listener listener = null;
080
081 public BuilderConfiguration(Listener listener, IProject project) {
082 this.listener = listener;
083 this.project = project;
084 }
085
086 public boolean isOutdated() {
087 return GranitePropertiesLoader.isOutdated(project, getProperties());
088 }
089
090 public IProject getProject() {
091 return project;
092 }
093
094 public IJavaProject getJavaProject() {
095 if (javaProject == null) {
096 javaProject = JavaCore.create(project);
097 if (javaProject == null) {
098 throw new RuntimeException(
099 new CoreException(ProjectUtil.createErrorStatus("Not a Java Project: " + project, null))
100 );
101 }
102 }
103 return javaProject;
104 }
105
106 public GraniteProperties getProperties() {
107 if (properties == null) {
108 try {
109 properties = GranitePropertiesLoader.load(project);
110 } catch (IOException e) {
111 throw new RuntimeException(
112 new CoreException(
113 ProjectUtil.createErrorStatus("Could not load Granite properties for: " + project,
114 e
115 ))
116 );
117 }
118 }
119 return properties;
120 }
121
122 public As3TypeFactory getAs3TypeFactory() {
123 if (as3TypeFactory == null) {
124 String factoryClass = getProperties().getGas3().getAs3TypeFactory();
125 if (factoryClass != null) {
126 try {
127 as3TypeFactory = BuilderUtil.newInstance(As3TypeFactory.class, factoryClass, getClassLoader());
128 as3TypeFactory.configure(
129 getProperties().getGas3().isExternalizeLong(),
130 getProperties().getGas3().isExternalizeBigInteger(),
131 getProperties().getGas3().isExternalizeBigDecimal()
132 );
133 } catch (Exception e) {
134 throw new RuntimeException(
135 new CoreException(
136 ProjectUtil.createErrorStatus("Could not load As3TypeFactory class: " + factoryClass,
137 e
138 ))
139 );
140 }
141 }
142 else
143 as3TypeFactory = new DefaultAs3TypeFactory();
144 }
145 return as3TypeFactory;
146 }
147
148 public EntityFactory getEntityFactory() {
149 if (entityFactory == null) {
150 String factoryClass = getProperties().getGas3().getEntityFactory();
151 if (factoryClass != null) {
152 try {
153 entityFactory = BuilderUtil.newInstance(EntityFactory.class, factoryClass, getClassLoader());
154 } catch (Exception e) {
155 throw new RuntimeException(
156 new CoreException(
157 ProjectUtil.createErrorStatus("Could not load EntityFactory class: " + factoryClass,
158 e
159 ))
160 );
161 }
162 }
163 else
164 entityFactory = new DefaultEntityFactory();
165 }
166 return entityFactory;
167 }
168
169 public RemoteDestinationFactory getRemoteDestinationFactory() {
170 if (remoteDestinationFactory == null) {
171 String factoryClass = getProperties().getGas3().getRemoteDestinationFactory();
172 if (factoryClass != null) {
173 try {
174 remoteDestinationFactory = BuilderUtil.newInstance(RemoteDestinationFactory.class, factoryClass, getClassLoader());
175 } catch (Exception e) {
176 throw new RuntimeException(
177 new CoreException(
178 ProjectUtil.createErrorStatus("Could not load RemoteDestinationFactory class: " + factoryClass,
179 e
180 ))
181 );
182 }
183 }
184 }
185 return remoteDestinationFactory;
186 }
187
188 public File getBaseOutputDir(JavaAs3Input input) {
189 BuilderJavaAs3Input builderInput = (BuilderJavaAs3Input)input;
190 return new File(ProjectUtil.getProjectFile(project), builderInput.getGas3Source().getBaseOutputDir(true));
191 }
192
193 public File getOutputDir(JavaAs3Input input) {
194 BuilderJavaAs3Input builderInput = (BuilderJavaAs3Input)input;
195 return new File(ProjectUtil.getProjectFile(project), builderInput.getGas3Source().getOutputDir());
196 }
197
198 public TemplateUri[] getTemplateUris(Kind kind, Class<?> clazz) {
199 return getProperties().getGas3().getMatchingTemplateUris(kind);
200 }
201
202 public List<PackageTranslator> getTranslators() {
203 if (translators == null) {
204 if (getProperties().getGas3().getTranslators().isEmpty())
205 translators = Collections.emptyList();
206 else {
207 translators = new ArrayList<PackageTranslator>(getProperties().getGas3().getTranslators().size());
208 for (Gas3Translator translator : getProperties().getGas3().getTranslators())
209 translators.add(translator.getPackageTranslator());
210 }
211 }
212 return translators;
213 }
214
215 public String getUid() {
216 return getProperties().getGas3().getUid();
217 }
218
219 public boolean isGenerated(Class<?> clazz) {
220 if (!getClassLoader().equals(clazz.getClassLoader()) || (clazz.isMemberClass() && !clazz.isEnum()))
221 return false;
222
223 Boolean generated = generatedClassCache.get(clazz);
224 if (generated == null) {
225 generated = Boolean.FALSE;
226
227 JavaClassInfo info = ProjectUtil.getJavaClassInfo(getJavaProject(), clazz);
228 if (info != null) {
229 Gas3Source source = getProperties().getGas3().getMatchingSource(
230 info.getSourceFolderPath(),
231 info.getSourceFilePath()
232 );
233 generated = Boolean.valueOf(source != null);
234 }
235 else {
236 for (Gas3Project gas3Project : getProperties().getGas3().getProjects()) {
237 IProject dependentProject = ProjectUtil.getProject(getJavaProject().getProject(), gas3Project.getPath());
238 try {
239 if (ProjectUtil.isGraniteProject(dependentProject)) {
240 BuilderConfiguration configuration = dependentProjectConfigurations.get(dependentProject.getName());
241 if (configuration == null) {
242 configuration = new BuilderConfiguration(listener, dependentProject);
243 dependentProjectConfigurations.put(dependentProject.getName(), configuration);
244 }
245 info = ProjectUtil.getJavaClassInfo(configuration.getJavaProject(), clazz);
246 if (info != null) {
247 Gas3Source source = configuration.getProperties().getGas3().getMatchingSource(
248 info.getSourceFolderPath(),
249 info.getSourceFilePath()
250 );
251 generated = Boolean.valueOf(source != null);
252 }
253 }
254 } catch (Exception e) {
255 // ignore???
256 }
257 }
258 }
259 generatedClassCache.put(clazz, generated);
260 }
261
262 return generated.booleanValue();
263 }
264
265 public GroovyTemplateFactory getGroovyTemplateFactory() {
266 if (groovyTemplateFactory == null)
267 groovyTemplateFactory = new GroovyTemplateFactory();
268 return groovyTemplateFactory;
269 }
270
271 public void resetClassLoader() {
272 generatedClassCache.clear();
273 dependentProjectConfigurations.clear();
274 loader = null;
275 }
276
277 public ClassLoader getClassLoader() {
278 if (loader == null) {
279 try {
280 List<URL> classpath = new ArrayList<URL>();
281 for (CpEntry entry : ProjectUtil.getFullClasspath(getJavaProject())) {
282 if (entry.getKind() == CpeKind.CONTAINER_JAR) {
283 for (CpEntry cEntry : entry.getChildren())
284 classpath.add(cEntry.toURL());
285 }
286 else
287 classpath.add(entry.toURL());
288 }
289
290 for (Gas3Classpath gas3Classpath : getProperties().getGas3().getClasspaths()) {
291 File file = new File(gas3Classpath.getPath());
292 if (file.exists()) {
293 try {
294 classpath.add(file.toURI().toURL());
295 } catch (MalformedURLException e) {
296 // Should never happen...
297 }
298 }
299 }
300
301 for (Gas3Project gas3Project : getProperties().getGas3().getProjects()) {
302 IProject dependentProject = ProjectUtil.getProject(getJavaProject().getProject(), gas3Project.getPath());
303 if (ProjectUtil.isGraniteProject(dependentProject)) {
304 for (CpEntry entry : ProjectUtil.getFullClasspath(JavaCore.create(dependentProject))) {
305 if (entry.getKind() == CpeKind.CONTAINER_JAR) {
306 for (CpEntry cEntry : entry.getChildren())
307 classpath.add(cEntry.toURL());
308 }
309 else
310 classpath.add(entry.toURL());
311 }
312 }
313 }
314
315 if (getProperties().getGas3().isDebugEnabled()) {
316 listener.debug("Using classpath: {");
317 for (URL url : classpath)
318 listener.debug(" " + (url != null ? url.toString() : "<null>"));
319 listener.debug("}");
320 }
321
322 loader = URLClassLoader.newInstance(
323 classpath.toArray(new URL[classpath.size()]),
324 new BuilderParentClassLoader()
325 );
326 } catch (Exception e) {
327 throw new RuntimeException(e);
328 }
329 }
330 return loader;
331 }
332 }