You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

WidgetSetBuilder.java 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. @VaadinApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.terminal.gwt.widgetsetutils;
  5. import java.io.BufferedReader;
  6. import java.io.BufferedWriter;
  7. import java.io.File;
  8. import java.io.FileNotFoundException;
  9. import java.io.FileOutputStream;
  10. import java.io.FileReader;
  11. import java.io.IOException;
  12. import java.io.OutputStreamWriter;
  13. import java.io.PrintStream;
  14. import java.io.Reader;
  15. import java.net.URL;
  16. import java.util.Collection;
  17. import java.util.HashSet;
  18. import java.util.Iterator;
  19. import java.util.Map;
  20. import java.util.regex.Matcher;
  21. import java.util.regex.Pattern;
  22. /**
  23. * Helper class to update widgetsets GWT module configuration file. Can be used
  24. * command line or via IDE tools.
  25. *
  26. * <p>
  27. * If module definition file contains text "WS Compiler: manually edited", tool
  28. * will skip editing file.
  29. *
  30. */
  31. public class WidgetSetBuilder {
  32. public static void main(String[] args) throws IOException {
  33. if (args.length == 0) {
  34. printUsage();
  35. } else {
  36. String widgetsetname = args[0];
  37. updateWidgetSet(widgetsetname);
  38. }
  39. }
  40. public static void updateWidgetSet(final String widgetset)
  41. throws IOException, FileNotFoundException {
  42. boolean changed = false;
  43. Map<String, URL> availableWidgetSets = ClassPathExplorer
  44. .getAvailableWidgetSets();
  45. URL sourceUrl = availableWidgetSets.get(widgetset);
  46. if (sourceUrl == null) {
  47. // find first/default source directory
  48. sourceUrl = ClassPathExplorer.getDefaultSourceDirectory();
  49. }
  50. String widgetsetfilename = sourceUrl.getFile() + "/"
  51. + widgetset.replace(".", "/") + ".gwt.xml";
  52. File widgetsetFile = new File(widgetsetfilename);
  53. if (!widgetsetFile.exists()) {
  54. // create empty gwt module file
  55. File parent = widgetsetFile.getParentFile();
  56. if (parent != null && !parent.exists()) {
  57. if (!parent.mkdirs()) {
  58. throw new IOException(
  59. "Could not create directory for the widgetset: "
  60. + parent.getPath());
  61. }
  62. }
  63. widgetsetFile.createNewFile();
  64. PrintStream printStream = new PrintStream(new FileOutputStream(
  65. widgetsetFile));
  66. printStream.print("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
  67. + "<!DOCTYPE module PUBLIC \"-//Google Inc.//DTD "
  68. + "Google Web Toolkit 1.7.0//EN\" \"http://google"
  69. + "-web-toolkit.googlecode.com/svn/tags/1.7.0/dis"
  70. + "tro-source/core/src/gwt-module.dtd\">\n");
  71. printStream.print("<module>\n");
  72. printStream
  73. .print(" <!--\n"
  74. + " Uncomment the following to compile the widgetset for one browser only.\n"
  75. + " This can reduce the GWT compilation time significantly when debugging.\n"
  76. + " The line should be commented out before deployment to production\n"
  77. + " environments.\n\n"
  78. + " Multiple browsers can be specified for GWT 1.7 as a comma separated\n"
  79. + " list. The supported user agents at the moment of writing were:\n"
  80. + " ie6,ie8,gecko,gecko1_8,safari,opera\n\n"
  81. + " The value gecko1_8 is used for Firefox 3 and later and safari is used for\n"
  82. + " webkit based browsers including Google Chrome.\n"
  83. + " -->\n"
  84. + " <!-- <set-property name=\"user.agent\" value=\"gecko1_8\"/> -->\n");
  85. printStream.print("\n</module>\n");
  86. printStream.close();
  87. changed = true;
  88. }
  89. String content = readFile(widgetsetFile);
  90. if (isEditable(content)) {
  91. String originalContent = content;
  92. Collection<String> oldInheritedWidgetsets = getCurrentInheritedWidgetsets(content);
  93. // add widgetsets that do not exist
  94. Iterator<String> i = availableWidgetSets.keySet().iterator();
  95. while (i.hasNext()) {
  96. String ws = i.next();
  97. if (ws.equals(widgetset)) {
  98. // do not inherit the module itself
  99. continue;
  100. }
  101. if (!oldInheritedWidgetsets.contains(ws)) {
  102. content = addWidgetSet(ws, content);
  103. }
  104. }
  105. for (String ws : oldInheritedWidgetsets) {
  106. if (!availableWidgetSets.containsKey(ws)) {
  107. // widgetset not available in classpath
  108. content = removeWidgetSet(ws, content);
  109. }
  110. }
  111. changed = changed || !content.equals(originalContent);
  112. if (changed) {
  113. commitChanges(widgetsetfilename, content);
  114. }
  115. } else {
  116. System.out
  117. .println("Widgetset is manually edited. Skipping updates.");
  118. }
  119. }
  120. private static boolean isEditable(String content) {
  121. return !content.contains("WS Compiler: manually edited");
  122. }
  123. private static String removeWidgetSet(String ws, String content) {
  124. return content.replaceFirst("<inherits name=\"" + ws + "\"[^/]*/>", "");
  125. }
  126. private static void commitChanges(String widgetsetfilename, String content)
  127. throws IOException {
  128. BufferedWriter bufferedWriter = new BufferedWriter(
  129. new OutputStreamWriter(new FileOutputStream(widgetsetfilename)));
  130. bufferedWriter.write(content);
  131. bufferedWriter.close();
  132. }
  133. private static String addWidgetSet(String ws, String content) {
  134. return content.replace("</module>", "\n <inherits name=\"" + ws
  135. + "\" />" + "\n</module>");
  136. }
  137. private static Collection<String> getCurrentInheritedWidgetsets(
  138. String content) {
  139. HashSet<String> hashSet = new HashSet<String>();
  140. Pattern inheritsPattern = Pattern.compile(" name=\"([^\"]*)\"");
  141. Matcher matcher = inheritsPattern.matcher(content);
  142. while (matcher.find()) {
  143. String gwtModule = matcher.group(1);
  144. if (isWidgetset(gwtModule)) {
  145. hashSet.add(gwtModule);
  146. }
  147. }
  148. return hashSet;
  149. }
  150. static boolean isWidgetset(String gwtModuleName) {
  151. return gwtModuleName.toLowerCase().contains("widgetset");
  152. }
  153. private static String readFile(File widgetsetFile) throws IOException {
  154. Reader fi = new FileReader(widgetsetFile);
  155. BufferedReader bufferedReader = new BufferedReader(fi);
  156. StringBuilder sb = new StringBuilder();
  157. String line;
  158. while ((line = bufferedReader.readLine()) != null) {
  159. sb.append(line);
  160. sb.append("\n");
  161. }
  162. fi.close();
  163. return sb.toString();
  164. }
  165. private static void printUsage() {
  166. PrintStream o = System.out;
  167. o.println(WidgetSetBuilder.class.getSimpleName() + " usage:");
  168. o.println(" 1. Set the same classpath as you will "
  169. + "have for the GWT compiler.");
  170. o.println(" 2. Give the widgetsetname (to be created or updated)"
  171. + " as first parameter");
  172. o.println();
  173. o.println("All found vaadin widgetsets will be inherited in given widgetset");
  174. }
  175. }