/** * GRANITE DATA SERVICES * Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S. * * This file is part of the Granite Data Services Platform. * * Granite Data Services is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * Granite Data Services is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA, or see <http://www.gnu.org/licenses/>. */ package org.granite.builder; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.granite.builder.properties.Gas3Classpath; import org.granite.builder.properties.Gas3Project; import org.granite.builder.properties.Gas3Source; import org.granite.builder.properties.Gas3Translator; import org.granite.builder.properties.GraniteProperties; import org.granite.builder.properties.GranitePropertiesLoader; import org.granite.builder.util.BuilderUtil; import org.granite.builder.util.JavaClassInfo; import org.granite.builder.util.ProjectUtil; import org.granite.builder.util.ProjectUtil.CpEntry; import org.granite.builder.util.ProjectUtil.CpEntry.CpeKind; import org.granite.generator.Listener; import org.granite.generator.TemplateUri; import org.granite.generator.as3.As3TypeFactory; import org.granite.generator.as3.DefaultAs3TypeFactory; import org.granite.generator.as3.DefaultEntityFactory; import org.granite.generator.as3.EntityFactory; import org.granite.generator.as3.JavaAs3GroovyConfiguration; import org.granite.generator.as3.JavaAs3Input; import org.granite.generator.as3.PackageTranslator; import org.granite.generator.as3.RemoteDestinationFactory; import org.granite.generator.as3.reflect.JavaType.Kind; import org.granite.generator.gsp.GroovyTemplateFactory; /** * @author Franck WOLFF */ public class BuilderConfiguration implements JavaAs3GroovyConfiguration { private final IProject project; private final Map<Class<?>, Boolean> generatedClassCache = new HashMap<Class<?>, Boolean>(); private final Map<String, BuilderConfiguration> dependentProjectConfigurations = new HashMap<String, BuilderConfiguration>(); private IJavaProject javaProject = null; private GraniteProperties properties = null; private As3TypeFactory clientTypeFactory = null; private EntityFactory entityFactory = null; private RemoteDestinationFactory remoteDestinationFactory = null; private GroovyTemplateFactory groovyTemplateFactory = null; private ClassLoader loader = null; private List<PackageTranslator> translators = null; private Listener listener = null; public BuilderConfiguration(Listener listener, IProject project) { this.listener = listener; this.project = project; } public boolean isOutdated() { return GranitePropertiesLoader.isOutdated(project, getProperties()); } public IProject getProject() { return project; } public IJavaProject getJavaProject() { if (javaProject == null) { javaProject = JavaCore.create(project); if (javaProject == null) { throw new RuntimeException( new CoreException(ProjectUtil.createErrorStatus("Not a Java Project: " + project, null)) ); } } return javaProject; } public GraniteProperties getProperties() { if (properties == null) { try { properties = GranitePropertiesLoader.load(project); } catch (IOException e) { throw new RuntimeException( new CoreException( ProjectUtil.createErrorStatus("Could not load Granite properties for: " + project, e )) ); } } return properties; } @Override public As3TypeFactory getAs3TypeFactory() { if (clientTypeFactory == null) { String factoryClass = getProperties().getGas3().getAs3TypeFactory(); if (factoryClass != null) { try { clientTypeFactory = BuilderUtil.newInstance(As3TypeFactory.class, factoryClass, getClassLoader()); clientTypeFactory.configure( getProperties().getGas3().isExternalizeLong(), getProperties().getGas3().isExternalizeBigInteger(), getProperties().getGas3().isExternalizeBigDecimal() ); } catch (Exception e) { throw new RuntimeException( new CoreException( ProjectUtil.createErrorStatus("Could not load As3TypeFactory class: " + factoryClass, e )) ); } } else clientTypeFactory = new DefaultAs3TypeFactory(); } return clientTypeFactory; } @Override public EntityFactory getEntityFactory() { if (entityFactory == null) { String factoryClass = getProperties().getGas3().getEntityFactory(); if (factoryClass != null) { try { entityFactory = BuilderUtil.newInstance(EntityFactory.class, factoryClass, getClassLoader()); } catch (Exception e) { throw new RuntimeException( new CoreException( ProjectUtil.createErrorStatus("Could not load EntityFactory class: " + factoryClass, e )) ); } } else entityFactory = new DefaultEntityFactory(); } return entityFactory; } @Override public RemoteDestinationFactory getRemoteDestinationFactory() { if (remoteDestinationFactory == null) { String factoryClass = getProperties().getGas3().getRemoteDestinationFactory(); if (factoryClass != null) { try { remoteDestinationFactory = BuilderUtil.newInstance(RemoteDestinationFactory.class, factoryClass, getClassLoader()); } catch (Exception e) { throw new RuntimeException( new CoreException( ProjectUtil.createErrorStatus("Could not load RemoteDestinationFactory class: " + factoryClass, e )) ); } } } return remoteDestinationFactory; } @Override public File getBaseOutputDir(JavaAs3Input input) { BuilderJavaClientInput builderInput = (BuilderJavaClientInput)input; return new File(ProjectUtil.getProjectFile(project), builderInput.getGas3Source().getBaseOutputDir(true)); } @Override public File getOutputDir(JavaAs3Input input) { BuilderJavaClientInput builderInput = (BuilderJavaClientInput)input; return new File(ProjectUtil.getProjectFile(project), builderInput.getGas3Source().getOutputDir()); } @Override public TemplateUri[] getTemplateUris(Kind kind, Class<?> clazz) { return getProperties().getGas3().getMatchingTemplateUris(kind); } @Override public List<PackageTranslator> getTranslators() { if (translators == null) { if (getProperties().getGas3().getTranslators().isEmpty()) translators = Collections.emptyList(); else { translators = new ArrayList<PackageTranslator>(getProperties().getGas3().getTranslators().size()); for (Gas3Translator translator : getProperties().getGas3().getTranslators()) translators.add(translator.getPackageTranslator()); } } return translators; } public PackageTranslator getPackageTranslator(String packageName) { PackageTranslator translator = null; int weight = 0; for (PackageTranslator t : getTranslators()) { int w = t.match(packageName); if (w > weight) { weight = w; translator = t; } } return translator; } @Override public String getUid() { return getProperties().getGas3().getUid(); } @Override public boolean isGenerated(Class<?> clazz) { if (!getClassLoader().equals(clazz.getClassLoader()) || (clazz.isMemberClass() && !clazz.isEnum())) return false; Boolean generated = generatedClassCache.get(clazz); if (generated == null) { generated = Boolean.FALSE; JavaClassInfo info = ProjectUtil.getJavaClassInfo(getJavaProject(), clazz); if (info != null) { Gas3Source source = getProperties().getGas3().getMatchingSource( info.getSourceFolderPath(), info.getSourceFilePath() ); generated = Boolean.valueOf(source != null); } else { for (Gas3Project gas3Project : getProperties().getGas3().getProjects()) { IProject dependentProject = ProjectUtil.getProject(getJavaProject().getProject(), gas3Project.getPath()); try { if (ProjectUtil.isGraniteProject(dependentProject)) { BuilderConfiguration configuration = dependentProjectConfigurations.get(dependentProject.getName()); if (configuration == null) { configuration = new BuilderConfiguration(listener, dependentProject); dependentProjectConfigurations.put(dependentProject.getName(), configuration); } info = ProjectUtil.getJavaClassInfo(configuration.getJavaProject(), clazz); if (info != null) { Gas3Source source = configuration.getProperties().getGas3().getMatchingSource( info.getSourceFolderPath(), info.getSourceFilePath() ); generated = Boolean.valueOf(source != null); } } } catch (Exception e) { // ignore??? } } } generatedClassCache.put(clazz, generated); } return generated.booleanValue(); } @Override public GroovyTemplateFactory getGroovyTemplateFactory() { if (groovyTemplateFactory == null) groovyTemplateFactory = new GroovyTemplateFactory(); return groovyTemplateFactory; } public void resetClassLoader() { generatedClassCache.clear(); dependentProjectConfigurations.clear(); loader = null; } @Override public ClassLoader getClassLoader() { if (loader == null) { try { List<URL> classpath = new ArrayList<URL>(); for (CpEntry entry : ProjectUtil.getFullResolvedClasspath(getJavaProject())) { if (entry.getKind() == CpeKind.CONTAINER_JAR) { for (CpEntry cEntry : entry.getChildren()) addToClasspath(classpath, cEntry.toURL()); } else addToClasspath(classpath, entry.toURL()); } for (Gas3Classpath gas3Classpath : getProperties().getGas3().getClasspaths()) { File file = new File(gas3Classpath.getPath()); if (file.exists()) { try { addToClasspath(classpath, file.toURI().toURL()); } catch (MalformedURLException e) { // Should never happen... } } } for (Gas3Project gas3Project : getProperties().getGas3().getProjects()) { IProject dependentProject = ProjectUtil.getProject(getJavaProject().getProject(), gas3Project.getPath()); if (ProjectUtil.isGraniteProject(dependentProject)) { for (CpEntry entry : ProjectUtil.getFullResolvedClasspath(JavaCore.create(dependentProject))) { if (entry.getKind() == CpeKind.CONTAINER_JAR) { for (CpEntry cEntry : entry.getChildren()) addToClasspath(classpath, cEntry.toURL()); } else addToClasspath(classpath, entry.toURL()); } } } if (getProperties().getGas3().isDebugEnabled()) { listener.debug("Using classpath: {"); for (URL url : classpath) listener.debug(" " + (url != null ? url.toString() : "<null>")); listener.debug("}"); } loader = URLClassLoader.newInstance( classpath.toArray(new URL[classpath.size()]), new BuilderParentClassLoader() ); } catch (Exception e) { throw new RuntimeException(e); } } return loader; } private void addToClasspath(List<URL> classpath, URL url) { if (!classpath.contains(url)) classpath.add(url); } @Override public File getWorkingDirectory() { return ProjectUtil.getProjectFile(project); } }