/******************************************************************************* * 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 com.google.common.collect.ImmutableSet; import com.google.common.io.Resources; import org.apache.commons.io.FileUtils; import org.reflections.Reflections; import org.reflections.scanners.ResourcesScanner; import org.reflections.util.ConfigurationBuilder; import org.reflections.util.FilterBuilder; import org.stringtemplate.v4.ST; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.Collections; import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.stream.Collectors; import static java.lang.Boolean.parseBoolean; import static java.nio.charset.StandardCharsets.UTF_8; import static org.eclipse.che.util.IgnoreUnExistedResourcesReflectionConfigurationBuilder.getConfigurationBuilder; /** * Generates uber IDE.gwt.xml from part found in class path. * * @author Sergii Kabashniuk */ public class GwtXmlGenerator { /** * Name of the template */ public static final String TEMPLATE_NAME = "/".concat(GwtXmlGenerator.class.getPackage().getName().replace(".", "/")).concat("/gwt.xml.template"); public static final String DEFAULT_GWT_XML_PATH = "org/eclipse/che/ide/IDE.gwt.xml"; public static final String DEFAULT_GWT_ETNRY_POINT = "org.eclipse.che.ide.client.IDE"; public static final String DEFAULT_STYLE_SHEET = "IDE.css"; public static final Boolean DEFAULT_LOGGING = false; private final GwtXmlGeneratorConfig config; public GwtXmlGenerator(GwtXmlGeneratorConfig config) { this.config = config; } public File generateGwtXml() throws IOException { File gwtXml = new File(config.getGenerationRoot(), config.getGwtFileName()); if (gwtXml.isDirectory() || gwtXml.exists()) { throw new IOException(gwtXml.getAbsolutePath() + " already exists or directory"); } ST template = getTemplate(); template.add("config", config); // flush content FileUtils.writeStringToFile(gwtXml, template.render()); return gwtXml; } /** * Get the template for typescript * * @return the String Template */ protected ST getTemplate() { URL url = Resources.getResource(GwtXmlGenerator.class, TEMPLATE_NAME); try { return new ST(Resources.toString(url, UTF_8), '$', '$'); } catch (IOException e) { throw new IllegalArgumentException("Unable to read template", e); } } /** * Generated consolidated gwt.xml based on exists XX.gwt.xml in class path * * @param args * possible arguments * --rootDir - directory where gwt.xml file will be generated, default "." * --gwtFileName - Name of the generated file in rootDir, default "org/eclipse/che/ide/IDE.gwt.xml" * --entryPoint - gwt xml entry point, default "org.eclipse.che.ide.client.IDE" * --styleSheet - gwt xml stylesheet, default "IDE.css" * --loggingEnabled - Enable or disable gwt logging, default "false" * --includePackages - Include only specific packages where *.gwt.xml can be found, default "No value. Means all packages" * --excludePackages - Exclude packages from *.gwt.xml scanning , default "com.google", "elemental","java.util","java.lang" * @throws IOException */ public static void main(String[] args) throws IOException { System.out.println(" ------------------------------------------------------------------------ "); System.out.println("Searching for GWT"); System.out.println(" ------------------------------------------------------------------------ "); Map<String, Set<String>> parsedArgs = GeneratorUtils.parseArgs(args); GwtXmlModuleSearcher searcher = new GwtXmlModuleSearcher(parsedArgs.getOrDefault("excludePackages", ImmutableSet.of("com.google", "elemental", "java.util", "java.lang" )), parsedArgs.getOrDefault("includePackages", Collections.emptySet()), Collections.emptySet()); Set<String> gwtModules = searcher.getGwtModulesFromClassPath(); gwtModules.forEach(System.out::println); System.out.println("Found " + gwtModules.size() + " gwt modules"); GwtXmlGeneratorConfig gwtXmlGeneratorConfig = new GwtXmlGeneratorConfig(gwtModules, new File(getSingleValueOrDefault(parsedArgs, "rootDir", ".")), getSingleValueOrDefault(parsedArgs, "gwtFileName", DEFAULT_GWT_XML_PATH), getSingleValueOrDefault(parsedArgs, "entryPoint", DEFAULT_GWT_ETNRY_POINT), getSingleValueOrDefault(parsedArgs, "styleSheet", DEFAULT_STYLE_SHEET), parseBoolean( getSingleValueOrDefault(parsedArgs, "loggingEnabled", DEFAULT_LOGGING.toString())) ); GwtXmlGenerator gwtXmlGenerator = new GwtXmlGenerator(gwtXmlGeneratorConfig); gwtXmlGenerator.generateGwtXml(); } private static String getSingleValueOrDefault(Map<String, Set<String>> parsedArgs, String key, String defaultValue) { Set<String> values = parsedArgs.get(key); return values != null ? values.iterator().next() : defaultValue; } /** * Class provides functionality of searching XXX.gwt.xml files in class path */ public static class GwtXmlModuleSearcher { private final Set<String> excludePackages; private final Set<String> includePackages; private final Set<URL> urls; public GwtXmlModuleSearcher(Set<String> excludePackages, Set<String> includePackages, Set<URL> urls) { this.excludePackages = excludePackages; this.includePackages = includePackages; this.urls = urls; } /** * Searches XXX.gwt.xml files in class path * * @return - set of XXX.gwt.xml files found in class path */ public Set<String> getGwtModulesFromClassPath() { ConfigurationBuilder configurationBuilder = getConfigurationBuilder(); if (urls != null && urls.size() > 0) { configurationBuilder.addUrls(urls); } FilterBuilder filterBuilder = new FilterBuilder(); for (String includePackage : includePackages) { filterBuilder.includePackage(includePackage); } for (String excludePackage : excludePackages) { filterBuilder.excludePackage(excludePackage); } configurationBuilder.setScanners(new ResourcesScanner()).filterInputsBy(filterBuilder); Reflections reflection = new Reflections(configurationBuilder); return new TreeSet<>(reflection.getResources(name -> name.endsWith(".gwt.xml"))); } } public static class GwtXmlGeneratorConfig { private final Set<String> gwtXmlModules; private final File generationRoot; private final String gwtFileName; private final String entryPoint; private final String stylesheet; private final boolean isLoggingEnabled; public GwtXmlGeneratorConfig(Set<String> gwtXmlModules, File generationRoot, String gwtFileName, String entryPoint, String stylesheet, boolean isLoggingEnabled) { this.gwtXmlModules = gwtXmlModules; this.generationRoot = generationRoot; this.gwtFileName = gwtFileName; this.entryPoint = entryPoint; this.stylesheet = stylesheet; this.isLoggingEnabled = isLoggingEnabled; } public GwtXmlGeneratorConfig(Set<String> gwtXmlModules, File generationRoot) { this(gwtXmlModules, generationRoot, DEFAULT_GWT_XML_PATH, DEFAULT_GWT_ETNRY_POINT, DEFAULT_STYLE_SHEET, DEFAULT_LOGGING); } public Set<String> getGwtXmlModules() { return gwtXmlModules; } /** * @return set of gwt modules where '/' replaced with '.' and removed 'gwt.xml' from end. * used to insert as inherits in gwt.xml */ public Set<String> getInherits() { return gwtXmlModules .stream() .map(gwtModule -> gwtModule.replace("/", ".").substring(0, gwtModule.length() - 8)) .collect(Collectors.toCollection(TreeSet::new)); } public File getGenerationRoot() { return generationRoot; } public String getGwtFileName() { return gwtFileName; } public String getEntryPoint() { return entryPoint; } public String getStylesheet() { return stylesheet; } public boolean isLoggingEnabled() { return isLoggingEnabled; } } }