Browse Source

vaadin widget jars now detected by details in manifest file, simple widgetsetbuilder tool + some refactoring

svn changeset:8990/svn branch:2009-09-widget-packaging_3332
tags/6.7.0.beta1
Matti Tahvonen 14 years ago
parent
commit
43467c624d

+ 1
- 1
src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml View File

@@ -31,7 +31,7 @@
<when-property-is name="user.agent" value="ie6"/>
</replace-with>

<generate-with class="com.vaadin.terminal.gwt.rebind.WidgetMapGenerator">
<generate-with class="com.vaadin.terminal.gwt.widgetsetutils.WidgetMapGenerator">
<when-type-is class="com.vaadin.terminal.gwt.client.WidgetMap"/>
</generate-with>

src/com/vaadin/terminal/gwt/rebind/ClassPathExplorer.java → src/com/vaadin/terminal/gwt/widgetsetutils/ClassPathExplorer.java View File

@@ -1,9 +1,10 @@
package com.vaadin.terminal.gwt.rebind;
package com.vaadin.terminal.gwt.widgetsetutils;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Collection;
@@ -12,25 +13,30 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;

import com.vaadin.terminal.Paintable;
import com.vaadin.ui.ClientWidget;

/**
* Utility class to find server side widgets with {@link ClientWidget}
* annotation. Used by WidgetMapGenerator to implement some monkey coding for
* Utility class to collect widgetset related information from classpath.
* Utility will seek all directories from classpaths, and jar files having
* "Vaadin-Widgetsets" key in their manifest file.
* <p>
* Used by WidgetMapGenerator and ide tools to implement some monkey coding for
* you.
* <p>
* If you end up reading this comment, I guess you have faced a sluggish
* performance of widget compilation or unreliable detection of components in
* your classpaths. The thing you might be able to do is to use annotation
* processing tool like apt to generate the needed information. Then either use
* that information in {@link WidgetMapGenerator} or create the appropriate
* monkey code for gwt directly in annotation processor and get rid of
* {@link WidgetMapGenerator}. Using annotation processor might be a good idea
* when dropping Java 1.5 support (integrated to javac in 6).
* Developer notice: If you end up reading this comment, I guess you have faced
* a sluggish performance of widget compilation or unreliable detection of
* components in your classpaths. The thing you might be able to do is to use
* annotation processing tool like apt to generate the needed information. Then
* either use that information in {@link WidgetMapGenerator} or create the
* appropriate monkey code for gwt directly in annotation processor and get rid
* of {@link WidgetMapGenerator}. Using annotation processor might be a good
* idea when dropping Java 1.5 support (integrated to javac in 6).
*
*/
public class ClassPathExplorer {
@@ -49,6 +55,9 @@ public class ClassPathExplorer {
private ClassPathExplorer() {
}

/**
* Finds server side widgets with {@link ClientWidget} annotation.
*/
public static Collection<Class<? extends Paintable>> getPaintablesHavingWidgetAnnotation() {
Collection<Class<? extends Paintable>> paintables = new HashSet<Class<? extends Paintable>>();
Set<URL> keySet = classpathLocations.keySet();
@@ -59,11 +68,75 @@ public class ClassPathExplorer {

}

/**
* Finds available widgetset names.
*
* @return
*/
public static Collection<String> getAvailableWidgetSets() {
Collection<String> widgetsets = new HashSet<String>();
Set<URL> keySet = classpathLocations.keySet();
for (URL url : keySet) {
searchForWidgetSets(url, widgetsets);
}
return widgetsets;
}

private static void searchForWidgetSets(URL location,
Collection<String> widgetsets) {

File directory = new File(location.getFile());

if (directory.exists() && !directory.isHidden()) {
// Get the list of the files contained in the directory
String[] files = directory.list();
for (int i = 0; i < files.length; i++) {
// we are only interested in .gwt.xml files
if (files[i].endsWith(".gwt.xml")) {
// remove the extension
String classname = files[i].substring(0,
files[i].length() - 8);
classname = classpathLocations.get(location) + "."
+ classname;
widgetsets.add(classname);
}
}
} else {

try {
// check files in jar file, entries will list all directories
// and files in jar

URLConnection openConnection = location.openConnection();
if (openConnection instanceof JarURLConnection) {
JarURLConnection conn = (JarURLConnection) openConnection;

JarFile jarFile = conn.getJarFile();

Manifest manifest = jarFile.getManifest();
String value = manifest.getMainAttributes().getValue(
"Vaadin-Widgetsets");
if (value != null) {
String[] widgetsetNames = value.split(",");
for (int i = 0; i < widgetsetNames.length; i++) {
String widgetsetname = widgetsetNames[i].trim()
.intern();
widgetsets.add(widgetsetname);
}
}
}
} catch (IOException e) {
System.err.println(e);
}

}
}

/**
* Determine every URL location defined by the current classpath, and it's
* associated package name.
*/
public final static Map<URL, String> getClasspathLocations() {
private final static Map<URL, String> getClasspathLocations() {
Map<URL, String> locations = new HashMap<URL, String>();

String pathSep = System.getProperty("path.separator");
@@ -92,6 +165,27 @@ public class ClassPathExplorer {
|| classpathEntry.contains(".vaadin.")) {
return true;
} else {
URL url;
try {
url = new URL("file:"
+ new File(classpathEntry).getCanonicalPath());
url = new URL("jar:" + url.toExternalForm() + "!/");
JarURLConnection conn = (JarURLConnection) url
.openConnection();
JarFile jarFile = conn.getJarFile();
Manifest manifest = jarFile.getManifest();
Attributes mainAttributes = manifest.getMainAttributes();
if (mainAttributes.getValue("Vaadin-Widgetsets") != null) {
return true;
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

return false;
}
}
@@ -155,26 +249,6 @@ public class ClassPathExplorer {

}

private static String packageNameFor(JarEntry entry) {
if (entry == null) {
return "";
}
String s = entry.getName();
if (s == null) {
return "";
}
if (s.length() == 0) {
return s;
}
if (s.startsWith("/")) {
s = s.substring(1, s.length());
}
if (s.endsWith("/")) {
s = s.substring(0, s.length() - 1);
}
return s.replace('/', '.');
}

private final static void searchForPaintables(URL location,
String packageName,
Collection<Class<? extends Paintable>> paintables) {
@@ -237,7 +311,7 @@ public class ClassPathExplorer {
Class<?> c = Class.forName(fullclassName);
if (c.getAnnotation(ClientWidget.class) != null) {
paintables.add((Class<? extends Paintable>) c);
System.out.println("Found paintable " + fullclassName);
// System.out.println("Found paintable " + fullclassName);
}
} catch (ExceptionInInitializerError e) {
// e.printStackTrace();
@@ -262,5 +336,14 @@ public class ClassPathExplorer {
for (Class<? extends Paintable> cls : paintables) {
System.out.println(cls.getCanonicalName());
}

System.out.println();
System.out.println("Searching available widgetsets...");

Collection<String> availableWidgetSets = ClassPathExplorer
.getAvailableWidgetSets();
for (String string : availableWidgetSets) {
System.out.println(string);
}
}
}

src/com/vaadin/terminal/gwt/rebind/WidgetMapGenerator.java → src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java View File

@@ -1,4 +1,4 @@
package com.vaadin.terminal.gwt.rebind;
package com.vaadin.terminal.gwt.widgetsetutils;

import java.io.PrintWriter;
import java.util.Collection;

+ 134
- 0
src/com/vaadin/terminal/gwt/widgetsetutils/WidgetSetBuilder.java View File

@@ -0,0 +1,134 @@
package com.vaadin.terminal.gwt.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.util.Collection;
import java.util.HashSet;
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.
*/
public class WidgetSetBuilder {

public static void main(String[] args) throws IOException {
if (args.length == 0) {
printUsage();
} else {
String widgetsetname = args[0];
String sourcepath = args[1];
updateWidgetSet(widgetsetname, sourcepath);

}
}

public static void updateWidgetSet(final String widgetset, String sourcepath)
throws IOException, FileNotFoundException {
String widgetsetfilename = sourcepath + "/"
+ widgetset.replace(".", "/") + ".gwt.xml";
File widgetsetFile = new File(widgetsetfilename);
if (!widgetsetFile.exists()) {
// create empty gwt module file
widgetsetFile.createNewFile();
PrintStream printStream = new PrintStream(new FileOutputStream(
widgetsetFile));
printStream.print("<module>\n\n</module>\n");
printStream.close();
}

String content = readFile(widgetsetFile);

Collection<String> oldInheritedWidgetsets = getCurrentWidgetSets(content);

Collection<String> availableWidgetSets = ClassPathExplorer
.getAvailableWidgetSets();

// add widgetsets that do not exist
for (String ws : availableWidgetSets) {
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.contains(ws)) {
// widgetset not available in classpath
content = removeWidgetSet(ws, content);
}
}

commitChanges(widgetsetfilename, content);
}

private static String removeWidgetSet(String ws, String content) {
return content.replaceFirst("<inherits name=\"" + ws + "\"[^/]*/>", "");
}

private static void commitChanges(String widgetsetfilename, String content)
throws IOException {
BufferedWriter bufferedWriter = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(widgetsetfilename)));
bufferedWriter.write(content);
bufferedWriter.close();
}

private static String addWidgetSet(String ws, String content) {
return content.replace("</module>", "\n\t<inherits name=\"" + ws
+ "\" />" + "\n</module>");
}

private static Collection<String> getCurrentWidgetSets(String content) {
HashSet<String> hashSet = new HashSet<String>();
Pattern inheritsPattern = Pattern.compile(" name=\"([^\"]*)\"");

Matcher matcher = inheritsPattern.matcher(content);

while (matcher.find()) {
String possibleWidgetSet = matcher.group(1);
if (possibleWidgetSet.toLowerCase().contains("widgetset")) {
hashSet.add(possibleWidgetSet);
}
}
return hashSet;
}

private static String readFile(File widgetsetFile) throws IOException {
Reader fi = new FileReader(widgetsetFile);
BufferedReader bufferedReader = new BufferedReader(fi);
StringBuilder 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("\t1. Set the same classpath as you will "
+ "have for the GWT compiler.");
o.println("\t2. Give the widgetsetname (to be created or updated)"
+ " as first parameter, source path as a second parameter");
o.println();
o
.println("All found vaadin widgetsets will be inherited in given widgetset");

}

}

Loading…
Cancel
Save