/* * Copyright 2000-2016 Vaadin Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.vaadin.server.widgetsetutils; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintStream; import java.io.Reader; import java.net.URISyntaxException; import java.net.URL; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Helper class to update widgetsets GWT module configuration file. Can be used * command line or via IDE tools. * * <p> * If module definition file contains text "WS Compiler: manually edited", tool * will skip editing file. * */ public class WidgetSetBuilder { public static void main(String[] args) throws IOException, URISyntaxException { if (args.length == 0) { printUsage(); } else { String widgetsetname = args[0]; updateWidgetSet(widgetsetname); } } public static void updateWidgetSet(final String widgetset) throws IOException, FileNotFoundException, URISyntaxException { boolean changed = false; Map<String, URL> availableWidgetSets = ClassPathExplorer .getAvailableWidgetSets(); String widgetsetFileName = widgetset.replace(".", "/") + ".gwt.xml"; URL sourceUrl = availableWidgetSets.get(widgetset); if (sourceUrl == null) { // find first/default source directory sourceUrl = ClassPathExplorer .getWidgetsetSourceDirectory(widgetsetFileName); } File widgetsetFile = new File(new File(sourceUrl.toURI()), widgetsetFileName); if (!widgetsetFile.exists()) { // create empty gwt module file File parent = widgetsetFile.getParentFile(); if (parent != null && !parent.exists()) { if (!parent.mkdirs()) { throw new IOException( "Could not create directory for the widgetset: " + parent.getPath()); } } widgetsetFile.createNewFile(); try (PrintStream printStream = new PrintStream( new FileOutputStream(widgetsetFile))) { printStream.print("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<!DOCTYPE module PUBLIC \"-//Google Inc.//DTD Google Web Toolkit 2.5.1//EN\" \"http://google-web-toolkit.googlecode.com/svn/tags/2.5.1/distro-source/core/src/gwt-module.dtd\">\n"); printStream.print("<module>\n"); printStream.print(" <!--\n" + " Uncomment the following to compile the widgetset for one browser only.\n\n" + " Multiple browsers can be specified as a comma separated list. The\n" + " supported user agents at the moment of writing were:\n" + " ie8,ie9,gecko1_8,safari,opera\n\n" + " The value gecko1_8 is used for Firefox and safari is used for webkit\n" + " based browsers including Google Chrome.\n" + " -->\n" + " <!-- <set-property name=\"user.agent\" value=\"safari\"/> -->\n\n" + " <!--\n" + " To enable SuperDevMode, uncomment this line.\n\n" + " See https://vaadin.com/wiki/-/wiki/Main/Using%20SuperDevMode for more\n" + " information and instructions.\n" + " -->\n" + " <!-- <set-configuration-property name=\"devModeRedirectEnabled\" value=\"true\" /> -->\n\n"); printStream.print("\n</module>\n"); } changed = true; } String content = readFile(widgetsetFile); if (isEditable(content)) { String originalContent = content; Collection<String> oldInheritedWidgetsets = getCurrentInheritedWidgetsets( content); // add widgetsets that do not exist Iterator<String> i = availableWidgetSets.keySet().iterator(); while (i.hasNext()) { String ws = i.next(); if (ws.equals(widgetset)) { // do not inherit the module itself continue; } if (!oldInheritedWidgetsets.contains(ws)) { content = addWidgetSet(ws, content); } } for (String ws : oldInheritedWidgetsets) { if (!availableWidgetSets.containsKey(ws)) { // widgetset not available in classpath content = removeWidgetSet(ws, content); } } changed = changed || !content.equals(originalContent); if (changed) { commitChanges(widgetsetFile, content); } } else { System.out .println("Widgetset is manually edited. Skipping updates."); } } private static boolean isEditable(String content) { return !content.contains("WS Compiler: manually edited"); } private static String removeWidgetSet(String ws, String content) { return content.replaceFirst("<inherits name=\"" + ws + "\"[^/]*/>", ""); } private static void commitChanges(File widgetsetFile, String content) throws IOException { try (BufferedWriter bufferedWriter = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(widgetsetFile)))) { bufferedWriter.write(content); } } private static String addWidgetSet(String ws, String content) { return content.replace("</module>", "\n <inherits name=\"" + ws + "\" />" + "\n</module>"); } private static Collection<String> getCurrentInheritedWidgetsets( String content) { HashSet<String> hashSet = new HashSet<>(); Pattern inheritsPattern = Pattern.compile(" name=\"([^\"]*)\""); Matcher matcher = inheritsPattern.matcher(content); while (matcher.find()) { String gwtModule = matcher.group(1); if (isWidgetset(gwtModule)) { hashSet.add(gwtModule); } } return hashSet; } static boolean isWidgetset(String gwtModuleName) { return gwtModuleName.toLowerCase().contains("widgetset"); } private static String readFile(File widgetsetFile) throws IOException { StringBuilder sb; try (Reader fi = new FileReader(widgetsetFile)) { BufferedReader bufferedReader = new BufferedReader(fi); sb = new StringBuilder(); String line; while ((line = bufferedReader.readLine()) != null) { sb.append(line); sb.append("\n"); } } return sb.toString(); } private static void printUsage() { PrintStream o = System.out; o.println(WidgetSetBuilder.class.getSimpleName() + " usage:"); o.println(" 1. Set the same classpath as you will " + "have for the GWT compiler."); o.println(" 2. Give the widgetsetname (to be created or updated)" + " as first parameter"); o.println(); o.println( "All found vaadin widgetsets will be inherited in given widgetset"); } }