/******************************************************************************* * 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.util; import org.apache.commons.io.FileUtils; import org.eclipse.che.ide.api.extension.ExtensionGinModule; import org.reflections.Reflections; import java.io.File; import java.io.IOException; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import static org.eclipse.che.util.IgnoreUnExistedResourcesReflectionConfigurationBuilder.*; /** * This class looks for all the Gin Modules annotated with ExtensionGinModule annotation * and adds all them to IDEInjector class. * * @author <a href="mailto:nzamosenchuk@exoplatform.com">Nikolay Zamosenchuk</a> */ public class IDEInjectorGenerator { /** Set containing all the FQNs of GinModules */ public static final Set<String> EXTENSIONS_FQN = new HashSet<>(); /** Annotation to look for */ protected static final String GIN_MODULE_ANNOTATION = "@ExtensionGinModule"; /** * Path of the output class, it definitely should already exits. To ensure proper config. * File content will be overridden. */ protected static final String IDE_INJECTOR_PATH = "org/eclipse/che/ide/client/inject/IDEInjector.java"; /** * Entry point. --rootDir is the optional parameter. * * @param args * @throws IOException */ public static void main(String[] args) throws IOException { File rootFolder = GeneratorUtils.getRootFolder(args); System.out.println(" ------------------------------------------------------------------------ "); System.out.println(String.format("Searching for GinModules in %s", rootFolder.getAbsolutePath())); System.out.println(" ------------------------------------------------------------------------ "); // find all Extension FQNs findGinModules(rootFolder); generateExtensionManager(rootFolder); } /** * Generate to source of the Class * * @param rootFolder */ public static void generateExtensionManager(File rootFolder) throws IOException { File extManager = new File(rootFolder, IDE_INJECTOR_PATH); StringBuilder builder = new StringBuilder(); // declare package name builder.append("package org.eclipse.che.ide.client.inject;\n\n"); // declare imports builder.append("import org.eclipse.che.ide.client.BootstrapController;\n"); builder.append("import com.google.gwt.inject.client.GinModules;\n"); builder.append("import com.google.gwt.inject.client.Ginjector;\n"); builder.append("\n"); // declare class Javadoc builder.append("/**\n"); builder.append(" * THIS CLASS WILL BE OVERRIDDEN BY MAVEN BUILD. DON'T EDIT CLASS, IT WILL HAVE NO EFFECT.\n"); builder.append(" * \n"); builder.append(" * Interface for GIN Injector, that provides access to the top level\n"); builder.append(" * application components. Implementation of Injector is generated\n"); builder.append(" * on compile time.\n"); builder.append(" */\n"); builder.append("@GinModules({\n"); // generate the list of modules includes generateListOfModules(builder); // close GinModules declaration builder.append("})\n"); // declare class definition builder.append("public interface IDEInjector extends Ginjector\n"); builder.append("{\n"); builder.append("\n"); // define method builder.append(GeneratorUtils.TAB).append("/**\n"); builder.append(GeneratorUtils.TAB).append(" * @return the instance of BootstrapController\n"); builder.append(GeneratorUtils.TAB).append(" */\n"); builder.append(GeneratorUtils.TAB).append("BootstrapController getBootstrapController();\n"); // close class definition builder.append("\n"); builder.append("}\n"); // flush content FileUtils.writeStringToFile(extManager, builder.toString()); } /** * Generate codeblock with all the GinModules * * @param builder */ public static void generateListOfModules(StringBuilder builder) { // Generate the list of GinModules declarations Iterator<String> entryIterator = EXTENSIONS_FQN.iterator(); while (entryIterator.hasNext()) { // <FullFQN, ClassName> String ginModuleFQN = entryIterator.next(); String hasComma = entryIterator.hasNext() ? "," : ""; // add ModuleDeclaration builder.append(GeneratorUtils.TAB).append(ginModuleFQN).append(".class ").append(hasComma).append("\n"); } } /** * Find all the Java files that have ExtensionGinModule annotation * * @throws IOException */ @SuppressWarnings("unchecked") public static void findGinModules(File rootFolder) throws IOException { Reflections reflection = new Reflections(getConfigurationBuilder()); Set<Class<?>> classes = reflection.getTypesAnnotatedWith(ExtensionGinModule.class); for (Class clazz : classes) { EXTENSIONS_FQN.add(clazz.getCanonicalName()); System.out.println(String.format("New Gin Module Found: %s", clazz.getCanonicalName())); } System.out.println(String.format("Found: %d Gin Modules", EXTENSIONS_FQN.size())); } }