/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.providers;
import com.google.common.io.Resources;
import org.reflections.Reflections;
import org.reflections.scanners.SubTypesScanner;
import org.reflections.scanners.TypeAnnotationsScanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import org.stringtemplate.v4.ST;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import static java.nio.charset.StandardCharsets.UTF_8;
/**
* Generate implementation for {@link DynaProvider}.
* Find all types annotated with {@link DynaObject} and add {@link com.google.inject.Provider} for them to {@link DynaProvider} implementation.
*
* @author Evgen Vidolob
*/
public class DynaProviderGenerator {
private static final String TEMPLATE_PATH =
"/".concat(DynaProviderGenerator.class.getPackage().getName().replace(".", "/")).concat("/DynaProvider.st");
/**
* String template instance used
*/
private ST st;
private final String packageName;
private final String className;
private final List<String> classpath;
private List<ClassModel> dynaClasses;
public DynaProviderGenerator(String packageName, String className, List<String> classpath) {
this.packageName = packageName;
this.className = className;
this.classpath = classpath;
}
public String generate() throws IOException {
dynaClasses = new ArrayList<>();
findDynaObjects();
ST st = getTemplate();
st.add("packageName", packageName);
st.add("className", className);
st.add("classes", dynaClasses);
return st.render();
}
private void findDynaObjects() throws IOException {
ConfigurationBuilder configuration = new ConfigurationBuilder();
List<URL> urls = new ArrayList<>();
for (String element : classpath) {
urls.add(new File(element).toURI().toURL());
}
ClassLoader contextClassLoader = URLClassLoader.newInstance(
urls.toArray(new URL[urls.size()]),
Thread.currentThread().getContextClassLoader());
Thread.currentThread().setContextClassLoader(contextClassLoader);
configuration.setUrls(ClasspathHelper.forClassLoader(contextClassLoader));
configuration.setScanners(new SubTypesScanner(),
new TypeAnnotationsScanner());
Reflections reflection = new Reflections(configuration);
Set<Class<?>> classes = reflection.getTypesAnnotatedWith(DynaObject.class);
for (Class clazz : classes) {
//accept only classes
if (clazz.isEnum() || clazz.isInterface() || clazz.isAnnotation()) {
continue;
}
dynaClasses.add(new ClassModel(clazz));
System.out.println(String.format("New Dyna Object Found: %s", clazz.getCanonicalName()));
}
System.out.println(String.format("Found: %d Dyna Objects", dynaClasses.size()));
}
/**
* Get the template for provider
* @return the String Template
*/
protected ST getTemplate() {
if (st == null) {
URL url = Resources.getResource(DynaProviderGenerator.class, TEMPLATE_PATH);
try {
st = new ST(Resources.toString(url, UTF_8));
} catch (IOException e) {
throw new IllegalArgumentException("Unable to read template", e);
}
}
return st;
}
}