From f5f73df7937d6fc8008ae34cc5a7d39e60de266b Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Wed, 29 Aug 2012 12:29:14 +0300 Subject: Renamed com.vaadin.terminal.gwt.widgetsetutils -> com.vaadin.server.widgetsetutils (#9431) --- build/package/build-widgetset.xml | 2 +- .../AcceptCriteriaFactoryGenerator.java | 139 +++++ .../server/widgetsetutils/ClassPathExplorer.java | 474 ++++++++++++++ .../ConnectorBundleLoaderFactory.java | 684 +++++++++++++++++++++ .../widgetsetutils/CustomWidgetMapGenerator.java | 96 +++ .../widgetsetutils/EagerWidgetMapGenerator.java | 41 ++ .../widgetsetutils/LazyWidgetMapGenerator.java | 35 ++ .../server/widgetsetutils/WidgetMapGenerator.java | 434 +++++++++++++ .../server/widgetsetutils/WidgetSetBuilder.java | 213 +++++++ .../widgetsetutils/metadata/ArraySerializer.java | 90 +++ .../widgetsetutils/metadata/ClientRpcVisitor.java | 45 ++ .../widgetsetutils/metadata/ConnectorBundle.java | 611 ++++++++++++++++++ .../metadata/ConnectorInitVisitor.java | 27 + .../widgetsetutils/metadata/CustomSerializer.java | 43 ++ .../widgetsetutils/metadata/EnumSerializer.java | 58 ++ .../widgetsetutils/metadata/FieldProperty.java | 86 +++ .../metadata/GeneratedSerializer.java | 26 + .../widgetsetutils/metadata/JsonSerializer.java | 88 +++ .../widgetsetutils/metadata/MethodProperty.java | 130 ++++ .../server/widgetsetutils/metadata/Property.java | 89 +++ .../widgetsetutils/metadata/ServerRpcVisitor.java | 48 ++ .../widgetsetutils/metadata/StateInitVisitor.java | 25 + .../widgetsetutils/metadata/TypeVisitor.java | 58 ++ .../widgetsetutils/metadata/WidgetInitVisitor.java | 73 +++ .../AcceptCriteriaFactoryGenerator.java | 139 ----- .../gwt/widgetsetutils/ClassPathExplorer.java | 474 -------------- .../ConnectorBundleLoaderFactory.java | 684 --------------------- .../widgetsetutils/CustomWidgetMapGenerator.java | 96 --- .../widgetsetutils/EagerWidgetMapGenerator.java | 41 -- .../gwt/widgetsetutils/LazyWidgetMapGenerator.java | 35 -- .../gwt/widgetsetutils/WidgetMapGenerator.java | 434 ------------- .../gwt/widgetsetutils/WidgetSetBuilder.java | 213 ------- .../widgetsetutils/metadata/ArraySerializer.java | 90 --- .../widgetsetutils/metadata/ClientRpcVisitor.java | 45 -- .../widgetsetutils/metadata/ConnectorBundle.java | 611 ------------------ .../metadata/ConnectorInitVisitor.java | 27 - .../widgetsetutils/metadata/CustomSerializer.java | 43 -- .../widgetsetutils/metadata/EnumSerializer.java | 58 -- .../gwt/widgetsetutils/metadata/FieldProperty.java | 86 --- .../metadata/GeneratedSerializer.java | 26 - .../widgetsetutils/metadata/JsonSerializer.java | 88 --- .../widgetsetutils/metadata/MethodProperty.java | 130 ---- .../gwt/widgetsetutils/metadata/Property.java | 89 --- .../widgetsetutils/metadata/ServerRpcVisitor.java | 48 -- .../widgetsetutils/metadata/StateInitVisitor.java | 25 - .../gwt/widgetsetutils/metadata/TypeVisitor.java | 58 -- .../widgetsetutils/metadata/WidgetInitVisitor.java | 73 --- .../src/com/vaadin/tools/WidgetsetCompiler.java | 2 +- client/src/com/vaadin/Vaadin.gwt.xml | 2 +- .../client/ui/dd/VAcceptCriterionFactory.java | 2 +- shared/src/com/vaadin/shared/ui/Connect.java | 10 +- .../vaadin/data/util/AbstractContainerTest.java | 6 +- 52 files changed, 3625 insertions(+), 3625 deletions(-) create mode 100644 client-compiler/src/com/vaadin/server/widgetsetutils/AcceptCriteriaFactoryGenerator.java create mode 100644 client-compiler/src/com/vaadin/server/widgetsetutils/ClassPathExplorer.java create mode 100644 client-compiler/src/com/vaadin/server/widgetsetutils/ConnectorBundleLoaderFactory.java create mode 100644 client-compiler/src/com/vaadin/server/widgetsetutils/CustomWidgetMapGenerator.java create mode 100644 client-compiler/src/com/vaadin/server/widgetsetutils/EagerWidgetMapGenerator.java create mode 100644 client-compiler/src/com/vaadin/server/widgetsetutils/LazyWidgetMapGenerator.java create mode 100644 client-compiler/src/com/vaadin/server/widgetsetutils/WidgetMapGenerator.java create mode 100644 client-compiler/src/com/vaadin/server/widgetsetutils/WidgetSetBuilder.java create mode 100644 client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ArraySerializer.java create mode 100644 client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ClientRpcVisitor.java create mode 100644 client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java create mode 100644 client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorInitVisitor.java create mode 100644 client-compiler/src/com/vaadin/server/widgetsetutils/metadata/CustomSerializer.java create mode 100644 client-compiler/src/com/vaadin/server/widgetsetutils/metadata/EnumSerializer.java create mode 100644 client-compiler/src/com/vaadin/server/widgetsetutils/metadata/FieldProperty.java create mode 100644 client-compiler/src/com/vaadin/server/widgetsetutils/metadata/GeneratedSerializer.java create mode 100644 client-compiler/src/com/vaadin/server/widgetsetutils/metadata/JsonSerializer.java create mode 100644 client-compiler/src/com/vaadin/server/widgetsetutils/metadata/MethodProperty.java create mode 100644 client-compiler/src/com/vaadin/server/widgetsetutils/metadata/Property.java create mode 100644 client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ServerRpcVisitor.java create mode 100644 client-compiler/src/com/vaadin/server/widgetsetutils/metadata/StateInitVisitor.java create mode 100644 client-compiler/src/com/vaadin/server/widgetsetutils/metadata/TypeVisitor.java create mode 100644 client-compiler/src/com/vaadin/server/widgetsetutils/metadata/WidgetInitVisitor.java delete mode 100644 client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/AcceptCriteriaFactoryGenerator.java delete mode 100644 client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/ClassPathExplorer.java delete mode 100644 client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/ConnectorBundleLoaderFactory.java delete mode 100644 client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/CustomWidgetMapGenerator.java delete mode 100644 client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/EagerWidgetMapGenerator.java delete mode 100644 client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/LazyWidgetMapGenerator.java delete mode 100644 client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java delete mode 100644 client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetSetBuilder.java delete mode 100644 client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ArraySerializer.java delete mode 100644 client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ClientRpcVisitor.java delete mode 100644 client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ConnectorBundle.java delete mode 100644 client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ConnectorInitVisitor.java delete mode 100644 client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/CustomSerializer.java delete mode 100644 client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/EnumSerializer.java delete mode 100644 client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/FieldProperty.java delete mode 100644 client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/GeneratedSerializer.java delete mode 100644 client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/JsonSerializer.java delete mode 100644 client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/MethodProperty.java delete mode 100644 client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/Property.java delete mode 100644 client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ServerRpcVisitor.java delete mode 100644 client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/StateInitVisitor.java delete mode 100644 client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/TypeVisitor.java delete mode 100644 client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/WidgetInitVisitor.java diff --git a/build/package/build-widgetset.xml b/build/package/build-widgetset.xml index 0be10a5b9d..f42b58ff0f 100644 --- a/build/package/build-widgetset.xml +++ b/build/package/build-widgetset.xml @@ -143,7 +143,7 @@ See configure target to adjust this buildfile. - diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/AcceptCriteriaFactoryGenerator.java b/client-compiler/src/com/vaadin/server/widgetsetutils/AcceptCriteriaFactoryGenerator.java new file mode 100644 index 0000000000..5b9cd399c7 --- /dev/null +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/AcceptCriteriaFactoryGenerator.java @@ -0,0 +1,139 @@ +/* + * Copyright 2011 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.PrintWriter; +import java.util.Date; + +import com.google.gwt.core.ext.Generator; +import com.google.gwt.core.ext.GeneratorContext; +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.TreeLogger.Type; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.core.ext.typeinfo.JClassType; +import com.google.gwt.core.ext.typeinfo.TypeOracle; +import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; +import com.google.gwt.user.rebind.SourceWriter; +import com.vaadin.client.ui.dd.VAcceptCriterion; +import com.vaadin.client.ui.dd.VAcceptCriterionFactory; +import com.vaadin.shared.ui.dd.AcceptCriterion; + +/** + * GWT generator to build {@link VAcceptCriterionFactory} implementation + * dynamically based on {@link AcceptCriterion} annotations available in + * classpath. + * + */ +public class AcceptCriteriaFactoryGenerator extends Generator { + + private String packageName; + private String className; + + @Override + public String generate(TreeLogger logger, GeneratorContext context, + String typeName) throws UnableToCompleteException { + + try { + TypeOracle typeOracle = context.getTypeOracle(); + + // get classType and save instance variables + JClassType classType = typeOracle.getType(typeName); + packageName = classType.getPackage().getName(); + className = classType.getSimpleSourceName() + "Impl"; + // Generate class source code + generateClass(logger, context); + } catch (Exception e) { + logger.log(TreeLogger.ERROR, + "Accept criterion factory creation failed", e); + } + // return the fully qualifed name of the class generated + return packageName + "." + className; + } + + /** + * Generate source code for WidgetMapImpl + * + * @param logger + * Logger object + * @param context + * Generator context + */ + private void generateClass(TreeLogger logger, GeneratorContext context) { + // get print writer that receives the source code + PrintWriter printWriter = null; + printWriter = context.tryCreate(logger, packageName, className); + // print writer if null, source code has ALREADY been generated, + // return (WidgetMap is equal to all permutations atm) + if (printWriter == null) { + return; + } + logger.log(Type.INFO, "Detecting available criteria ..."); + Date date = new Date(); + + // init composer, set class properties, create source writer + ClassSourceFileComposerFactory composer = null; + composer = new ClassSourceFileComposerFactory(packageName, className); + composer.addImport("com.google.gwt.core.client.GWT"); + composer.setSuperclass("com.vaadin.client.ui.dd.VAcceptCriterionFactory"); + SourceWriter sourceWriter = composer.createSourceWriter(context, + printWriter); + + // generator constructor source code + generateInstantiatorMethod(sourceWriter, context, logger); + // close generated class + sourceWriter.outdent(); + sourceWriter.println("}"); + // commit generated class + context.commit(logger, printWriter); + logger.log(Type.INFO, + "Done. (" + (new Date().getTime() - date.getTime()) / 1000 + + "seconds)"); + + } + + private void generateInstantiatorMethod(SourceWriter sourceWriter, + GeneratorContext context, TreeLogger logger) { + + sourceWriter.println("public VAcceptCriterion get(String name) {"); + sourceWriter.indent(); + + sourceWriter.println("name = name.intern();"); + + JClassType criteriaType = context.getTypeOracle().findType( + VAcceptCriterion.class.getName()); + for (JClassType clientClass : criteriaType.getSubtypes()) { + AcceptCriterion annotation = clientClass + .getAnnotation(AcceptCriterion.class); + if (annotation != null) { + String clientClassName = clientClass.getQualifiedSourceName(); + Class serverClass = clientClass.getAnnotation( + AcceptCriterion.class).value(); + String serverClassName = serverClass.getCanonicalName(); + logger.log(Type.INFO, "creating mapping for " + serverClassName); + sourceWriter.print("if (\""); + sourceWriter.print(serverClassName); + sourceWriter.print("\" == name) return GWT.create("); + sourceWriter.print(clientClassName); + sourceWriter.println(".class );"); + sourceWriter.print("else "); + } + } + + sourceWriter.println("return null;"); + sourceWriter.outdent(); + sourceWriter.println("}"); + } +} diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/ClassPathExplorer.java b/client-compiler/src/com/vaadin/server/widgetsetutils/ClassPathExplorer.java new file mode 100644 index 0000000000..70120b944d --- /dev/null +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/ClassPathExplorer.java @@ -0,0 +1,474 @@ +/* + * Copyright 2011 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.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.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.jar.Attributes; +import java.util.jar.JarFile; +import java.util.jar.Manifest; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * 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. + *

+ * Used by WidgetMapGenerator and ide tools to implement some monkey coding for + * you. + *

+ * 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 { + + private static final String VAADIN_ADDON_VERSION_ATTRIBUTE = "Vaadin-Package-Version"; + + /** + * File filter that only accepts directories. + */ + private final static FileFilter DIRECTORIES_ONLY = new FileFilter() { + @Override + public boolean accept(File f) { + if (f.exists() && f.isDirectory()) { + return true; + } else { + return false; + } + } + }; + + /** + * Raw class path entries as given in the java class path string. Only + * entries that could include widgets/widgetsets are listed (primarily + * directories, Vaadin JARs and add-on JARs). + */ + private static List rawClasspathEntries = getRawClasspathEntries(); + + /** + * Map from identifiers (either a package name preceded by the path and a + * slash, or a URL for a JAR file) to the corresponding URLs. This is + * constructed from the class path. + */ + private static Map classpathLocations = getClasspathLocations(rawClasspathEntries); + + /** + * No instantiation from outside, callable methods are static. + */ + private ClassPathExplorer() { + } + + /** + * Finds the names and locations of widgetsets available on the class path. + * + * @return map from widgetset classname to widgetset location URL + */ + public static Map getAvailableWidgetSets() { + long start = System.currentTimeMillis(); + Map widgetsets = new HashMap(); + Set keySet = classpathLocations.keySet(); + for (String location : keySet) { + searchForWidgetSets(location, widgetsets); + } + long end = System.currentTimeMillis(); + + StringBuilder sb = new StringBuilder(); + sb.append("Widgetsets found from classpath:\n"); + for (String ws : widgetsets.keySet()) { + sb.append("\t"); + sb.append(ws); + sb.append(" in "); + sb.append(widgetsets.get(ws)); + sb.append("\n"); + } + final Logger logger = getLogger(); + logger.info(sb.toString()); + logger.info("Search took " + (end - start) + "ms"); + return widgetsets; + } + + /** + * Finds all GWT modules / Vaadin widgetsets in a valid location. + * + * If the location is a directory, all GWT modules (files with the + * ".gwt.xml" extension) are added to widgetsets. + * + * If the location is a JAR file, the comma-separated values of the + * "Vaadin-Widgetsets" attribute in its manifest are added to widgetsets. + * + * @param locationString + * an entry in {@link #classpathLocations} + * @param widgetsets + * a map from widgetset name (including package, with dots as + * separators) to a URL (see {@link #classpathLocations}) - new + * entries are added to this map + */ + private static void searchForWidgetSets(String locationString, + Map widgetsets) { + + URL location = classpathLocations.get(locationString); + 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")) { + continue; + } + + // remove the .gwt.xml extension + String classname = files[i].substring(0, files[i].length() - 8); + String packageName = locationString.substring(locationString + .lastIndexOf("/") + 1); + classname = packageName + "." + classname; + + if (!WidgetSetBuilder.isWidgetset(classname)) { + // Only return widgetsets and not GWT modules to avoid + // comparing modules and widgetsets + continue; + } + + if (!widgetsets.containsKey(classname)) { + String packagePath = packageName.replaceAll("\\.", "/"); + String basePath = location.getFile().replaceAll( + "/" + packagePath + "$", ""); + try { + URL url = new URL(location.getProtocol(), + location.getHost(), location.getPort(), + basePath); + widgetsets.put(classname, url); + } catch (MalformedURLException e) { + // should never happen as based on an existing URL, + // only changing end of file name/path part + getLogger().log(Level.SEVERE, + "Error locating the widgetset " + classname, e); + } + } + } + } 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(); + if (manifest == null) { + // No manifest so this is not a Vaadin Add-on + return; + } + 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(); + if (!widgetsetname.equals("")) { + widgetsets.put(widgetsetname, location); + } + } + } + } + } catch (IOException e) { + getLogger().log(Level.WARNING, "Error parsing jar file", e); + } + + } + } + + /** + * Splits the current class path into entries, and filters them accepting + * directories, Vaadin add-on JARs with widgetsets and Vaadin JARs. + * + * Some other non-JAR entries may also be included in the result. + * + * @return filtered list of class path entries + */ + private final static List getRawClasspathEntries() { + // try to keep the order of the classpath + List locations = new ArrayList(); + + String pathSep = System.getProperty("path.separator"); + String classpath = System.getProperty("java.class.path"); + + if (classpath.startsWith("\"")) { + classpath = classpath.substring(1); + } + if (classpath.endsWith("\"")) { + classpath = classpath.substring(0, classpath.length() - 1); + } + + getLogger().fine("Classpath: " + classpath); + + String[] split = classpath.split(pathSep); + for (int i = 0; i < split.length; i++) { + String classpathEntry = split[i]; + if (acceptClassPathEntry(classpathEntry)) { + locations.add(classpathEntry); + } + } + + return locations; + } + + /** + * Determine every URL location defined by the current classpath, and it's + * associated package name. + * + * See {@link #classpathLocations} for information on output format. + * + * @param rawClasspathEntries + * raw class path entries as split from the Java class path + * string + * @return map of classpath locations, see {@link #classpathLocations} + */ + private final static Map getClasspathLocations( + List rawClasspathEntries) { + long start = System.currentTimeMillis(); + // try to keep the order of the classpath + Map locations = new LinkedHashMap(); + for (String classpathEntry : rawClasspathEntries) { + File file = new File(classpathEntry); + include(null, file, locations); + } + long end = System.currentTimeMillis(); + Logger logger = getLogger(); + if (logger.isLoggable(Level.FINE)) { + logger.fine("getClassPathLocations took " + (end - start) + "ms"); + } + return locations; + } + + /** + * Checks a class path entry to see whether it can contain widgets and + * widgetsets. + * + * All directories are automatically accepted. JARs are accepted if they + * have the "Vaadin-Widgetsets" attribute in their manifest or the JAR file + * name contains "vaadin-" or ".vaadin.". + * + * Also other non-JAR entries may be accepted, the caller should be prepared + * to handle them. + * + * @param classpathEntry + * class path entry string as given in the Java class path + * @return true if the entry should be considered when looking for widgets + * or widgetsets + */ + private static boolean acceptClassPathEntry(String classpathEntry) { + if (!classpathEntry.endsWith(".jar")) { + // accept all non jars (practically directories) + return true; + } else { + // accepts jars that comply with vaadin-component packaging + // convention (.vaadin. or vaadin- as distribution packages), + if (classpathEntry.contains("vaadin-") + || 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(); + getLogger().fine(url.toString()); + JarFile jarFile = conn.getJarFile(); + Manifest manifest = jarFile.getManifest(); + if (manifest != null) { + Attributes mainAttributes = manifest + .getMainAttributes(); + if (mainAttributes.getValue("Vaadin-Widgetsets") != null) { + return true; + } + } + } catch (MalformedURLException e) { + getLogger().log(Level.FINEST, "Failed to inspect JAR file", + e); + } catch (IOException e) { + getLogger().log(Level.FINEST, "Failed to inspect JAR file", + e); + } + + return false; + } + } + } + + /** + * Recursively add subdirectories and jar files to locations - see + * {@link #classpathLocations}. + * + * @param name + * @param file + * @param locations + */ + private final static void include(String name, File file, + Map locations) { + if (!file.exists()) { + return; + } + if (!file.isDirectory()) { + // could be a JAR file + includeJar(file, locations); + return; + } + + if (file.isHidden() || file.getPath().contains(File.separator + ".")) { + return; + } + + if (name == null) { + name = ""; + } else { + name += "."; + } + + // add all directories recursively + File[] dirs = file.listFiles(DIRECTORIES_ONLY); + for (int i = 0; i < dirs.length; i++) { + try { + // add the present directory + if (!dirs[i].isHidden() + && !dirs[i].getPath().contains(File.separator + ".")) { + String key = dirs[i].getCanonicalPath() + "/" + name + + dirs[i].getName(); + locations.put(key, + new URL("file://" + dirs[i].getCanonicalPath())); + } + } catch (Exception ioe) { + return; + } + include(name + dirs[i].getName(), dirs[i], locations); + } + } + + /** + * Add a jar file to locations - see {@link #classpathLocations}. + * + * @param name + * @param locations + */ + private static void includeJar(File file, Map locations) { + try { + URL url = new URL("file:" + file.getCanonicalPath()); + url = new URL("jar:" + url.toExternalForm() + "!/"); + JarURLConnection conn = (JarURLConnection) url.openConnection(); + JarFile jarFile = conn.getJarFile(); + if (jarFile != null) { + // the key does not matter here as long as it is unique + locations.put(url.toString(), url); + } + } catch (Exception e) { + // e.printStackTrace(); + return; + } + + } + + /** + * Find and return the default source directory where to create new + * widgetsets. + * + * Return the first directory (not a JAR file etc.) on the classpath by + * default. + * + * TODO this could be done better... + * + * @return URL + */ + public static URL getDefaultSourceDirectory() { + + final Logger logger = getLogger(); + + if (logger.isLoggable(Level.FINE)) { + logger.fine("classpathLocations values:"); + ArrayList locations = new ArrayList( + classpathLocations.keySet()); + for (String location : locations) { + logger.fine(String.valueOf(classpathLocations.get(location))); + } + } + + Iterator it = rawClasspathEntries.iterator(); + while (it.hasNext()) { + String entry = it.next(); + + File directory = new File(entry); + if (directory.exists() && !directory.isHidden() + && directory.isDirectory()) { + try { + return new URL("file://" + directory.getCanonicalPath()); + } catch (MalformedURLException e) { + logger.log(Level.FINEST, "Ignoring exception", e); + // ignore: continue to the next classpath entry + } catch (IOException e) { + logger.log(Level.FINEST, "Ignoring exception", e); + // ignore: continue to the next classpath entry + } + } + } + return null; + } + + /** + * Test method for helper tool + */ + public static void main(String[] args) { + getLogger().info("Searching available widgetsets..."); + + Map availableWidgetSets = ClassPathExplorer + .getAvailableWidgetSets(); + for (String string : availableWidgetSets.keySet()) { + + getLogger().info(string + " in " + availableWidgetSets.get(string)); + } + } + + private static final Logger getLogger() { + return Logger.getLogger(ClassPathExplorer.class.getName()); + } + +} diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/ConnectorBundleLoaderFactory.java b/client-compiler/src/com/vaadin/server/widgetsetutils/ConnectorBundleLoaderFactory.java new file mode 100644 index 0000000000..aa220225c9 --- /dev/null +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/ConnectorBundleLoaderFactory.java @@ -0,0 +1,684 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.server.widgetsetutils; + +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.core.ext.Generator; +import com.google.gwt.core.ext.GeneratorContext; +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.TreeLogger.Type; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.core.ext.typeinfo.JClassType; +import com.google.gwt.core.ext.typeinfo.JMethod; +import com.google.gwt.core.ext.typeinfo.JParameterizedType; +import com.google.gwt.core.ext.typeinfo.JType; +import com.google.gwt.core.ext.typeinfo.NotFoundException; +import com.google.gwt.core.ext.typeinfo.TypeOracle; +import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; +import com.google.gwt.user.rebind.SourceWriter; +import com.vaadin.client.ServerConnector; +import com.vaadin.client.metadata.ConnectorBundleLoader; +import com.vaadin.client.metadata.InvokationHandler; +import com.vaadin.client.metadata.ProxyHandler; +import com.vaadin.client.metadata.TypeData; +import com.vaadin.client.metadata.TypeDataBundle; +import com.vaadin.client.metadata.TypeDataStore; +import com.vaadin.client.ui.UnknownComponentConnector; +import com.vaadin.server.widgetsetutils.metadata.ClientRpcVisitor; +import com.vaadin.server.widgetsetutils.metadata.ConnectorBundle; +import com.vaadin.server.widgetsetutils.metadata.ConnectorInitVisitor; +import com.vaadin.server.widgetsetutils.metadata.GeneratedSerializer; +import com.vaadin.server.widgetsetutils.metadata.Property; +import com.vaadin.server.widgetsetutils.metadata.ServerRpcVisitor; +import com.vaadin.server.widgetsetutils.metadata.StateInitVisitor; +import com.vaadin.server.widgetsetutils.metadata.TypeVisitor; +import com.vaadin.server.widgetsetutils.metadata.WidgetInitVisitor; +import com.vaadin.shared.annotations.Delayed; +import com.vaadin.shared.annotations.DelegateToWidget; +import com.vaadin.shared.communication.ClientRpc; +import com.vaadin.shared.communication.ServerRpc; +import com.vaadin.shared.ui.Connect; +import com.vaadin.shared.ui.Connect.LoadStyle; + +public class ConnectorBundleLoaderFactory extends Generator { + + @Override + public String generate(TreeLogger logger, GeneratorContext context, + String typeName) throws UnableToCompleteException { + TypeOracle typeOracle = context.getTypeOracle(); + + try { + JClassType classType = typeOracle.getType(typeName); + String packageName = classType.getPackage().getName(); + String className = classType.getSimpleSourceName() + "Impl"; + + generateClass(logger, context, packageName, className, typeName); + + return packageName + "." + className; + } catch (UnableToCompleteException e) { + // Just rethrow + throw e; + } catch (Exception e) { + logger.log(Type.ERROR, getClass() + " failed", e); + throw new UnableToCompleteException(); + } + + } + + private void generateClass(TreeLogger logger, GeneratorContext context, + String packageName, String className, String requestedType) + throws Exception { + PrintWriter printWriter = context.tryCreate(logger, packageName, + className); + if (printWriter == null) { + return; + } + + List bundles = buildBundles(logger, + context.getTypeOracle()); + + ClassSourceFileComposerFactory composer = new ClassSourceFileComposerFactory( + packageName, className); + composer.setSuperclass(requestedType); + + SourceWriter w = composer.createSourceWriter(context, printWriter); + + w.println("public void init() {"); + w.indent(); + + for (ConnectorBundle bundle : bundles) { + String name = bundle.getName(); + boolean isEager = name + .equals(ConnectorBundleLoader.EAGER_BUNDLE_NAME); + + w.print("addAsyncBlockLoader(new AsyncBundleLoader(\""); + w.print(escape(name)); + w.print("\", "); + + w.print("new String[] {"); + for (Entry> entry : bundle.getIdentifiers() + .entrySet()) { + Set identifiers = entry.getValue(); + for (String id : identifiers) { + w.print("\""); + w.print(escape(id)); + w.print("\","); + } + } + w.println("}) {"); + w.indent(); + + w.print("protected void load(final "); + w.print(TypeDataStore.class.getName()); + w.println(" store) {"); + w.indent(); + + if (!isEager) { + w.print(GWT.class.getName()); + w.print(".runAsync("); + } + + w.print("new "); + w.print(TypeDataBundle.class.getName()); + w.println("(getName()) {"); + w.indent(); + + w.println("public void load() {"); + w.indent(); + + printBundleData(logger, w, bundle); + + // Close load method + w.outdent(); + w.println("}"); + + // Close new TypeDataBundle() {} + w.outdent(); + w.print("}"); + + if (isEager) { + w.println(".onSuccess();"); + } else { + w.println(");"); + } + + // Close load method + w.outdent(); + w.println("}"); + + // Close add(new ... + w.outdent(); + w.println("});"); + } + + w.outdent(); + w.println("}"); + + w.commit(logger); + } + + private void printBundleData(TreeLogger logger, SourceWriter w, + ConnectorBundle bundle) throws UnableToCompleteException { + writeIdentifiers(w, bundle); + writeGwtConstructors(w, bundle); + writeReturnTypes(w, bundle); + writeInvokers(w, bundle); + writeParamTypes(w, bundle); + writeProxys(w, bundle); + wirteDelayedInfo(w, bundle); + writeProperites(logger, w, bundle); + writePropertyTypes(w, bundle); + writeSetters(logger, w, bundle); + writeGetters(logger, w, bundle); + writeSerializers(logger, w, bundle); + writeDelegateToWidget(logger, w, bundle); + } + + private void writeDelegateToWidget(TreeLogger logger, SourceWriter w, + ConnectorBundle bundle) { + Set needsDelegateToWidget = bundle.getNeedsDelegateToWidget(); + for (Property property : needsDelegateToWidget) { + w.println("store.setDelegateToWidget(%s, \"%s\", \"%s\");", + getClassLiteralString(property.getBeanType()), + property.getName(), + property.getAnnotation(DelegateToWidget.class).value()); + } + } + + private void writeSerializers(TreeLogger logger, SourceWriter w, + ConnectorBundle bundle) throws UnableToCompleteException { + Map serializers = bundle.getSerializers(); + for (Entry entry : serializers.entrySet()) { + JType type = entry.getKey(); + GeneratedSerializer serializer = entry.getValue(); + + w.print("store.setSerializerFactory("); + writeClassLiteral(w, type); + w.print(", "); + w.println("new Invoker() {"); + w.indent(); + + w.println("public Object invoke(Object target, Object[] params) {"); + w.indent(); + + serializer.writeSerializerInstantiator(logger, w); + + w.outdent(); + w.println("}"); + + w.outdent(); + w.print("}"); + w.println(");"); + } + } + + private void writeGetters(TreeLogger logger, SourceWriter w, + ConnectorBundle bundle) { + Set properties = bundle.getNeedsSetter(); + for (Property property : properties) { + w.print("store.setGetter("); + writeClassLiteral(w, property.getBeanType()); + w.print(", \""); + w.print(escape(property.getName())); + w.println("\", new Invoker() {"); + w.indent(); + + w.println("public Object invoke(Object bean, Object[] params) {"); + w.indent(); + + property.writeGetterBody(logger, w, "bean"); + w.println(); + + w.outdent(); + w.println("}"); + + w.outdent(); + w.println("});"); + } + } + + private void writeSetters(TreeLogger logger, SourceWriter w, + ConnectorBundle bundle) { + Set properties = bundle.getNeedsSetter(); + for (Property property : properties) { + w.print("store.setSetter("); + writeClassLiteral(w, property.getBeanType()); + w.print(", \""); + w.print(escape(property.getName())); + w.println("\", new Invoker() {"); + w.indent(); + + w.println("public Object invoke(Object bean, Object[] params) {"); + w.indent(); + + property.writeSetterBody(logger, w, "bean", "params[0]"); + + w.println("return null;"); + + w.outdent(); + w.println("}"); + + w.outdent(); + w.println("});"); + } + } + + private void writePropertyTypes(SourceWriter w, ConnectorBundle bundle) { + Set properties = bundle.getNeedsType(); + for (Property property : properties) { + w.print("store.setPropertyType("); + writeClassLiteral(w, property.getBeanType()); + w.print(", \""); + w.print(escape(property.getName())); + w.print("\", "); + writeTypeCreator(w, property.getPropertyType()); + w.println(");"); + } + } + + private void writeProperites(TreeLogger logger, SourceWriter w, + ConnectorBundle bundle) throws UnableToCompleteException { + Set needsPropertyListing = bundle.getNeedsPropertyListing(); + for (JClassType type : needsPropertyListing) { + w.print("store.setProperties("); + writeClassLiteral(w, type); + w.print(", new String[] {"); + + Set usedPropertyNames = new HashSet(); + Collection properties = bundle.getProperties(type); + for (Property property : properties) { + String name = property.getName(); + if (!usedPropertyNames.add(name)) { + logger.log( + Type.ERROR, + type.getQualifiedSourceName() + + " has multiple properties with the name " + + name + + ". This can happen if there are multiple setters with identical names exect casing."); + throw new UnableToCompleteException(); + } + + w.print("\""); + w.print(name); + w.print("\", "); + } + + w.println("});"); + } + } + + private void wirteDelayedInfo(SourceWriter w, ConnectorBundle bundle) { + Map> needsDelayedInfo = bundle + .getNeedsDelayedInfo(); + Set>> entrySet = needsDelayedInfo + .entrySet(); + for (Entry> entry : entrySet) { + JClassType type = entry.getKey(); + Set methods = entry.getValue(); + for (JMethod method : methods) { + Delayed annotation = method.getAnnotation(Delayed.class); + if (annotation != null) { + w.print("store.setDelayed("); + writeClassLiteral(w, type); + w.print(", \""); + w.print(escape(method.getName())); + w.println("\");"); + + if (annotation.lastonly()) { + w.print("store.setLastonly("); + writeClassLiteral(w, type); + w.print(", \""); + w.print(escape(method.getName())); + w.println("\");"); + } + } + } + } + } + + private void writeProxys(SourceWriter w, ConnectorBundle bundle) { + Set needsProxySupport = bundle.getNeedsProxySupport(); + for (JClassType type : needsProxySupport) { + w.print("store.setProxyHandler("); + writeClassLiteral(w, type); + w.print(", new "); + w.print(ProxyHandler.class.getCanonicalName()); + w.println("() {"); + w.indent(); + + w.println("public Object createProxy(final " + + InvokationHandler.class.getName() + " handler) {"); + w.indent(); + + w.print("return new "); + w.print(type.getQualifiedSourceName()); + w.println("() {"); + w.indent(); + + JMethod[] methods = type.getOverridableMethods(); + for (JMethod method : methods) { + if (method.isAbstract()) { + w.print("public "); + w.print(method.getReturnType().getQualifiedSourceName()); + w.print(" "); + w.print(method.getName()); + w.print("("); + + JType[] types = method.getParameterTypes(); + for (int i = 0; i < types.length; i++) { + if (i != 0) { + w.print(", "); + } + w.print(types[i].getQualifiedSourceName()); + w.print(" p"); + w.print(Integer.toString(i)); + } + + w.println(") {"); + w.indent(); + + if (!method.getReturnType().getQualifiedSourceName() + .equals("void")) { + w.print("return "); + } + + w.print("handler.invoke(this, "); + w.print(TypeData.class.getCanonicalName()); + w.print(".getType("); + writeClassLiteral(w, type); + w.print(").getMethod(\""); + w.print(escape(method.getName())); + w.print("\"), new Object [] {"); + for (int i = 0; i < types.length; i++) { + w.print("p" + i + ", "); + } + w.println("});"); + + w.outdent(); + w.println("}"); + } + } + + w.outdent(); + w.println("};"); + + w.outdent(); + w.println("}"); + + w.outdent(); + w.println("});"); + + } + } + + private void writeParamTypes(SourceWriter w, ConnectorBundle bundle) { + Map> needsParamTypes = bundle + .getNeedsParamTypes(); + for (Entry> entry : needsParamTypes.entrySet()) { + JClassType type = entry.getKey(); + + Set methods = entry.getValue(); + for (JMethod method : methods) { + w.print("store.setParamTypes("); + writeClassLiteral(w, type); + w.print(", \""); + w.print(escape(method.getName())); + w.print("\", new Type[] {"); + + for (JType parameter : method.getParameterTypes()) { + ConnectorBundleLoaderFactory.writeTypeCreator(w, parameter); + w.print(", "); + } + + w.println("});"); + + } + } + } + + private void writeInvokers(SourceWriter w, ConnectorBundle bundle) { + Map> needsInvoker = bundle.getNeedsInvoker(); + for (Entry> entry : needsInvoker.entrySet()) { + JClassType type = entry.getKey(); + + Set methods = entry.getValue(); + for (JMethod method : methods) { + w.print("store.setInvoker("); + writeClassLiteral(w, type); + w.print(", \""); + w.print(escape(method.getName())); + w.println("\", new Invoker() {"); + w.indent(); + + w.println("public Object invoke(Object target, Object[] params) {"); + w.indent(); + + JType returnType = method.getReturnType(); + boolean hasReturnType = !"void".equals(returnType + .getQualifiedSourceName()); + if (hasReturnType) { + w.print("return "); + } + + JType[] parameterTypes = method.getParameterTypes(); + + w.print("((" + type.getQualifiedSourceName() + ") target)." + + method.getName() + "("); + for (int i = 0; i < parameterTypes.length; i++) { + JType parameterType = parameterTypes[i]; + if (i != 0) { + w.print(", "); + } + String parameterTypeName = getBoxedTypeName(parameterType); + w.print("(" + parameterTypeName + ") params[" + i + "]"); + } + w.println(");"); + + if (!hasReturnType) { + w.println("return null;"); + } + + w.outdent(); + w.println("}"); + + w.outdent(); + w.println("});"); + + } + } + } + + private void writeReturnTypes(SourceWriter w, ConnectorBundle bundle) { + Map> methodReturnTypes = bundle + .getMethodReturnTypes(); + for (Entry> entry : methodReturnTypes + .entrySet()) { + JClassType type = entry.getKey(); + + Set methods = entry.getValue(); + for (JMethod method : methods) { + // setReturnType(Class type, String methodName, Type + // returnType) + w.print("store.setReturnType("); + writeClassLiteral(w, type); + w.print(", \""); + w.print(escape(method.getName())); + w.print("\", "); + writeTypeCreator(w, method.getReturnType()); + w.println(");"); + } + } + } + + private void writeGwtConstructors(SourceWriter w, ConnectorBundle bundle) { + Set constructors = bundle.getGwtConstructors(); + for (JClassType type : constructors) { + w.print("store.setConstructor("); + writeClassLiteral(w, type); + w.println(", new Invoker() {"); + w.indent(); + + w.println("public Object invoke(Object target, Object[] params) {"); + w.indent(); + + w.print("return "); + w.print(GWT.class.getName()); + w.print(".create("); + writeClassLiteral(w, type); + w.println(");"); + + w.outdent(); + w.println("}"); + + w.outdent(); + w.println("});"); + } + } + + public static void writeClassLiteral(SourceWriter w, JType type) { + w.print(getClassLiteralString(type)); + } + + public static String getClassLiteralString(JType type) { + return type.getQualifiedSourceName() + ".class"; + } + + private void writeIdentifiers(SourceWriter w, ConnectorBundle bundle) { + Map> identifiers = bundle.getIdentifiers(); + for (Entry> entry : identifiers.entrySet()) { + Set ids = entry.getValue(); + JClassType type = entry.getKey(); + for (String id : ids) { + w.print("store.setClass(\""); + w.print(escape(id)); + w.print("\", "); + writeClassLiteral(w, type); + w.println(");"); + } + } + } + + private List buildBundles(TreeLogger logger, + TypeOracle typeOracle) throws NotFoundException, + UnableToCompleteException { + + Map> connectorsByLoadStyle = new HashMap>(); + for (LoadStyle loadStyle : LoadStyle.values()) { + connectorsByLoadStyle.put(loadStyle, new ArrayList()); + } + + JClassType connectorType = typeOracle.getType(ServerConnector.class + .getName()); + JClassType[] subtypes = connectorType.getSubtypes(); + for (JClassType connectorSubtype : subtypes) { + if (!connectorSubtype.isAnnotationPresent(Connect.class)) { + continue; + } + LoadStyle loadStyle = getLoadStyle(connectorSubtype); + if (loadStyle != null) { + connectorsByLoadStyle.get(loadStyle).add(connectorSubtype); + } + } + + List bundles = new ArrayList(); + + Collection visitors = getVisitors(typeOracle); + + ConnectorBundle eagerBundle = new ConnectorBundle( + ConnectorBundleLoader.EAGER_BUNDLE_NAME, visitors, typeOracle); + TreeLogger eagerLogger = logger.branch(Type.TRACE, + "Populating eager bundle"); + + // Eager connectors and all RPC interfaces are loaded by default + eagerBundle.processTypes(eagerLogger, + connectorsByLoadStyle.get(LoadStyle.EAGER)); + eagerBundle.processType(eagerLogger, typeOracle + .findType(UnknownComponentConnector.class.getCanonicalName())); + eagerBundle.processSubTypes(eagerLogger, + typeOracle.getType(ClientRpc.class.getName())); + eagerBundle.processSubTypes(eagerLogger, + typeOracle.getType(ServerRpc.class.getName())); + + bundles.add(eagerBundle); + + ConnectorBundle deferredBundle = new ConnectorBundle( + ConnectorBundleLoader.DEFERRED_BUNDLE_NAME, eagerBundle); + TreeLogger deferredLogger = logger.branch(Type.TRACE, + "Populating deferred bundle"); + deferredBundle.processTypes(deferredLogger, + connectorsByLoadStyle.get(LoadStyle.DEFERRED)); + + bundles.add(deferredBundle); + + Collection lazy = connectorsByLoadStyle.get(LoadStyle.LAZY); + for (JClassType type : lazy) { + ConnectorBundle bundle = new ConnectorBundle(type.getName(), + eagerBundle); + TreeLogger subLogger = logger.branch(Type.TRACE, "Populating " + + type.getName() + " bundle"); + bundle.processType(subLogger, type); + + bundles.add(bundle); + } + + return bundles; + } + + private Collection getVisitors(TypeOracle oracle) + throws NotFoundException { + List visitors = Arrays. asList( + new ConnectorInitVisitor(), new StateInitVisitor(), + new WidgetInitVisitor(), new ClientRpcVisitor(), + new ServerRpcVisitor()); + for (TypeVisitor typeVisitor : visitors) { + typeVisitor.init(oracle); + } + return visitors; + } + + protected LoadStyle getLoadStyle(JClassType connectorType) { + Connect annotation = connectorType.getAnnotation(Connect.class); + return annotation.loadStyle(); + } + + public static String getBoxedTypeName(JType type) { + if (type.isPrimitive() != null) { + // Used boxed types for primitives + return type.isPrimitive().getQualifiedBoxedSourceName(); + } else { + return type.getErasedType().getQualifiedSourceName(); + } + } + + public static void writeTypeCreator(SourceWriter sourceWriter, JType type) { + String typeName = ConnectorBundleLoaderFactory.getBoxedTypeName(type); + JParameterizedType parameterized = type.isParameterized(); + if (parameterized != null) { + sourceWriter.print("new Type(\"" + typeName + "\", "); + sourceWriter.print("new Type[] {"); + JClassType[] typeArgs = parameterized.getTypeArgs(); + for (JClassType jClassType : typeArgs) { + writeTypeCreator(sourceWriter, jClassType); + sourceWriter.print(", "); + } + sourceWriter.print("}"); + } else { + sourceWriter.print("new Type(" + typeName + ".class"); + } + sourceWriter.print(")"); + } + +} diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/CustomWidgetMapGenerator.java b/client-compiler/src/com/vaadin/server/widgetsetutils/CustomWidgetMapGenerator.java new file mode 100644 index 0000000000..250bfbb4a1 --- /dev/null +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/CustomWidgetMapGenerator.java @@ -0,0 +1,96 @@ +/* + * Copyright 2011 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.util.Collection; +import java.util.HashSet; + +import com.vaadin.client.ComponentConnector; +import com.vaadin.client.ServerConnector; +import com.vaadin.shared.ui.Connect; +import com.vaadin.shared.ui.Connect.LoadStyle; + +/** + * An abstract helper class that can be used to easily build a widgetset with + * customized load styles for each components. In three abstract methods one can + * override the default values given in {@link Connect} annotations. + * + * @see WidgetMapGenerator + * + */ +public abstract class CustomWidgetMapGenerator extends WidgetMapGenerator { + + private Collection> eagerPaintables = new HashSet>(); + private Collection> lazyPaintables = new HashSet>(); + private Collection> deferredPaintables = new HashSet>(); + + @Override + protected LoadStyle getLoadStyle(Class connector) { + if (eagerPaintables == null) { + init(); + } + if (eagerPaintables.contains(connector)) { + return LoadStyle.EAGER; + } + if (lazyPaintables.contains(connector)) { + return LoadStyle.LAZY; + } + if (deferredPaintables.contains(connector)) { + return LoadStyle.DEFERRED; + } + return super.getLoadStyle(connector); + } + + private void init() { + Class[] eagerComponents = getEagerComponents(); + if (eagerComponents != null) { + for (Class class1 : eagerComponents) { + eagerPaintables.add(class1); + } + } + Class[] lazyComponents = getEagerComponents(); + if (lazyComponents != null) { + for (Class class1 : lazyComponents) { + lazyPaintables.add(class1); + } + } + Class[] deferredComponents = getEagerComponents(); + if (deferredComponents != null) { + for (Class class1 : deferredComponents) { + deferredPaintables.add(class1); + } + } + } + + /** + * @return an array of components whose load style should be overridden to + * {@link LoadStyle#EAGER} + */ + protected abstract Class[] getEagerComponents(); + + /** + * @return an array of components whose load style should be overridden to + * {@link LoadStyle#LAZY} + */ + protected abstract Class[] getLazyComponents(); + + /** + * @return an array of components whose load style should be overridden to + * {@link LoadStyle#DEFERRED} + */ + protected abstract Class[] getDeferredComponents(); + +} diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/EagerWidgetMapGenerator.java b/client-compiler/src/com/vaadin/server/widgetsetutils/EagerWidgetMapGenerator.java new file mode 100644 index 0000000000..568dc939e7 --- /dev/null +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/EagerWidgetMapGenerator.java @@ -0,0 +1,41 @@ +/* + * Copyright 2011 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 com.vaadin.client.ServerConnector; +import com.vaadin.shared.ui.Connect.LoadStyle; + +/** + * WidgetMap generator that builds a widgetset that packs all included widgets + * into a single JavaScript file loaded at application initialization. Initially + * loaded data will be relatively large, but minimal amount of server requests + * will be done. + *

+ * This is the default generator in version 6.4 and produces similar type of + * widgetset as in previous versions of Vaadin. To activate "code splitting", + * use the {@link WidgetMapGenerator} instead, that loads most components + * deferred. + * + * @see WidgetMapGenerator + * + */ +public class EagerWidgetMapGenerator extends WidgetMapGenerator { + + @Override + protected LoadStyle getLoadStyle(Class connector) { + return LoadStyle.EAGER; + } +} diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/LazyWidgetMapGenerator.java b/client-compiler/src/com/vaadin/server/widgetsetutils/LazyWidgetMapGenerator.java new file mode 100644 index 0000000000..9e46b6d9dd --- /dev/null +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/LazyWidgetMapGenerator.java @@ -0,0 +1,35 @@ +/* + * Copyright 2011 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 com.vaadin.client.ServerConnector; +import com.vaadin.shared.ui.Connect.LoadStyle; + +/** + * WidgetMap generator that builds a widgetset that optimizes the transferred + * data. Widgets are loaded only when used if the widgetset is built with this + * generator. + * + * @see WidgetMapGenerator + * + */ +public class LazyWidgetMapGenerator extends WidgetMapGenerator { + @Override + protected LoadStyle getLoadStyle(Class connector) { + return LoadStyle.LAZY; + } + +} diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/WidgetMapGenerator.java b/client-compiler/src/com/vaadin/server/widgetsetutils/WidgetMapGenerator.java new file mode 100644 index 0000000000..b90791d61b --- /dev/null +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/WidgetMapGenerator.java @@ -0,0 +1,434 @@ +/* + * Copyright 2011 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.PrintWriter; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Map; +import java.util.TreeSet; + +import com.google.gwt.core.ext.Generator; +import com.google.gwt.core.ext.GeneratorContext; +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.TreeLogger.Type; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.core.ext.typeinfo.JClassType; +import com.google.gwt.core.ext.typeinfo.TypeOracle; +import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; +import com.google.gwt.user.rebind.SourceWriter; +import com.vaadin.client.ServerConnector; +import com.vaadin.client.ui.UnknownComponentConnector; +import com.vaadin.client.ui.UI.UIConnector; +import com.vaadin.server.ClientConnector; +import com.vaadin.shared.Connector; +import com.vaadin.shared.ui.Connect; +import com.vaadin.shared.ui.Connect.LoadStyle; + +/** + * WidgetMapGenerator's are GWT generator to build WidgetMapImpl dynamically + * based on {@link Connect} annotations available in workspace. By modifying the + * generator it is possible to do some fine tuning for the generated widgetset + * (aka client side engine). The components to be included in the client side + * engine can modified be overriding {@link #getUsedConnectors()}. + *

+ * The generator also decides how the client side component implementations are + * loaded to the browser. The default generator is + * {@link EagerWidgetMapGenerator} that builds a monolithic client side engine + * that loads all widget implementation on application initialization. This has + * been the only option until Vaadin 6.4. + *

+ * This generator uses the loadStyle hints from the {@link Connect} annotations. + * Depending on the {@link LoadStyle} used, the widget may be included in the + * initially loaded JavaScript, loaded when the application has started and + * there is no communication to server or lazy loaded when the implementation is + * absolutely needed. + *

+ * The GWT module description file of the widgetset ( + * ...Widgetset.gwt.xml) can be used to define the + * WidgetMapGenarator. An example that defines this generator to be used: + * + *

+ * 
+ * <generate-with
+ *           class="com.vaadin.server.widgetsetutils.MyWidgetMapGenerator">
+ *          <when-type-is class="com.vaadin.client.WidgetMap" />
+ * </generate-with>
+ * 
+ * 
+ * 
+ * + *

+ * Vaadin package also includes {@link LazyWidgetMapGenerator}, which is a good + * option if the transferred data should be minimized, and + * {@link CustomWidgetMapGenerator} for easy overriding of loading strategies. + * + */ +public class WidgetMapGenerator extends Generator { + + private static String serverConnectorClassName = ServerConnector.class + .getName(); + + private String packageName; + private String className; + + @Override + public String generate(TreeLogger logger, GeneratorContext context, + String typeName) throws UnableToCompleteException { + + try { + TypeOracle typeOracle = context.getTypeOracle(); + + // get classType and save instance variables + JClassType classType = typeOracle.getType(typeName); + packageName = classType.getPackage().getName(); + className = classType.getSimpleSourceName() + "Impl"; + // Generate class source code + generateClass(logger, context); + } catch (Exception e) { + logger.log(TreeLogger.ERROR, "WidgetMap creation failed", e); + } + // return the fully qualifed name of the class generated + return packageName + "." + className; + } + + /** + * Generate source code for WidgetMapImpl + * + * @param logger + * Logger object + * @param context + * Generator context + * @throws UnableToCompleteException + */ + private void generateClass(TreeLogger logger, GeneratorContext context) + throws UnableToCompleteException { + // get print writer that receives the source code + PrintWriter printWriter = null; + printWriter = context.tryCreate(logger, packageName, className); + // print writer if null, source code has ALREADY been generated, + // return (WidgetMap is equal to all permutations atm) + if (printWriter == null) { + return; + } + logger.log(Type.INFO, + "Detecting Vaadin connectors in classpath to generate WidgetMapImpl.java ..."); + Date date = new Date(); + + // init composer, set class properties, create source writer + ClassSourceFileComposerFactory composer = null; + composer = new ClassSourceFileComposerFactory(packageName, className); + composer.addImport("com.google.gwt.core.client.GWT"); + composer.addImport("java.util.HashMap"); + composer.addImport("com.google.gwt.core.client.RunAsyncCallback"); + composer.setSuperclass("com.vaadin.client.WidgetMap"); + SourceWriter sourceWriter = composer.createSourceWriter(context, + printWriter); + + Collection> connectors = getUsedConnectors(context + .getTypeOracle()); + + validateConnectors(logger, connectors); + logConnectors(logger, context, connectors); + + // generator constructor source code + generateImplementationDetector(logger, sourceWriter, connectors); + generateInstantiatorMethod(sourceWriter, connectors); + // close generated class + sourceWriter.outdent(); + sourceWriter.println("}"); + // commit generated class + context.commit(logger, printWriter); + logger.log(Type.INFO, + "Done. (" + (new Date().getTime() - date.getTime()) / 1000 + + "seconds)"); + + } + + private void validateConnectors(TreeLogger logger, + Collection> connectors) { + + Iterator> iter = connectors.iterator(); + while (iter.hasNext()) { + Class connectorClass = iter.next(); + Connect annotation = connectorClass.getAnnotation(Connect.class); + if (!ClientConnector.class.isAssignableFrom(annotation.value())) { + logger.log( + Type.WARN, + "Connector class " + + annotation.value().getName() + + " defined in @Connect annotation is not a subclass of " + + ClientConnector.class.getName() + + ". The component connector " + + connectorClass.getName() + + " will not be included in the widgetset."); + iter.remove(); + } + } + + } + + private void logConnectors(TreeLogger logger, GeneratorContext context, + Collection> connectors) { + logger.log(Type.INFO, + "Widget set will contain implementations for following component connectors: "); + + TreeSet classNames = new TreeSet(); + HashMap loadStyle = new HashMap(); + for (Class connectorClass : connectors) { + String className = connectorClass.getCanonicalName(); + classNames.add(className); + if (getLoadStyle(connectorClass) == LoadStyle.DEFERRED) { + loadStyle.put(className, "DEFERRED"); + } else if (getLoadStyle(connectorClass) == LoadStyle.LAZY) { + loadStyle.put(className, "LAZY"); + } + + } + for (String className : classNames) { + String msg = className; + if (loadStyle.containsKey(className)) { + msg += " (load style: " + loadStyle.get(className) + ")"; + } + logger.log(Type.INFO, "\t" + msg); + } + } + + /** + * This method is protected to allow creation of optimized widgetsets. The + * Widgetset will contain only implementation returned by this function. If + * one knows which widgets are needed for the application, returning only + * them here will significantly optimize the size of the produced JS. + * + * @return a collections of Vaadin components that will be added to + * widgetset + */ + @SuppressWarnings("unchecked") + private Collection> getUsedConnectors( + TypeOracle typeOracle) { + JClassType connectorType = typeOracle.findType(Connector.class + .getName()); + Collection> connectors = new HashSet>(); + for (JClassType jClassType : connectorType.getSubtypes()) { + Connect annotation = jClassType.getAnnotation(Connect.class); + if (annotation != null) { + try { + Class clazz = (Class) Class + .forName(jClassType.getQualifiedSourceName()); + connectors.add(clazz); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + } + return connectors; + } + + /** + * Returns true if the widget for given component will be lazy loaded by the + * client. The default implementation reads the information from the + * {@link Connect} annotation. + *

+ * The method can be overridden to optimize the widget loading mechanism. If + * the Widgetset is wanted to be optimized for a network with a high latency + * or for a one with a very fast throughput, it may be good to return false + * for every component. + * + * @param connector + * @return true iff the widget for given component should be lazy loaded by + * the client side engine + */ + protected LoadStyle getLoadStyle(Class connector) { + Connect annotation = connector.getAnnotation(Connect.class); + return annotation.loadStyle(); + } + + private void generateInstantiatorMethod( + SourceWriter sourceWriter, + Collection> connectorsHavingComponentAnnotation) { + + Collection> deferredWidgets = new LinkedList>(); + + // TODO detect if it would be noticably faster to instantiate with a + // lookup with index than with the hashmap + + sourceWriter.println("public void ensureInstantiator(Class classType) {"); + sourceWriter.println("if(!instmap.containsKey(classType)){"); + boolean first = true; + + ArrayList> lazyLoadedConnectors = new ArrayList>(); + + HashSet> connectorsWithInstantiator = new HashSet>(); + + for (Class class1 : connectorsHavingComponentAnnotation) { + Class clientClass = class1; + if (connectorsWithInstantiator.contains(clientClass)) { + continue; + } + if (clientClass == UIConnector.class) { + // Roots are not instantiated by widgetset + continue; + } + if (!first) { + sourceWriter.print(" else "); + } else { + first = false; + } + sourceWriter.print("if( classType == " + clientClass.getName() + + ".class) {"); + + String instantiator = "new WidgetInstantiator() {\n public " + + serverConnectorClassName + + " get() {\n return GWT.create(" + clientClass.getName() + + ".class );\n}\n}\n"; + + LoadStyle loadStyle = getLoadStyle(class1); + + if (loadStyle != LoadStyle.EAGER) { + sourceWriter + .print("ApplicationConfiguration.startWidgetLoading();\n" + + "GWT.runAsync( \n" + + "new WidgetLoader() { void addInstantiator() {instmap.put(" + + clientClass.getName() + + ".class," + + instantiator + ");}});\n"); + lazyLoadedConnectors.add(class1); + + if (loadStyle == LoadStyle.DEFERRED) { + deferredWidgets.add(class1); + } + + } else { + // widget implementation in initially loaded js script + sourceWriter.print("instmap.put("); + sourceWriter.print(clientClass.getName()); + sourceWriter.print(".class, "); + sourceWriter.print(instantiator); + sourceWriter.print(");"); + } + sourceWriter.print("}"); + connectorsWithInstantiator.add(clientClass); + } + + sourceWriter.println("}"); + + sourceWriter.println("}"); + + sourceWriter.println("public Class[] getDeferredLoadedConnectors() {"); + + sourceWriter.println("return new Class[] {"); + first = true; + for (Class class2 : deferredWidgets) { + if (!first) { + sourceWriter.println(","); + } + first = false; + sourceWriter.print(class2.getName() + ".class"); + } + + sourceWriter.println("};"); + sourceWriter.println("}"); + + // in constructor add a "thread" that lazyly loads lazy loaded widgets + // if communication to server idles + + // TODO an array of lazy loaded widgets + + // TODO an index of last ensured widget in array + + sourceWriter.println("public " + serverConnectorClassName + + " instantiate(Class classType) {"); + sourceWriter.indent(); + sourceWriter.println(serverConnectorClassName + + " p = super.instantiate(classType); if(p!= null) return p;"); + sourceWriter.println("return instmap.get(classType).get();"); + + sourceWriter.outdent(); + sourceWriter.println("}"); + + } + + /** + * + * @param logger + * logger to print messages to + * @param sourceWriter + * Source writer to output source code + * @param paintablesHavingWidgetAnnotation + * @throws UnableToCompleteException + */ + private void generateImplementationDetector( + TreeLogger logger, + SourceWriter sourceWriter, + Collection> paintablesHavingWidgetAnnotation) + throws UnableToCompleteException { + sourceWriter + .println("public Class " + + "getConnectorClassForServerSideClassName(String fullyQualifiedName) {"); + sourceWriter.indent(); + sourceWriter + .println("fullyQualifiedName = fullyQualifiedName.intern();"); + + // Keep track of encountered mappings to detect conflicts + Map, Class> mappings = new HashMap, Class>(); + + for (Class connectorClass : paintablesHavingWidgetAnnotation) { + Class clientConnectorClass = getClientConnectorClass(connectorClass); + + // Check for conflicts + Class prevousMapping = mappings.put( + clientConnectorClass, connectorClass); + if (prevousMapping != null) { + logger.log(Type.ERROR, + "Both " + connectorClass.getName() + " and " + + prevousMapping.getName() + + " have @Connect referring to " + + clientConnectorClass.getName() + "."); + throw new UnableToCompleteException(); + } + + sourceWriter.print("if ( fullyQualifiedName == \""); + sourceWriter.print(clientConnectorClass.getName()); + sourceWriter.print("\" ) { ensureInstantiator(" + + connectorClass.getName() + ".class); return "); + sourceWriter.print(connectorClass.getName()); + sourceWriter.println(".class;}"); + sourceWriter.print("else "); + } + sourceWriter.println("return " + + UnknownComponentConnector.class.getName() + ".class;"); + sourceWriter.outdent(); + sourceWriter.println("}"); + + } + + private static Class getClientConnectorClass( + Class connectorClass) { + Connect annotation = connectorClass.getAnnotation(Connect.class); + return (Class) annotation.value(); + } +} diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/WidgetSetBuilder.java b/client-compiler/src/com/vaadin/server/widgetsetutils/WidgetSetBuilder.java new file mode 100644 index 0000000000..4137662b35 --- /dev/null +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/WidgetSetBuilder.java @@ -0,0 +1,213 @@ +/* + * Copyright 2011 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.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. + * + *

+ * 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 { + if (args.length == 0) { + printUsage(); + } else { + String widgetsetname = args[0]; + updateWidgetSet(widgetsetname); + + } + } + + public static void updateWidgetSet(final String widgetset) + throws IOException, FileNotFoundException { + boolean changed = false; + + Map availableWidgetSets = ClassPathExplorer + .getAvailableWidgetSets(); + + URL sourceUrl = availableWidgetSets.get(widgetset); + if (sourceUrl == null) { + // find first/default source directory + sourceUrl = ClassPathExplorer.getDefaultSourceDirectory(); + } + + String widgetsetfilename = sourceUrl.getFile() + "/" + + widgetset.replace(".", "/") + ".gwt.xml"; + + File widgetsetFile = new File(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(); + PrintStream printStream = new PrintStream(new FileOutputStream( + widgetsetFile)); + printStream.print("\n" + + "\n"); + printStream.print("\n"); + printStream + .print(" \n" + + " \n"); + printStream.print("\n\n"); + printStream.close(); + changed = true; + } + + String content = readFile(widgetsetFile); + if (isEditable(content)) { + String originalContent = content; + + Collection oldInheritedWidgetsets = getCurrentInheritedWidgetsets(content); + + // add widgetsets that do not exist + Iterator 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(widgetsetfilename, 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("", ""); + } + + 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("", "\n " + "\n"); + } + + private static Collection getCurrentInheritedWidgetsets( + String content) { + HashSet 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 { + 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"); + } + fi.close(); + 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"); + + } + +} diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ArraySerializer.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ArraySerializer.java new file mode 100644 index 0000000000..4ab5cccb2e --- /dev/null +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ArraySerializer.java @@ -0,0 +1,90 @@ +/* + * Copyright 2011 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.metadata; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.typeinfo.JArrayType; +import com.google.gwt.core.ext.typeinfo.JType; +import com.google.gwt.json.client.JSONArray; +import com.google.gwt.user.rebind.SourceWriter; +import com.vaadin.client.communication.JsonDecoder; +import com.vaadin.client.communication.JsonEncoder; +import com.vaadin.server.widgetsetutils.ConnectorBundleLoaderFactory; + +public class ArraySerializer extends JsonSerializer { + + private final JArrayType arrayType; + + public ArraySerializer(JArrayType arrayType) { + super(arrayType); + this.arrayType = arrayType; + } + + @Override + protected void printDeserializerBody(TreeLogger logger, SourceWriter w, + String type, String jsonValue, String connection) { + JType leafType = arrayType.getLeafType(); + int rank = arrayType.getRank(); + + w.println(JSONArray.class.getName() + " jsonArray = " + jsonValue + + ".isArray();"); + + // Type value = new Type[jsonArray.size()][][]; + w.print(arrayType.getQualifiedSourceName() + " value = new " + + leafType.getQualifiedSourceName() + "[jsonArray.size()]"); + for (int i = 1; i < rank; i++) { + w.print("[]"); + } + w.println(";"); + + w.println("for(int i = 0 ; i < value.length; i++) {"); + w.indent(); + + JType componentType = arrayType.getComponentType(); + + w.print("value[i] = (" + + ConnectorBundleLoaderFactory.getBoxedTypeName(componentType) + + ") " + JsonDecoder.class.getName() + ".decodeValue("); + ConnectorBundleLoaderFactory.writeTypeCreator(w, componentType); + w.print(", jsonArray.get(i), null, " + connection + ")"); + + w.println(";"); + + w.outdent(); + w.println("}"); + + w.println("return value;"); + } + + @Override + protected void printSerializerBody(TreeLogger logger, SourceWriter w, + String value, String applicationConnection) { + w.println(JSONArray.class.getName() + " values = new " + + JSONArray.class.getName() + "();"); + // JPrimitiveType primitive = componentType.isPrimitive(); + w.println("for (int i = 0; i < " + value + ".length; i++) {"); + w.indent(); + w.print("values.set(i, "); + w.print(JsonEncoder.class.getName() + ".encode(" + value + + "[i], false, " + applicationConnection + ")"); + w.println(");"); + w.outdent(); + w.println("}"); + w.println("return values;"); + } + +} diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ClientRpcVisitor.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ClientRpcVisitor.java new file mode 100644 index 0000000000..3b78519a0d --- /dev/null +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ClientRpcVisitor.java @@ -0,0 +1,45 @@ +/* + * Copyright 2011 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.metadata; + +import java.util.Set; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.typeinfo.JClassType; +import com.google.gwt.core.ext.typeinfo.JMethod; +import com.google.gwt.core.ext.typeinfo.JType; + +public class ClientRpcVisitor extends TypeVisitor { + @Override + public void visitClientRpc(TreeLogger logger, JClassType type, + ConnectorBundle bundle) { + Set hierarchy = type + .getFlattenedSupertypeHierarchy(); + for (JClassType subType : hierarchy) { + JMethod[] methods = subType.getMethods(); + for (JMethod method : methods) { + bundle.setNeedsInvoker(type, method); + bundle.setNeedsParamTypes(type, method); + + JType[] parameterTypes = method.getParameterTypes(); + for (JType paramType : parameterTypes) { + bundle.setNeedsSerialize(paramType); + } + } + } + } +} diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java new file mode 100644 index 0000000000..1d37d12a45 --- /dev/null +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java @@ -0,0 +1,611 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.server.widgetsetutils.metadata; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.TreeLogger.Type; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.core.ext.typeinfo.JArrayType; +import com.google.gwt.core.ext.typeinfo.JClassType; +import com.google.gwt.core.ext.typeinfo.JEnumType; +import com.google.gwt.core.ext.typeinfo.JMethod; +import com.google.gwt.core.ext.typeinfo.JParameterizedType; +import com.google.gwt.core.ext.typeinfo.JType; +import com.google.gwt.core.ext.typeinfo.NotFoundException; +import com.google.gwt.core.ext.typeinfo.TypeOracle; +import com.google.gwt.json.client.JSONValue; +import com.vaadin.client.ApplicationConnection; +import com.vaadin.client.ComponentConnector; +import com.vaadin.client.ServerConnector; +import com.vaadin.client.communication.JSONSerializer; +import com.vaadin.client.ui.UnknownComponentConnector; +import com.vaadin.shared.communication.ClientRpc; +import com.vaadin.shared.communication.ServerRpc; +import com.vaadin.shared.ui.Connect; + +public class ConnectorBundle { + private static final String FAIL_IF_NOT_SERIALIZABLE = "vFailIfNotSerializable"; + + private final String name; + private final ConnectorBundle previousBundle; + private final Collection visitors; + private final Map customSerializers; + + private final Set hasSerializeSupport = new HashSet(); + private final Set needsSerializeSupport = new HashSet(); + private final Map serializers = new HashMap(); + + private final Set needsPropertyList = new HashSet(); + private final Set needsGwtConstructor = new HashSet(); + private final Set visitedTypes = new HashSet(); + private final Set needsProxySupport = new HashSet(); + + private final Map> identifiers = new HashMap>(); + private final Map> needsReturnType = new HashMap>(); + private final Map> needsInvoker = new HashMap>(); + private final Map> needsParamTypes = new HashMap>(); + private final Map> needsDelayedInfo = new HashMap>(); + + private final Set needsSetter = new HashSet(); + private final Set needsType = new HashSet(); + private final Set needsGetter = new HashSet(); + private final Set needsDelegateToWidget = new HashSet(); + + private ConnectorBundle(String name, ConnectorBundle previousBundle, + Collection visitors, + Map customSerializers) { + this.name = name; + this.previousBundle = previousBundle; + this.visitors = visitors; + this.customSerializers = customSerializers; + } + + public ConnectorBundle(String name, ConnectorBundle previousBundle) { + this(name, previousBundle, previousBundle.visitors, + previousBundle.customSerializers); + } + + public ConnectorBundle(String name, Collection visitors, + TypeOracle oracle) throws NotFoundException { + this(name, null, visitors, findCustomSerializers(oracle)); + } + + private static Map findCustomSerializers( + TypeOracle oracle) throws NotFoundException { + Map serializers = new HashMap(); + + JClassType serializerInterface = oracle.findType(JSONSerializer.class + .getName()); + JType[] deserializeParamTypes = new JType[] { + oracle.findType(com.vaadin.client.metadata.Type.class + .getName()), + oracle.findType(JSONValue.class.getName()), + oracle.findType(ApplicationConnection.class.getName()) }; + String deserializeMethodName = "deserialize"; + // Just test that the method exists + serializerInterface.getMethod(deserializeMethodName, + deserializeParamTypes); + + for (JClassType serializer : serializerInterface.getSubtypes()) { + JMethod deserializeMethod = serializer.findMethod( + deserializeMethodName, deserializeParamTypes); + if (deserializeMethod == null) { + continue; + } + JType returnType = deserializeMethod.getReturnType(); + + serializers.put(returnType, serializer); + } + return serializers; + } + + public void setNeedsGwtConstructor(JClassType type) { + if (!needsGwtConstructor(type)) { + needsGwtConstructor.add(type); + } + } + + private boolean needsGwtConstructor(JClassType type) { + if (needsGwtConstructor.contains(type)) { + return true; + } else { + return previousBundle != null + && previousBundle.needsGwtConstructor(type); + } + } + + public void setIdentifier(JClassType type, String identifier) { + if (!hasIdentifier(type, identifier)) { + addMapping(identifiers, type, identifier); + } + } + + private boolean hasIdentifier(JClassType type, String identifier) { + if (hasMapping(identifiers, type, identifier)) { + return true; + } else { + return previousBundle != null + && previousBundle.hasIdentifier(type, identifier); + } + } + + public ConnectorBundle getPreviousBundle() { + return previousBundle; + } + + public String getName() { + return name; + } + + public Map> getIdentifiers() { + return Collections.unmodifiableMap(identifiers); + } + + public Set getGwtConstructors() { + return Collections.unmodifiableSet(needsGwtConstructor); + } + + public void processTypes(TreeLogger logger, Collection types) + throws UnableToCompleteException { + for (JClassType type : types) { + processType(logger, type); + } + } + + public void processType(TreeLogger logger, JClassType type) + throws UnableToCompleteException { + if (!isTypeVisited(type)) { + for (TypeVisitor typeVisitor : visitors) { + invokeVisitor(logger, type, typeVisitor); + } + visitedTypes.add(type); + purgeSerializeSupportQueue(logger); + } + } + + private boolean isTypeVisited(JClassType type) { + if (visitedTypes.contains(type)) { + return true; + } else { + return previousBundle != null && previousBundle.isTypeVisited(type); + } + } + + private void purgeSerializeSupportQueue(TreeLogger logger) + throws UnableToCompleteException { + while (!needsSerializeSupport.isEmpty()) { + Iterator iterator = needsSerializeSupport.iterator(); + JType type = iterator.next(); + iterator.remove(); + + if (hasSserializeSupport(type)) { + continue; + } + + addSerializeSupport(logger, type); + } + } + + private void addSerializeSupport(TreeLogger logger, JType type) + throws UnableToCompleteException { + hasSerializeSupport.add(type); + + JParameterizedType parametrized = type.isParameterized(); + if (parametrized != null) { + for (JClassType parameterType : parametrized.getTypeArgs()) { + setNeedsSerialize(parameterType); + } + } + + if (serializationHandledByFramework(type)) { + return; + } + + JClassType customSerializer = customSerializers.get(type); + JClassType typeAsClass = type.isClass(); + JEnumType enumType = type.isEnum(); + JArrayType arrayType = type.isArray(); + + if (customSerializer != null) { + logger.log(Type.INFO, "Will serialize " + type + " using " + + customSerializer.getName()); + setSerializer(type, new CustomSerializer(customSerializer)); + } else if (arrayType != null) { + logger.log(Type.INFO, "Will serialize " + type + " as an array"); + setSerializer(type, new ArraySerializer(arrayType)); + setNeedsSerialize(arrayType.getComponentType()); + } else if (enumType != null) { + logger.log(Type.INFO, "Will serialize " + type + " as an enum"); + setSerializer(type, new EnumSerializer(enumType)); + } else if (typeAsClass != null) { + // Bean + checkSerializable(logger, typeAsClass); + + logger.log(Type.INFO, "Will serialize " + type + " as a bean"); + + setNeedsPropertyList(typeAsClass); + + for (Property property : getProperties(typeAsClass)) { + setNeedsGwtConstructor(property.getBeanType()); + setNeedsSetter(property); + + // Getters needed for reading previous value that should be + // passed to sub encoder + setNeedsGetter(property); + setNeedsType(property); + + JType propertyType = property.getPropertyType(); + setNeedsSerialize(propertyType); + } + } + } + + private void checkSerializable(TreeLogger logger, JClassType type) + throws UnableToCompleteException { + JClassType javaSerializable = type.getOracle().findType( + Serializable.class.getName()); + boolean serializable = type.isAssignableTo(javaSerializable); + if (!serializable) { + boolean abortCompile = "true".equals(System + .getProperty(FAIL_IF_NOT_SERIALIZABLE)); + logger.log( + abortCompile ? Type.ERROR : Type.WARN, + type + + " is used in RPC or shared state but does not implement " + + Serializable.class.getName() + + ". Communication will work but the Application on server side cannot be serialized if it refers to objects of this type. " + + "If the system property " + + FAIL_IF_NOT_SERIALIZABLE + + " is set to \"true\", this causes the compilation to fail instead of just emitting a warning."); + if (abortCompile) { + throw new UnableToCompleteException(); + } + } + } + + private void setSerializer(JType type, GeneratedSerializer serializer) { + if (!hasSerializer(type)) { + serializers.put(type, serializer); + } + } + + private boolean hasSerializer(JType type) { + if (serializers.containsKey(type)) { + return true; + } else { + return previousBundle != null && previousBundle.hasSerializer(type); + } + } + + public Map getSerializers() { + return Collections.unmodifiableMap(serializers); + } + + private void setNeedsGetter(Property property) { + if (!isNeedsGetter(property)) { + needsGetter.add(property); + } + } + + private boolean isNeedsGetter(Property property) { + if (needsGetter.contains(property)) { + return true; + } else { + return previousBundle != null + && previousBundle.isNeedsGetter(property); + } + } + + public Set getNeedsGetter() { + return Collections.unmodifiableSet(needsGetter); + } + + private void setNeedsType(Property property) { + if (!isNeedsType(property)) { + needsType.add(property); + } + } + + public Set getNeedsType() { + return Collections.unmodifiableSet(needsType); + } + + private boolean isNeedsType(Property property) { + if (needsType.contains(property)) { + return true; + } else { + return previousBundle != null + && previousBundle.isNeedsType(property); + } + } + + public void setNeedsSetter(Property property) { + if (!isNeedsSetter(property)) { + needsSetter.add(property); + } + } + + private boolean isNeedsSetter(Property property) { + if (needsSetter.contains(property)) { + return true; + } else { + return previousBundle != null + && previousBundle.isNeedsSetter(property); + } + } + + public Set getNeedsSetter() { + return Collections.unmodifiableSet(needsSetter); + } + + private void setNeedsPropertyList(JClassType type) { + if (!isNeedsPropertyList(type)) { + needsPropertyList.add(type); + } + } + + private boolean isNeedsPropertyList(JClassType type) { + if (needsPropertyList.contains(type)) { + return true; + } else { + return previousBundle != null + && previousBundle.isNeedsPropertyList(type); + } + } + + public Set getNeedsPropertyListing() { + return Collections.unmodifiableSet(needsPropertyList); + } + + public Collection getProperties(JClassType type) { + HashSet properties = new HashSet(); + + properties.addAll(MethodProperty.findProperties(type)); + properties.addAll(FieldProperty.findProperties(type)); + + return properties; + } + + private void invokeVisitor(TreeLogger logger, JClassType type, + TypeVisitor typeVisitor) throws UnableToCompleteException { + TreeLogger subLogger = logger.branch(Type.TRACE, + "Visiting " + type.getName() + " with " + + typeVisitor.getClass().getSimpleName()); + if (isConnectedConnector(type)) { + typeVisitor.visitConnector(subLogger, type, this); + } + if (isClientRpc(type)) { + typeVisitor.visitClientRpc(subLogger, type, this); + } + if (isServerRpc(type)) { + typeVisitor.visitServerRpc(subLogger, type, this); + } + } + + public void processSubTypes(TreeLogger logger, JClassType type) + throws UnableToCompleteException { + processTypes(logger, Arrays.asList(type.getSubtypes())); + } + + public void setNeedsReturnType(JClassType type, JMethod method) { + if (!isNeedsReturnType(type, method)) { + addMapping(needsReturnType, type, method); + } + } + + private boolean isNeedsReturnType(JClassType type, JMethod method) { + if (hasMapping(needsReturnType, type, method)) { + return true; + } else { + return previousBundle != null + && previousBundle.isNeedsReturnType(type, method); + } + } + + public Map> getMethodReturnTypes() { + return Collections.unmodifiableMap(needsReturnType); + } + + private static boolean isClientRpc(JClassType type) { + return isType(type, ClientRpc.class); + } + + private static boolean isServerRpc(JClassType type) { + return isType(type, ServerRpc.class); + } + + public static boolean isConnectedConnector(JClassType type) { + return isConnected(type) && isType(type, ServerConnector.class); + } + + private static boolean isConnected(JClassType type) { + return type.isAnnotationPresent(Connect.class) + || type.getQualifiedSourceName().equals( + UnknownComponentConnector.class.getCanonicalName()); + } + + public static boolean isConnectedComponentConnector(JClassType type) { + return isConnected(type) && isType(type, ComponentConnector.class); + } + + private static boolean isType(JClassType type, Class class1) { + try { + return type.getOracle().getType(class1.getName()) + .isAssignableFrom(type); + } catch (NotFoundException e) { + throw new RuntimeException("Could not find " + class1.getName(), e); + } + } + + public void setNeedsInvoker(JClassType type, JMethod method) { + if (!isNeedsInvoker(type, method)) { + addMapping(needsInvoker, type, method); + } + } + + private void addMapping(Map> map, K key, V value) { + Set set = map.get(key); + if (set == null) { + set = new HashSet(); + map.put(key, set); + } + set.add(value); + } + + private boolean hasMapping(Map> map, K key, V value) { + return map.containsKey(key) && map.get(key).contains(value); + } + + private boolean isNeedsInvoker(JClassType type, JMethod method) { + if (hasMapping(needsInvoker, type, method)) { + return true; + } else { + return previousBundle != null + && previousBundle.isNeedsInvoker(type, method); + } + } + + public Map> getNeedsInvoker() { + return Collections.unmodifiableMap(needsInvoker); + } + + public void setNeedsParamTypes(JClassType type, JMethod method) { + if (!isNeedsParamTypes(type, method)) { + addMapping(needsParamTypes, type, method); + } + } + + private boolean isNeedsParamTypes(JClassType type, JMethod method) { + if (hasMapping(needsParamTypes, type, method)) { + return true; + } else { + return previousBundle != null + && previousBundle.isNeedsParamTypes(type, method); + } + } + + public Map> getNeedsParamTypes() { + return Collections.unmodifiableMap(needsParamTypes); + } + + public void setNeedsProxySupport(JClassType type) { + if (!isNeedsProxySupport(type)) { + needsProxySupport.add(type); + } + } + + private boolean isNeedsProxySupport(JClassType type) { + if (needsProxySupport.contains(type)) { + return true; + } else { + return previousBundle != null + && previousBundle.isNeedsProxySupport(type); + } + } + + public Set getNeedsProxySupport() { + return Collections.unmodifiableSet(needsProxySupport); + } + + public void setNeedsDelayedInfo(JClassType type, JMethod method) { + if (!isNeedsDelayedInfo(type, method)) { + addMapping(needsDelayedInfo, type, method); + } + } + + private boolean isNeedsDelayedInfo(JClassType type, JMethod method) { + if (hasMapping(needsDelayedInfo, type, method)) { + return true; + } else { + return previousBundle != null + && previousBundle.isNeedsDelayedInfo(type, method); + } + } + + public Map> getNeedsDelayedInfo() { + return Collections.unmodifiableMap(needsDelayedInfo); + } + + public void setNeedsSerialize(JType type) { + if (!hasSserializeSupport(type)) { + needsSerializeSupport.add(type); + } + } + + private static Set> frameworkHandledTypes = new HashSet>(); + { + frameworkHandledTypes.add(String.class); + frameworkHandledTypes.add(Boolean.class); + frameworkHandledTypes.add(Integer.class); + frameworkHandledTypes.add(Float.class); + frameworkHandledTypes.add(Double.class); + frameworkHandledTypes.add(Long.class); + frameworkHandledTypes.add(Enum.class); + frameworkHandledTypes.add(String[].class); + frameworkHandledTypes.add(Object[].class); + frameworkHandledTypes.add(Map.class); + frameworkHandledTypes.add(List.class); + frameworkHandledTypes.add(Set.class); + frameworkHandledTypes.add(Byte.class); + frameworkHandledTypes.add(Character.class); + + } + + private boolean serializationHandledByFramework(JType setterType) { + // Some types are handled by the framework at the moment. See #8449 + // This method should be removed at some point. + if (setterType.isPrimitive() != null) { + return true; + } + + String qualifiedName = setterType.getQualifiedSourceName(); + for (Class cls : frameworkHandledTypes) { + if (qualifiedName.equals(cls.getName())) { + return true; + } + } + + return false; + } + + private boolean hasSserializeSupport(JType type) { + if (hasSerializeSupport.contains(type)) { + return true; + } else { + return previousBundle != null + && previousBundle.hasSserializeSupport(type); + } + } + + public void setNeedsDelegateToWidget(Property property) { + if (!isNeedsDelegateToWidget(property)) { + needsDelegateToWidget.add(property); + } + } + + private boolean isNeedsDelegateToWidget(Property property) { + if (needsDelegateToWidget.contains(property)) { + return true; + } else { + return previousBundle != null + && previousBundle.isNeedsDelegateToWidget(property); + } + } + + public Set getNeedsDelegateToWidget() { + return Collections.unmodifiableSet(needsDelegateToWidget); + } +} \ No newline at end of file diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorInitVisitor.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorInitVisitor.java new file mode 100644 index 0000000000..3e863516a5 --- /dev/null +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorInitVisitor.java @@ -0,0 +1,27 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.server.widgetsetutils.metadata; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.TreeLogger.Type; +import com.google.gwt.core.ext.typeinfo.JClassType; +import com.vaadin.shared.ui.Connect; + +public class ConnectorInitVisitor extends TypeVisitor { + + @Override + public void visitConnector(TreeLogger logger, JClassType type, + ConnectorBundle bundle) { + Connect connectAnnotation = type.getAnnotation(Connect.class); + if (connectAnnotation != null) { + logger.log(Type.INFO, type.getName() + " will be in the " + + bundle.getName().replaceAll("^_*", "") + " bundle"); + bundle.setIdentifier(type, connectAnnotation.value() + .getCanonicalName()); + bundle.setNeedsGwtConstructor(type); + } + } + +} diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/CustomSerializer.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/CustomSerializer.java new file mode 100644 index 0000000000..a0105b4bf3 --- /dev/null +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/CustomSerializer.java @@ -0,0 +1,43 @@ +/* + * Copyright 2011 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.metadata; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.core.ext.typeinfo.JClassType; +import com.google.gwt.user.rebind.SourceWriter; +import com.vaadin.server.widgetsetutils.ConnectorBundleLoaderFactory; + +public class CustomSerializer implements GeneratedSerializer { + + private final JClassType serializerType; + + public CustomSerializer(JClassType serializerType) { + this.serializerType = serializerType; + } + + @Override + public void writeSerializerInstantiator(TreeLogger logger, SourceWriter w) + throws UnableToCompleteException { + w.print("return "); + w.print(GWT.class.getCanonicalName()); + w.print(".create("); + ConnectorBundleLoaderFactory.writeClassLiteral(w, serializerType); + w.println(");"); + } +} diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/EnumSerializer.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/EnumSerializer.java new file mode 100644 index 0000000000..5590e6cd7a --- /dev/null +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/EnumSerializer.java @@ -0,0 +1,58 @@ +/* + * Copyright 2011 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.metadata; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.typeinfo.JEnumConstant; +import com.google.gwt.core.ext.typeinfo.JEnumType; +import com.google.gwt.json.client.JSONString; +import com.google.gwt.user.rebind.SourceWriter; + +public class EnumSerializer extends JsonSerializer { + + private final JEnumType enumType; + + public EnumSerializer(JEnumType type) { + super(type); + enumType = type; + } + + @Override + protected void printDeserializerBody(TreeLogger logger, SourceWriter w, + String type, String jsonValue, String connection) { + w.println("String enumIdentifier = ((" + JSONString.class.getName() + + ")" + jsonValue + ").stringValue();"); + for (JEnumConstant e : enumType.getEnumConstants()) { + w.println("if (\"" + e.getName() + "\".equals(enumIdentifier)) {"); + w.indent(); + w.println("return " + enumType.getQualifiedSourceName() + "." + + e.getName() + ";"); + w.outdent(); + w.println("}"); + } + w.println("return null;"); + } + + @Override + protected void printSerializerBody(TreeLogger logger, SourceWriter w, + String value, String applicationConnection) { + // return new JSONString(castedValue.name()); + w.println("return new " + JSONString.class.getName() + "(" + value + + ".name());"); + } + +} diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/FieldProperty.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/FieldProperty.java new file mode 100644 index 0000000000..a7896a5bf6 --- /dev/null +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/FieldProperty.java @@ -0,0 +1,86 @@ +/* + * Copyright 2011 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.metadata; + +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.typeinfo.JClassType; +import com.google.gwt.core.ext.typeinfo.JField; +import com.google.gwt.user.rebind.SourceWriter; + +public class FieldProperty extends Property { + + private final JField field; + + private FieldProperty(JClassType beanType, JField field) { + super(field.getName(), beanType, field.getType()); + this.field = field; + } + + @Override + public void writeSetterBody(TreeLogger logger, SourceWriter w, + String beanVariable, String valueVariable) { + w.print("((%s) %s).%s = (%s)%s;", getBeanType() + .getQualifiedSourceName(), beanVariable, getName(), + getUnboxedPropertyTypeName(), valueVariable); + } + + @Override + public void writeGetterBody(TreeLogger logger, SourceWriter w, + String beanVariable) { + w.print("return ((%s) %s).%s;", getBeanType().getQualifiedSourceName(), + beanVariable, getName()); + } + + public static Collection findProperties(JClassType type) { + Collection properties = new ArrayList(); + + List fields = getPublicFields(type); + for (JField field : fields) { + properties.add(new FieldProperty(type, field)); + } + + return properties; + } + + private static List getPublicFields(JClassType type) { + Set names = new HashSet(); + ArrayList fields = new ArrayList(); + for (JClassType subType : type.getFlattenedSupertypeHierarchy()) { + JField[] subFields = subType.getFields(); + for (JField field : subFields) { + if (field.isPublic() && !field.isStatic() + && names.add(field.getName())) { + fields.add(field); + } + } + } + return fields; + } + + @Override + public T getAnnotation(Class annotationClass) { + return field.getAnnotation(annotationClass); + } + +} diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/GeneratedSerializer.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/GeneratedSerializer.java new file mode 100644 index 0000000000..8f6c8696fd --- /dev/null +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/GeneratedSerializer.java @@ -0,0 +1,26 @@ +/* + * Copyright 2011 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.metadata; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.user.rebind.SourceWriter; + +public interface GeneratedSerializer { + public void writeSerializerInstantiator(TreeLogger logger, SourceWriter w) + throws UnableToCompleteException; +} diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/JsonSerializer.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/JsonSerializer.java new file mode 100644 index 0000000000..6e521dc763 --- /dev/null +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/JsonSerializer.java @@ -0,0 +1,88 @@ +/* + * Copyright 2011 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.metadata; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.core.ext.typeinfo.JType; +import com.google.gwt.json.client.JSONValue; +import com.google.gwt.user.rebind.SourceWriter; +import com.vaadin.client.ApplicationConnection; +import com.vaadin.client.communication.JSONSerializer; + +public abstract class JsonSerializer implements GeneratedSerializer { + + private final JType type; + + public JsonSerializer(JType type) { + this.type = type; + } + + @Override + public void writeSerializerInstantiator(TreeLogger logger, SourceWriter w) + throws UnableToCompleteException { + + w.print("return new "); + w.print(JSONSerializer.class.getCanonicalName()); + w.print("<"); + w.print(type.getQualifiedSourceName()); + w.println(">() {"); + w.indent(); + + writeSerializerBody(logger, w); + + w.outdent(); + w.println("};"); + } + + protected void writeSerializerBody(TreeLogger logger, SourceWriter w) { + String qualifiedSourceName = type.getQualifiedSourceName(); + w.println("public " + JSONValue.class.getName() + " serialize(" + + qualifiedSourceName + " value, " + + ApplicationConnection.class.getName() + " connection) {"); + w.indent(); + // MouseEventDetails castedValue = (MouseEventDetails) value; + w.println(qualifiedSourceName + " castedValue = (" + + qualifiedSourceName + ") value;"); + + printSerializerBody(logger, w, "castedValue", "connection"); + + // End of serializer method + w.outdent(); + w.println("}"); + + // Deserializer + // T deserialize(Type type, JSONValue jsonValue, ApplicationConnection + // connection); + w.println("public " + qualifiedSourceName + " deserialize(Type type, " + + JSONValue.class.getName() + " jsonValue, " + + ApplicationConnection.class.getName() + " connection) {"); + w.indent(); + + printDeserializerBody(logger, w, "type", "jsonValue", "connection"); + + w.outdent(); + w.println("}"); + } + + protected abstract void printDeserializerBody(TreeLogger logger, + SourceWriter w, String type, String jsonValue, String connection); + + protected abstract void printSerializerBody(TreeLogger logger, + SourceWriter w, String value, String applicationConnection); + +} diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/MethodProperty.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/MethodProperty.java new file mode 100644 index 0000000000..318519f37d --- /dev/null +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/MethodProperty.java @@ -0,0 +1,130 @@ +/* + * Copyright 2011 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.metadata; + +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.typeinfo.JClassType; +import com.google.gwt.core.ext.typeinfo.JMethod; +import com.google.gwt.core.ext.typeinfo.JType; +import com.google.gwt.user.rebind.SourceWriter; + +public class MethodProperty extends Property { + + private final JMethod setter; + + private MethodProperty(JClassType beanType, JMethod setter) { + super(getTransportFieldName(setter), beanType, setter + .getParameterTypes()[0]); + this.setter = setter; + } + + public static Collection findProperties(JClassType type) { + Collection properties = new ArrayList(); + + List setters = getSetters(type); + for (JMethod setter : setters) { + properties.add(new MethodProperty(type, setter)); + } + + return properties; + } + + /** + * Returns a list of all setters found in the beanType or its parent class + * + * @param beanType + * The type to check + * @return A list of setter methods from the class and its parents + */ + private static List getSetters(JClassType beanType) { + List setterMethods = new ArrayList(); + + while (beanType != null + && !beanType.getQualifiedSourceName().equals( + Object.class.getName())) { + for (JMethod method : beanType.getMethods()) { + // Process all setters that have corresponding fields + if (!method.isPublic() || method.isStatic() + || !method.getName().startsWith("set") + || method.getParameterTypes().length != 1) { + // Not setter, skip to next method + continue; + } + setterMethods.add(method); + } + beanType = beanType.getSuperclass(); + } + + return setterMethods; + } + + @Override + public void writeSetterBody(TreeLogger logger, SourceWriter w, + String beanVariable, String valueVariable) { + w.print("(("); + w.print(getBeanType().getQualifiedSourceName()); + w.print(") "); + w.print(beanVariable); + w.print(")."); + w.print(setter.getName()); + w.print("(("); + w.print(getUnboxedPropertyTypeName()); + w.print(") "); + w.print(valueVariable); + w.println(");"); + } + + @Override + public void writeGetterBody(TreeLogger logger, SourceWriter w, + String beanVariable) { + w.print("return (("); + w.print(getBeanType().getQualifiedSourceName()); + w.print(") "); + w.print(beanVariable); + w.print(")."); + w.print(findGetter(getBeanType(), setter)); + w.print("();"); + } + + private String findGetter(JClassType beanType, JMethod setterMethod) { + JType setterParameterType = setterMethod.getParameterTypes()[0]; + String fieldName = setterMethod.getName().substring(3); + if (setterParameterType.getQualifiedSourceName().equals( + boolean.class.getName())) { + return "is" + fieldName; + } else { + return "get" + fieldName; + } + } + + private static String getTransportFieldName(JMethod setter) { + String baseName = setter.getName().substring(3); + return Character.toLowerCase(baseName.charAt(0)) + + baseName.substring(1); + } + + @Override + public T getAnnotation(Class annotationClass) { + return setter.getAnnotation(annotationClass); + } + +} diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/Property.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/Property.java new file mode 100644 index 0000000000..b55b70784a --- /dev/null +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/Property.java @@ -0,0 +1,89 @@ +/* + * Copyright 2011 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.metadata; + +import java.lang.annotation.Annotation; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.typeinfo.JClassType; +import com.google.gwt.core.ext.typeinfo.JPrimitiveType; +import com.google.gwt.core.ext.typeinfo.JType; +import com.google.gwt.user.rebind.SourceWriter; + +public abstract class Property { + private final String name; + private final JClassType beanType; + private final JType propertyType; + + protected Property(String name, JClassType beanType, JType propertyType) { + this.name = name; + this.beanType = beanType; + this.propertyType = propertyType; + } + + public String getName() { + return name; + } + + public JType getPropertyType() { + return propertyType; + } + + public String getUnboxedPropertyTypeName() { + JType propertyType = getPropertyType(); + JPrimitiveType primitive = propertyType.isPrimitive(); + if (primitive != null) { + return primitive.getQualifiedBoxedSourceName(); + } else { + return propertyType.getQualifiedSourceName(); + } + } + + public JClassType getBeanType() { + return beanType; + } + + public abstract void writeSetterBody(TreeLogger logger, SourceWriter w, + String beanVariable, String valueVariable); + + public abstract void writeGetterBody(TreeLogger logger, SourceWriter w, + String beanVariable); + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (obj instanceof Property) { + Property other = (Property) obj; + return other.getClass() == getClass() + && other.getBeanType().equals(getBeanType()) + && other.getName().equals(getName()); + } else { + return false; + } + } + + @Override + public int hashCode() { + return getClass().hashCode() * 31 ^ 2 + getBeanType().hashCode() * 31 + + getName().hashCode(); + } + + public abstract T getAnnotation( + Class annotationClass); + +} diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ServerRpcVisitor.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ServerRpcVisitor.java new file mode 100644 index 0000000000..cbcfc3075b --- /dev/null +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ServerRpcVisitor.java @@ -0,0 +1,48 @@ +/* + * Copyright 2011 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.metadata; + +import java.util.Set; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.typeinfo.JClassType; +import com.google.gwt.core.ext.typeinfo.JMethod; +import com.google.gwt.core.ext.typeinfo.JType; + +public class ServerRpcVisitor extends TypeVisitor { + @Override + public void visitServerRpc(TreeLogger logger, JClassType type, + ConnectorBundle bundle) { + bundle.setNeedsProxySupport(type); + + Set superTypes = type + .getFlattenedSupertypeHierarchy(); + for (JClassType subType : superTypes) { + if (subType.isInterface() != null) { + JMethod[] methods = subType.getMethods(); + for (JMethod method : methods) { + bundle.setNeedsDelayedInfo(type, method); + + JType[] parameterTypes = method.getParameterTypes(); + for (JType paramType : parameterTypes) { + bundle.setNeedsSerialize(paramType); + } + } + } + } + } +} diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/StateInitVisitor.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/StateInitVisitor.java new file mode 100644 index 0000000000..17ea62b249 --- /dev/null +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/StateInitVisitor.java @@ -0,0 +1,25 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.server.widgetsetutils.metadata; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.typeinfo.JClassType; +import com.google.gwt.core.ext.typeinfo.JMethod; +import com.google.gwt.core.ext.typeinfo.JType; + +public class StateInitVisitor extends TypeVisitor { + @Override + public void visitConnector(TreeLogger logger, JClassType type, + ConnectorBundle bundle) { + JMethod getState = findInheritedMethod(type, "getState"); + bundle.setNeedsReturnType(type, getState); + + bundle.setNeedsSerialize(getState.getReturnType()); + + JType stateType = getState.getReturnType(); + bundle.setNeedsGwtConstructor(stateType.isClass()); + } + +} diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/TypeVisitor.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/TypeVisitor.java new file mode 100644 index 0000000000..7191093755 --- /dev/null +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/TypeVisitor.java @@ -0,0 +1,58 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.server.widgetsetutils.metadata; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.core.ext.typeinfo.JClassType; +import com.google.gwt.core.ext.typeinfo.JMethod; +import com.google.gwt.core.ext.typeinfo.JType; +import com.google.gwt.core.ext.typeinfo.NotFoundException; +import com.google.gwt.core.ext.typeinfo.TypeOracle; + +public abstract class TypeVisitor { + public void init(TypeOracle oracle) throws NotFoundException { + // Default does nothing + } + + public void visitConnector(TreeLogger logger, JClassType type, + ConnectorBundle bundle) throws UnableToCompleteException { + // Default does nothing + } + + public void visitClientRpc(TreeLogger logger, JClassType type, + ConnectorBundle bundle) { + // Default does nothing + } + + public void visitServerRpc(TreeLogger logger, JClassType type, + ConnectorBundle bundle) { + // Default does nothing + } + + protected JMethod findInheritedMethod(JClassType type, String methodName, + JType... params) { + + JClassType currentType = type; + while (currentType != null) { + JMethod method = currentType.findMethod(methodName, params); + if (method != null) { + return method; + } + currentType = currentType.getSuperclass(); + } + + JClassType[] interfaces = type.getImplementedInterfaces(); + for (JClassType iface : interfaces) { + JMethod method = iface.findMethod(methodName, params); + if (method != null) { + return method; + } + } + + return null; + } + +} diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/WidgetInitVisitor.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/WidgetInitVisitor.java new file mode 100644 index 0000000000..fbbabe084d --- /dev/null +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/WidgetInitVisitor.java @@ -0,0 +1,73 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.server.widgetsetutils.metadata; + +import java.util.Collection; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.TreeLogger.Type; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.core.ext.typeinfo.JClassType; +import com.google.gwt.core.ext.typeinfo.JMethod; +import com.vaadin.client.ui.AbstractComponentConnector; +import com.vaadin.shared.annotations.DelegateToWidget; + +public class WidgetInitVisitor extends TypeVisitor { + + @Override + public void visitConnector(TreeLogger logger, JClassType type, + ConnectorBundle bundle) throws UnableToCompleteException { + if (ConnectorBundle.isConnectedComponentConnector(type)) { + JClassType createWidgetClass = findInheritedMethod(type, + "createWidget").getEnclosingType(); + boolean createWidgetOverridden = !createWidgetClass + .getQualifiedSourceName() + .equals(AbstractComponentConnector.class.getCanonicalName()); + if (createWidgetOverridden) { + // Don't generate if createWidget is already overridden + return; + } + + JMethod getWidget = findInheritedMethod(type, "getWidget"); + bundle.setNeedsReturnType(type, getWidget); + + JClassType widgetType = getWidget.getReturnType().isClass(); + bundle.setNeedsGwtConstructor(widgetType); + + JMethod getState = findInheritedMethod(type, "getState"); + JClassType stateType = getState.getReturnType().isClass(); + + Collection properties = bundle.getProperties(stateType); + for (Property property : properties) { + DelegateToWidget delegateToWidget = property + .getAnnotation(DelegateToWidget.class); + if (delegateToWidget != null) { + bundle.setNeedsDelegateToWidget(property); + String methodName = DelegateToWidget.Helper + .getDelegateTarget(property.getName(), + delegateToWidget.value()); + JMethod delegatedSetter = findInheritedMethod(widgetType, + methodName, property.getPropertyType()); + if (delegatedSetter == null) { + logger.log( + Type.ERROR, + widgetType.getName() + + "." + + methodName + + "(" + + property.getPropertyType() + .getSimpleSourceName() + + ") required by @DelegateToWidget for " + + stateType.getName() + "." + + property.getName() + + " can not be found."); + throw new UnableToCompleteException(); + } + bundle.setNeedsInvoker(widgetType, delegatedSetter); + } + } + } + } +} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/AcceptCriteriaFactoryGenerator.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/AcceptCriteriaFactoryGenerator.java deleted file mode 100644 index 2721f5dcf9..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/AcceptCriteriaFactoryGenerator.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2011 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.terminal.gwt.widgetsetutils; - -import java.io.PrintWriter; -import java.util.Date; - -import com.google.gwt.core.ext.Generator; -import com.google.gwt.core.ext.GeneratorContext; -import com.google.gwt.core.ext.TreeLogger; -import com.google.gwt.core.ext.TreeLogger.Type; -import com.google.gwt.core.ext.UnableToCompleteException; -import com.google.gwt.core.ext.typeinfo.JClassType; -import com.google.gwt.core.ext.typeinfo.TypeOracle; -import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; -import com.google.gwt.user.rebind.SourceWriter; -import com.vaadin.client.ui.dd.VAcceptCriterion; -import com.vaadin.client.ui.dd.VAcceptCriterionFactory; -import com.vaadin.shared.ui.dd.AcceptCriterion; - -/** - * GWT generator to build {@link VAcceptCriterionFactory} implementation - * dynamically based on {@link AcceptCriterion} annotations available in - * classpath. - * - */ -public class AcceptCriteriaFactoryGenerator extends Generator { - - private String packageName; - private String className; - - @Override - public String generate(TreeLogger logger, GeneratorContext context, - String typeName) throws UnableToCompleteException { - - try { - TypeOracle typeOracle = context.getTypeOracle(); - - // get classType and save instance variables - JClassType classType = typeOracle.getType(typeName); - packageName = classType.getPackage().getName(); - className = classType.getSimpleSourceName() + "Impl"; - // Generate class source code - generateClass(logger, context); - } catch (Exception e) { - logger.log(TreeLogger.ERROR, - "Accept criterion factory creation failed", e); - } - // return the fully qualifed name of the class generated - return packageName + "." + className; - } - - /** - * Generate source code for WidgetMapImpl - * - * @param logger - * Logger object - * @param context - * Generator context - */ - private void generateClass(TreeLogger logger, GeneratorContext context) { - // get print writer that receives the source code - PrintWriter printWriter = null; - printWriter = context.tryCreate(logger, packageName, className); - // print writer if null, source code has ALREADY been generated, - // return (WidgetMap is equal to all permutations atm) - if (printWriter == null) { - return; - } - logger.log(Type.INFO, "Detecting available criteria ..."); - Date date = new Date(); - - // init composer, set class properties, create source writer - ClassSourceFileComposerFactory composer = null; - composer = new ClassSourceFileComposerFactory(packageName, className); - composer.addImport("com.google.gwt.core.client.GWT"); - composer.setSuperclass("com.vaadin.client.ui.dd.VAcceptCriterionFactory"); - SourceWriter sourceWriter = composer.createSourceWriter(context, - printWriter); - - // generator constructor source code - generateInstantiatorMethod(sourceWriter, context, logger); - // close generated class - sourceWriter.outdent(); - sourceWriter.println("}"); - // commit generated class - context.commit(logger, printWriter); - logger.log(Type.INFO, - "Done. (" + (new Date().getTime() - date.getTime()) / 1000 - + "seconds)"); - - } - - private void generateInstantiatorMethod(SourceWriter sourceWriter, - GeneratorContext context, TreeLogger logger) { - - sourceWriter.println("public VAcceptCriterion get(String name) {"); - sourceWriter.indent(); - - sourceWriter.println("name = name.intern();"); - - JClassType criteriaType = context.getTypeOracle().findType( - VAcceptCriterion.class.getName()); - for (JClassType clientClass : criteriaType.getSubtypes()) { - AcceptCriterion annotation = clientClass - .getAnnotation(AcceptCriterion.class); - if (annotation != null) { - String clientClassName = clientClass.getQualifiedSourceName(); - Class serverClass = clientClass.getAnnotation( - AcceptCriterion.class).value(); - String serverClassName = serverClass.getCanonicalName(); - logger.log(Type.INFO, "creating mapping for " + serverClassName); - sourceWriter.print("if (\""); - sourceWriter.print(serverClassName); - sourceWriter.print("\" == name) return GWT.create("); - sourceWriter.print(clientClassName); - sourceWriter.println(".class );"); - sourceWriter.print("else "); - } - } - - sourceWriter.println("return null;"); - sourceWriter.outdent(); - sourceWriter.println("}"); - } -} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/ClassPathExplorer.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/ClassPathExplorer.java deleted file mode 100644 index f57a58a557..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/ClassPathExplorer.java +++ /dev/null @@ -1,474 +0,0 @@ -/* - * Copyright 2011 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.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.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.jar.Attributes; -import java.util.jar.JarFile; -import java.util.jar.Manifest; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * 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. - *

- * Used by WidgetMapGenerator and ide tools to implement some monkey coding for - * you. - *

- * 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 { - - private static final String VAADIN_ADDON_VERSION_ATTRIBUTE = "Vaadin-Package-Version"; - - /** - * File filter that only accepts directories. - */ - private final static FileFilter DIRECTORIES_ONLY = new FileFilter() { - @Override - public boolean accept(File f) { - if (f.exists() && f.isDirectory()) { - return true; - } else { - return false; - } - } - }; - - /** - * Raw class path entries as given in the java class path string. Only - * entries that could include widgets/widgetsets are listed (primarily - * directories, Vaadin JARs and add-on JARs). - */ - private static List rawClasspathEntries = getRawClasspathEntries(); - - /** - * Map from identifiers (either a package name preceded by the path and a - * slash, or a URL for a JAR file) to the corresponding URLs. This is - * constructed from the class path. - */ - private static Map classpathLocations = getClasspathLocations(rawClasspathEntries); - - /** - * No instantiation from outside, callable methods are static. - */ - private ClassPathExplorer() { - } - - /** - * Finds the names and locations of widgetsets available on the class path. - * - * @return map from widgetset classname to widgetset location URL - */ - public static Map getAvailableWidgetSets() { - long start = System.currentTimeMillis(); - Map widgetsets = new HashMap(); - Set keySet = classpathLocations.keySet(); - for (String location : keySet) { - searchForWidgetSets(location, widgetsets); - } - long end = System.currentTimeMillis(); - - StringBuilder sb = new StringBuilder(); - sb.append("Widgetsets found from classpath:\n"); - for (String ws : widgetsets.keySet()) { - sb.append("\t"); - sb.append(ws); - sb.append(" in "); - sb.append(widgetsets.get(ws)); - sb.append("\n"); - } - final Logger logger = getLogger(); - logger.info(sb.toString()); - logger.info("Search took " + (end - start) + "ms"); - return widgetsets; - } - - /** - * Finds all GWT modules / Vaadin widgetsets in a valid location. - * - * If the location is a directory, all GWT modules (files with the - * ".gwt.xml" extension) are added to widgetsets. - * - * If the location is a JAR file, the comma-separated values of the - * "Vaadin-Widgetsets" attribute in its manifest are added to widgetsets. - * - * @param locationString - * an entry in {@link #classpathLocations} - * @param widgetsets - * a map from widgetset name (including package, with dots as - * separators) to a URL (see {@link #classpathLocations}) - new - * entries are added to this map - */ - private static void searchForWidgetSets(String locationString, - Map widgetsets) { - - URL location = classpathLocations.get(locationString); - 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")) { - continue; - } - - // remove the .gwt.xml extension - String classname = files[i].substring(0, files[i].length() - 8); - String packageName = locationString.substring(locationString - .lastIndexOf("/") + 1); - classname = packageName + "." + classname; - - if (!WidgetSetBuilder.isWidgetset(classname)) { - // Only return widgetsets and not GWT modules to avoid - // comparing modules and widgetsets - continue; - } - - if (!widgetsets.containsKey(classname)) { - String packagePath = packageName.replaceAll("\\.", "/"); - String basePath = location.getFile().replaceAll( - "/" + packagePath + "$", ""); - try { - URL url = new URL(location.getProtocol(), - location.getHost(), location.getPort(), - basePath); - widgetsets.put(classname, url); - } catch (MalformedURLException e) { - // should never happen as based on an existing URL, - // only changing end of file name/path part - getLogger().log(Level.SEVERE, - "Error locating the widgetset " + classname, e); - } - } - } - } 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(); - if (manifest == null) { - // No manifest so this is not a Vaadin Add-on - return; - } - 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(); - if (!widgetsetname.equals("")) { - widgetsets.put(widgetsetname, location); - } - } - } - } - } catch (IOException e) { - getLogger().log(Level.WARNING, "Error parsing jar file", e); - } - - } - } - - /** - * Splits the current class path into entries, and filters them accepting - * directories, Vaadin add-on JARs with widgetsets and Vaadin JARs. - * - * Some other non-JAR entries may also be included in the result. - * - * @return filtered list of class path entries - */ - private final static List getRawClasspathEntries() { - // try to keep the order of the classpath - List locations = new ArrayList(); - - String pathSep = System.getProperty("path.separator"); - String classpath = System.getProperty("java.class.path"); - - if (classpath.startsWith("\"")) { - classpath = classpath.substring(1); - } - if (classpath.endsWith("\"")) { - classpath = classpath.substring(0, classpath.length() - 1); - } - - getLogger().fine("Classpath: " + classpath); - - String[] split = classpath.split(pathSep); - for (int i = 0; i < split.length; i++) { - String classpathEntry = split[i]; - if (acceptClassPathEntry(classpathEntry)) { - locations.add(classpathEntry); - } - } - - return locations; - } - - /** - * Determine every URL location defined by the current classpath, and it's - * associated package name. - * - * See {@link #classpathLocations} for information on output format. - * - * @param rawClasspathEntries - * raw class path entries as split from the Java class path - * string - * @return map of classpath locations, see {@link #classpathLocations} - */ - private final static Map getClasspathLocations( - List rawClasspathEntries) { - long start = System.currentTimeMillis(); - // try to keep the order of the classpath - Map locations = new LinkedHashMap(); - for (String classpathEntry : rawClasspathEntries) { - File file = new File(classpathEntry); - include(null, file, locations); - } - long end = System.currentTimeMillis(); - Logger logger = getLogger(); - if (logger.isLoggable(Level.FINE)) { - logger.fine("getClassPathLocations took " + (end - start) + "ms"); - } - return locations; - } - - /** - * Checks a class path entry to see whether it can contain widgets and - * widgetsets. - * - * All directories are automatically accepted. JARs are accepted if they - * have the "Vaadin-Widgetsets" attribute in their manifest or the JAR file - * name contains "vaadin-" or ".vaadin.". - * - * Also other non-JAR entries may be accepted, the caller should be prepared - * to handle them. - * - * @param classpathEntry - * class path entry string as given in the Java class path - * @return true if the entry should be considered when looking for widgets - * or widgetsets - */ - private static boolean acceptClassPathEntry(String classpathEntry) { - if (!classpathEntry.endsWith(".jar")) { - // accept all non jars (practically directories) - return true; - } else { - // accepts jars that comply with vaadin-component packaging - // convention (.vaadin. or vaadin- as distribution packages), - if (classpathEntry.contains("vaadin-") - || 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(); - getLogger().fine(url.toString()); - JarFile jarFile = conn.getJarFile(); - Manifest manifest = jarFile.getManifest(); - if (manifest != null) { - Attributes mainAttributes = manifest - .getMainAttributes(); - if (mainAttributes.getValue("Vaadin-Widgetsets") != null) { - return true; - } - } - } catch (MalformedURLException e) { - getLogger().log(Level.FINEST, "Failed to inspect JAR file", - e); - } catch (IOException e) { - getLogger().log(Level.FINEST, "Failed to inspect JAR file", - e); - } - - return false; - } - } - } - - /** - * Recursively add subdirectories and jar files to locations - see - * {@link #classpathLocations}. - * - * @param name - * @param file - * @param locations - */ - private final static void include(String name, File file, - Map locations) { - if (!file.exists()) { - return; - } - if (!file.isDirectory()) { - // could be a JAR file - includeJar(file, locations); - return; - } - - if (file.isHidden() || file.getPath().contains(File.separator + ".")) { - return; - } - - if (name == null) { - name = ""; - } else { - name += "."; - } - - // add all directories recursively - File[] dirs = file.listFiles(DIRECTORIES_ONLY); - for (int i = 0; i < dirs.length; i++) { - try { - // add the present directory - if (!dirs[i].isHidden() - && !dirs[i].getPath().contains(File.separator + ".")) { - String key = dirs[i].getCanonicalPath() + "/" + name - + dirs[i].getName(); - locations.put(key, - new URL("file://" + dirs[i].getCanonicalPath())); - } - } catch (Exception ioe) { - return; - } - include(name + dirs[i].getName(), dirs[i], locations); - } - } - - /** - * Add a jar file to locations - see {@link #classpathLocations}. - * - * @param name - * @param locations - */ - private static void includeJar(File file, Map locations) { - try { - URL url = new URL("file:" + file.getCanonicalPath()); - url = new URL("jar:" + url.toExternalForm() + "!/"); - JarURLConnection conn = (JarURLConnection) url.openConnection(); - JarFile jarFile = conn.getJarFile(); - if (jarFile != null) { - // the key does not matter here as long as it is unique - locations.put(url.toString(), url); - } - } catch (Exception e) { - // e.printStackTrace(); - return; - } - - } - - /** - * Find and return the default source directory where to create new - * widgetsets. - * - * Return the first directory (not a JAR file etc.) on the classpath by - * default. - * - * TODO this could be done better... - * - * @return URL - */ - public static URL getDefaultSourceDirectory() { - - final Logger logger = getLogger(); - - if (logger.isLoggable(Level.FINE)) { - logger.fine("classpathLocations values:"); - ArrayList locations = new ArrayList( - classpathLocations.keySet()); - for (String location : locations) { - logger.fine(String.valueOf(classpathLocations.get(location))); - } - } - - Iterator it = rawClasspathEntries.iterator(); - while (it.hasNext()) { - String entry = it.next(); - - File directory = new File(entry); - if (directory.exists() && !directory.isHidden() - && directory.isDirectory()) { - try { - return new URL("file://" + directory.getCanonicalPath()); - } catch (MalformedURLException e) { - logger.log(Level.FINEST, "Ignoring exception", e); - // ignore: continue to the next classpath entry - } catch (IOException e) { - logger.log(Level.FINEST, "Ignoring exception", e); - // ignore: continue to the next classpath entry - } - } - } - return null; - } - - /** - * Test method for helper tool - */ - public static void main(String[] args) { - getLogger().info("Searching available widgetsets..."); - - Map availableWidgetSets = ClassPathExplorer - .getAvailableWidgetSets(); - for (String string : availableWidgetSets.keySet()) { - - getLogger().info(string + " in " + availableWidgetSets.get(string)); - } - } - - private static final Logger getLogger() { - return Logger.getLogger(ClassPathExplorer.class.getName()); - } - -} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/ConnectorBundleLoaderFactory.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/ConnectorBundleLoaderFactory.java deleted file mode 100644 index 2e94ba9b64..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/ConnectorBundleLoaderFactory.java +++ /dev/null @@ -1,684 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.terminal.gwt.widgetsetutils; - -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.core.ext.Generator; -import com.google.gwt.core.ext.GeneratorContext; -import com.google.gwt.core.ext.TreeLogger; -import com.google.gwt.core.ext.TreeLogger.Type; -import com.google.gwt.core.ext.UnableToCompleteException; -import com.google.gwt.core.ext.typeinfo.JClassType; -import com.google.gwt.core.ext.typeinfo.JMethod; -import com.google.gwt.core.ext.typeinfo.JParameterizedType; -import com.google.gwt.core.ext.typeinfo.JType; -import com.google.gwt.core.ext.typeinfo.NotFoundException; -import com.google.gwt.core.ext.typeinfo.TypeOracle; -import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; -import com.google.gwt.user.rebind.SourceWriter; -import com.vaadin.client.ServerConnector; -import com.vaadin.client.metadata.ConnectorBundleLoader; -import com.vaadin.client.metadata.InvokationHandler; -import com.vaadin.client.metadata.ProxyHandler; -import com.vaadin.client.metadata.TypeData; -import com.vaadin.client.metadata.TypeDataBundle; -import com.vaadin.client.metadata.TypeDataStore; -import com.vaadin.client.ui.UnknownComponentConnector; -import com.vaadin.shared.annotations.Delayed; -import com.vaadin.shared.annotations.DelegateToWidget; -import com.vaadin.shared.communication.ClientRpc; -import com.vaadin.shared.communication.ServerRpc; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.Connect.LoadStyle; -import com.vaadin.terminal.gwt.widgetsetutils.metadata.ClientRpcVisitor; -import com.vaadin.terminal.gwt.widgetsetutils.metadata.ConnectorBundle; -import com.vaadin.terminal.gwt.widgetsetutils.metadata.ConnectorInitVisitor; -import com.vaadin.terminal.gwt.widgetsetutils.metadata.GeneratedSerializer; -import com.vaadin.terminal.gwt.widgetsetutils.metadata.Property; -import com.vaadin.terminal.gwt.widgetsetutils.metadata.ServerRpcVisitor; -import com.vaadin.terminal.gwt.widgetsetutils.metadata.StateInitVisitor; -import com.vaadin.terminal.gwt.widgetsetutils.metadata.TypeVisitor; -import com.vaadin.terminal.gwt.widgetsetutils.metadata.WidgetInitVisitor; - -public class ConnectorBundleLoaderFactory extends Generator { - - @Override - public String generate(TreeLogger logger, GeneratorContext context, - String typeName) throws UnableToCompleteException { - TypeOracle typeOracle = context.getTypeOracle(); - - try { - JClassType classType = typeOracle.getType(typeName); - String packageName = classType.getPackage().getName(); - String className = classType.getSimpleSourceName() + "Impl"; - - generateClass(logger, context, packageName, className, typeName); - - return packageName + "." + className; - } catch (UnableToCompleteException e) { - // Just rethrow - throw e; - } catch (Exception e) { - logger.log(Type.ERROR, getClass() + " failed", e); - throw new UnableToCompleteException(); - } - - } - - private void generateClass(TreeLogger logger, GeneratorContext context, - String packageName, String className, String requestedType) - throws Exception { - PrintWriter printWriter = context.tryCreate(logger, packageName, - className); - if (printWriter == null) { - return; - } - - List bundles = buildBundles(logger, - context.getTypeOracle()); - - ClassSourceFileComposerFactory composer = new ClassSourceFileComposerFactory( - packageName, className); - composer.setSuperclass(requestedType); - - SourceWriter w = composer.createSourceWriter(context, printWriter); - - w.println("public void init() {"); - w.indent(); - - for (ConnectorBundle bundle : bundles) { - String name = bundle.getName(); - boolean isEager = name - .equals(ConnectorBundleLoader.EAGER_BUNDLE_NAME); - - w.print("addAsyncBlockLoader(new AsyncBundleLoader(\""); - w.print(escape(name)); - w.print("\", "); - - w.print("new String[] {"); - for (Entry> entry : bundle.getIdentifiers() - .entrySet()) { - Set identifiers = entry.getValue(); - for (String id : identifiers) { - w.print("\""); - w.print(escape(id)); - w.print("\","); - } - } - w.println("}) {"); - w.indent(); - - w.print("protected void load(final "); - w.print(TypeDataStore.class.getName()); - w.println(" store) {"); - w.indent(); - - if (!isEager) { - w.print(GWT.class.getName()); - w.print(".runAsync("); - } - - w.print("new "); - w.print(TypeDataBundle.class.getName()); - w.println("(getName()) {"); - w.indent(); - - w.println("public void load() {"); - w.indent(); - - printBundleData(logger, w, bundle); - - // Close load method - w.outdent(); - w.println("}"); - - // Close new TypeDataBundle() {} - w.outdent(); - w.print("}"); - - if (isEager) { - w.println(".onSuccess();"); - } else { - w.println(");"); - } - - // Close load method - w.outdent(); - w.println("}"); - - // Close add(new ... - w.outdent(); - w.println("});"); - } - - w.outdent(); - w.println("}"); - - w.commit(logger); - } - - private void printBundleData(TreeLogger logger, SourceWriter w, - ConnectorBundle bundle) throws UnableToCompleteException { - writeIdentifiers(w, bundle); - writeGwtConstructors(w, bundle); - writeReturnTypes(w, bundle); - writeInvokers(w, bundle); - writeParamTypes(w, bundle); - writeProxys(w, bundle); - wirteDelayedInfo(w, bundle); - writeProperites(logger, w, bundle); - writePropertyTypes(w, bundle); - writeSetters(logger, w, bundle); - writeGetters(logger, w, bundle); - writeSerializers(logger, w, bundle); - writeDelegateToWidget(logger, w, bundle); - } - - private void writeDelegateToWidget(TreeLogger logger, SourceWriter w, - ConnectorBundle bundle) { - Set needsDelegateToWidget = bundle.getNeedsDelegateToWidget(); - for (Property property : needsDelegateToWidget) { - w.println("store.setDelegateToWidget(%s, \"%s\", \"%s\");", - getClassLiteralString(property.getBeanType()), - property.getName(), - property.getAnnotation(DelegateToWidget.class).value()); - } - } - - private void writeSerializers(TreeLogger logger, SourceWriter w, - ConnectorBundle bundle) throws UnableToCompleteException { - Map serializers = bundle.getSerializers(); - for (Entry entry : serializers.entrySet()) { - JType type = entry.getKey(); - GeneratedSerializer serializer = entry.getValue(); - - w.print("store.setSerializerFactory("); - writeClassLiteral(w, type); - w.print(", "); - w.println("new Invoker() {"); - w.indent(); - - w.println("public Object invoke(Object target, Object[] params) {"); - w.indent(); - - serializer.writeSerializerInstantiator(logger, w); - - w.outdent(); - w.println("}"); - - w.outdent(); - w.print("}"); - w.println(");"); - } - } - - private void writeGetters(TreeLogger logger, SourceWriter w, - ConnectorBundle bundle) { - Set properties = bundle.getNeedsSetter(); - for (Property property : properties) { - w.print("store.setGetter("); - writeClassLiteral(w, property.getBeanType()); - w.print(", \""); - w.print(escape(property.getName())); - w.println("\", new Invoker() {"); - w.indent(); - - w.println("public Object invoke(Object bean, Object[] params) {"); - w.indent(); - - property.writeGetterBody(logger, w, "bean"); - w.println(); - - w.outdent(); - w.println("}"); - - w.outdent(); - w.println("});"); - } - } - - private void writeSetters(TreeLogger logger, SourceWriter w, - ConnectorBundle bundle) { - Set properties = bundle.getNeedsSetter(); - for (Property property : properties) { - w.print("store.setSetter("); - writeClassLiteral(w, property.getBeanType()); - w.print(", \""); - w.print(escape(property.getName())); - w.println("\", new Invoker() {"); - w.indent(); - - w.println("public Object invoke(Object bean, Object[] params) {"); - w.indent(); - - property.writeSetterBody(logger, w, "bean", "params[0]"); - - w.println("return null;"); - - w.outdent(); - w.println("}"); - - w.outdent(); - w.println("});"); - } - } - - private void writePropertyTypes(SourceWriter w, ConnectorBundle bundle) { - Set properties = bundle.getNeedsType(); - for (Property property : properties) { - w.print("store.setPropertyType("); - writeClassLiteral(w, property.getBeanType()); - w.print(", \""); - w.print(escape(property.getName())); - w.print("\", "); - writeTypeCreator(w, property.getPropertyType()); - w.println(");"); - } - } - - private void writeProperites(TreeLogger logger, SourceWriter w, - ConnectorBundle bundle) throws UnableToCompleteException { - Set needsPropertyListing = bundle.getNeedsPropertyListing(); - for (JClassType type : needsPropertyListing) { - w.print("store.setProperties("); - writeClassLiteral(w, type); - w.print(", new String[] {"); - - Set usedPropertyNames = new HashSet(); - Collection properties = bundle.getProperties(type); - for (Property property : properties) { - String name = property.getName(); - if (!usedPropertyNames.add(name)) { - logger.log( - Type.ERROR, - type.getQualifiedSourceName() - + " has multiple properties with the name " - + name - + ". This can happen if there are multiple setters with identical names exect casing."); - throw new UnableToCompleteException(); - } - - w.print("\""); - w.print(name); - w.print("\", "); - } - - w.println("});"); - } - } - - private void wirteDelayedInfo(SourceWriter w, ConnectorBundle bundle) { - Map> needsDelayedInfo = bundle - .getNeedsDelayedInfo(); - Set>> entrySet = needsDelayedInfo - .entrySet(); - for (Entry> entry : entrySet) { - JClassType type = entry.getKey(); - Set methods = entry.getValue(); - for (JMethod method : methods) { - Delayed annotation = method.getAnnotation(Delayed.class); - if (annotation != null) { - w.print("store.setDelayed("); - writeClassLiteral(w, type); - w.print(", \""); - w.print(escape(method.getName())); - w.println("\");"); - - if (annotation.lastonly()) { - w.print("store.setLastonly("); - writeClassLiteral(w, type); - w.print(", \""); - w.print(escape(method.getName())); - w.println("\");"); - } - } - } - } - } - - private void writeProxys(SourceWriter w, ConnectorBundle bundle) { - Set needsProxySupport = bundle.getNeedsProxySupport(); - for (JClassType type : needsProxySupport) { - w.print("store.setProxyHandler("); - writeClassLiteral(w, type); - w.print(", new "); - w.print(ProxyHandler.class.getCanonicalName()); - w.println("() {"); - w.indent(); - - w.println("public Object createProxy(final " - + InvokationHandler.class.getName() + " handler) {"); - w.indent(); - - w.print("return new "); - w.print(type.getQualifiedSourceName()); - w.println("() {"); - w.indent(); - - JMethod[] methods = type.getOverridableMethods(); - for (JMethod method : methods) { - if (method.isAbstract()) { - w.print("public "); - w.print(method.getReturnType().getQualifiedSourceName()); - w.print(" "); - w.print(method.getName()); - w.print("("); - - JType[] types = method.getParameterTypes(); - for (int i = 0; i < types.length; i++) { - if (i != 0) { - w.print(", "); - } - w.print(types[i].getQualifiedSourceName()); - w.print(" p"); - w.print(Integer.toString(i)); - } - - w.println(") {"); - w.indent(); - - if (!method.getReturnType().getQualifiedSourceName() - .equals("void")) { - w.print("return "); - } - - w.print("handler.invoke(this, "); - w.print(TypeData.class.getCanonicalName()); - w.print(".getType("); - writeClassLiteral(w, type); - w.print(").getMethod(\""); - w.print(escape(method.getName())); - w.print("\"), new Object [] {"); - for (int i = 0; i < types.length; i++) { - w.print("p" + i + ", "); - } - w.println("});"); - - w.outdent(); - w.println("}"); - } - } - - w.outdent(); - w.println("};"); - - w.outdent(); - w.println("}"); - - w.outdent(); - w.println("});"); - - } - } - - private void writeParamTypes(SourceWriter w, ConnectorBundle bundle) { - Map> needsParamTypes = bundle - .getNeedsParamTypes(); - for (Entry> entry : needsParamTypes.entrySet()) { - JClassType type = entry.getKey(); - - Set methods = entry.getValue(); - for (JMethod method : methods) { - w.print("store.setParamTypes("); - writeClassLiteral(w, type); - w.print(", \""); - w.print(escape(method.getName())); - w.print("\", new Type[] {"); - - for (JType parameter : method.getParameterTypes()) { - ConnectorBundleLoaderFactory.writeTypeCreator(w, parameter); - w.print(", "); - } - - w.println("});"); - - } - } - } - - private void writeInvokers(SourceWriter w, ConnectorBundle bundle) { - Map> needsInvoker = bundle.getNeedsInvoker(); - for (Entry> entry : needsInvoker.entrySet()) { - JClassType type = entry.getKey(); - - Set methods = entry.getValue(); - for (JMethod method : methods) { - w.print("store.setInvoker("); - writeClassLiteral(w, type); - w.print(", \""); - w.print(escape(method.getName())); - w.println("\", new Invoker() {"); - w.indent(); - - w.println("public Object invoke(Object target, Object[] params) {"); - w.indent(); - - JType returnType = method.getReturnType(); - boolean hasReturnType = !"void".equals(returnType - .getQualifiedSourceName()); - if (hasReturnType) { - w.print("return "); - } - - JType[] parameterTypes = method.getParameterTypes(); - - w.print("((" + type.getQualifiedSourceName() + ") target)." - + method.getName() + "("); - for (int i = 0; i < parameterTypes.length; i++) { - JType parameterType = parameterTypes[i]; - if (i != 0) { - w.print(", "); - } - String parameterTypeName = getBoxedTypeName(parameterType); - w.print("(" + parameterTypeName + ") params[" + i + "]"); - } - w.println(");"); - - if (!hasReturnType) { - w.println("return null;"); - } - - w.outdent(); - w.println("}"); - - w.outdent(); - w.println("});"); - - } - } - } - - private void writeReturnTypes(SourceWriter w, ConnectorBundle bundle) { - Map> methodReturnTypes = bundle - .getMethodReturnTypes(); - for (Entry> entry : methodReturnTypes - .entrySet()) { - JClassType type = entry.getKey(); - - Set methods = entry.getValue(); - for (JMethod method : methods) { - // setReturnType(Class type, String methodName, Type - // returnType) - w.print("store.setReturnType("); - writeClassLiteral(w, type); - w.print(", \""); - w.print(escape(method.getName())); - w.print("\", "); - writeTypeCreator(w, method.getReturnType()); - w.println(");"); - } - } - } - - private void writeGwtConstructors(SourceWriter w, ConnectorBundle bundle) { - Set constructors = bundle.getGwtConstructors(); - for (JClassType type : constructors) { - w.print("store.setConstructor("); - writeClassLiteral(w, type); - w.println(", new Invoker() {"); - w.indent(); - - w.println("public Object invoke(Object target, Object[] params) {"); - w.indent(); - - w.print("return "); - w.print(GWT.class.getName()); - w.print(".create("); - writeClassLiteral(w, type); - w.println(");"); - - w.outdent(); - w.println("}"); - - w.outdent(); - w.println("});"); - } - } - - public static void writeClassLiteral(SourceWriter w, JType type) { - w.print(getClassLiteralString(type)); - } - - public static String getClassLiteralString(JType type) { - return type.getQualifiedSourceName() + ".class"; - } - - private void writeIdentifiers(SourceWriter w, ConnectorBundle bundle) { - Map> identifiers = bundle.getIdentifiers(); - for (Entry> entry : identifiers.entrySet()) { - Set ids = entry.getValue(); - JClassType type = entry.getKey(); - for (String id : ids) { - w.print("store.setClass(\""); - w.print(escape(id)); - w.print("\", "); - writeClassLiteral(w, type); - w.println(");"); - } - } - } - - private List buildBundles(TreeLogger logger, - TypeOracle typeOracle) throws NotFoundException, - UnableToCompleteException { - - Map> connectorsByLoadStyle = new HashMap>(); - for (LoadStyle loadStyle : LoadStyle.values()) { - connectorsByLoadStyle.put(loadStyle, new ArrayList()); - } - - JClassType connectorType = typeOracle.getType(ServerConnector.class - .getName()); - JClassType[] subtypes = connectorType.getSubtypes(); - for (JClassType connectorSubtype : subtypes) { - if (!connectorSubtype.isAnnotationPresent(Connect.class)) { - continue; - } - LoadStyle loadStyle = getLoadStyle(connectorSubtype); - if (loadStyle != null) { - connectorsByLoadStyle.get(loadStyle).add(connectorSubtype); - } - } - - List bundles = new ArrayList(); - - Collection visitors = getVisitors(typeOracle); - - ConnectorBundle eagerBundle = new ConnectorBundle( - ConnectorBundleLoader.EAGER_BUNDLE_NAME, visitors, typeOracle); - TreeLogger eagerLogger = logger.branch(Type.TRACE, - "Populating eager bundle"); - - // Eager connectors and all RPC interfaces are loaded by default - eagerBundle.processTypes(eagerLogger, - connectorsByLoadStyle.get(LoadStyle.EAGER)); - eagerBundle.processType(eagerLogger, typeOracle - .findType(UnknownComponentConnector.class.getCanonicalName())); - eagerBundle.processSubTypes(eagerLogger, - typeOracle.getType(ClientRpc.class.getName())); - eagerBundle.processSubTypes(eagerLogger, - typeOracle.getType(ServerRpc.class.getName())); - - bundles.add(eagerBundle); - - ConnectorBundle deferredBundle = new ConnectorBundle( - ConnectorBundleLoader.DEFERRED_BUNDLE_NAME, eagerBundle); - TreeLogger deferredLogger = logger.branch(Type.TRACE, - "Populating deferred bundle"); - deferredBundle.processTypes(deferredLogger, - connectorsByLoadStyle.get(LoadStyle.DEFERRED)); - - bundles.add(deferredBundle); - - Collection lazy = connectorsByLoadStyle.get(LoadStyle.LAZY); - for (JClassType type : lazy) { - ConnectorBundle bundle = new ConnectorBundle(type.getName(), - eagerBundle); - TreeLogger subLogger = logger.branch(Type.TRACE, "Populating " - + type.getName() + " bundle"); - bundle.processType(subLogger, type); - - bundles.add(bundle); - } - - return bundles; - } - - private Collection getVisitors(TypeOracle oracle) - throws NotFoundException { - List visitors = Arrays. asList( - new ConnectorInitVisitor(), new StateInitVisitor(), - new WidgetInitVisitor(), new ClientRpcVisitor(), - new ServerRpcVisitor()); - for (TypeVisitor typeVisitor : visitors) { - typeVisitor.init(oracle); - } - return visitors; - } - - protected LoadStyle getLoadStyle(JClassType connectorType) { - Connect annotation = connectorType.getAnnotation(Connect.class); - return annotation.loadStyle(); - } - - public static String getBoxedTypeName(JType type) { - if (type.isPrimitive() != null) { - // Used boxed types for primitives - return type.isPrimitive().getQualifiedBoxedSourceName(); - } else { - return type.getErasedType().getQualifiedSourceName(); - } - } - - public static void writeTypeCreator(SourceWriter sourceWriter, JType type) { - String typeName = ConnectorBundleLoaderFactory.getBoxedTypeName(type); - JParameterizedType parameterized = type.isParameterized(); - if (parameterized != null) { - sourceWriter.print("new Type(\"" + typeName + "\", "); - sourceWriter.print("new Type[] {"); - JClassType[] typeArgs = parameterized.getTypeArgs(); - for (JClassType jClassType : typeArgs) { - writeTypeCreator(sourceWriter, jClassType); - sourceWriter.print(", "); - } - sourceWriter.print("}"); - } else { - sourceWriter.print("new Type(" + typeName + ".class"); - } - sourceWriter.print(")"); - } - -} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/CustomWidgetMapGenerator.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/CustomWidgetMapGenerator.java deleted file mode 100644 index dbe3cd2efc..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/CustomWidgetMapGenerator.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2011 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.terminal.gwt.widgetsetutils; - -import java.util.Collection; -import java.util.HashSet; - -import com.vaadin.client.ComponentConnector; -import com.vaadin.client.ServerConnector; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.Connect.LoadStyle; - -/** - * An abstract helper class that can be used to easily build a widgetset with - * customized load styles for each components. In three abstract methods one can - * override the default values given in {@link Connect} annotations. - * - * @see WidgetMapGenerator - * - */ -public abstract class CustomWidgetMapGenerator extends WidgetMapGenerator { - - private Collection> eagerPaintables = new HashSet>(); - private Collection> lazyPaintables = new HashSet>(); - private Collection> deferredPaintables = new HashSet>(); - - @Override - protected LoadStyle getLoadStyle(Class connector) { - if (eagerPaintables == null) { - init(); - } - if (eagerPaintables.contains(connector)) { - return LoadStyle.EAGER; - } - if (lazyPaintables.contains(connector)) { - return LoadStyle.LAZY; - } - if (deferredPaintables.contains(connector)) { - return LoadStyle.DEFERRED; - } - return super.getLoadStyle(connector); - } - - private void init() { - Class[] eagerComponents = getEagerComponents(); - if (eagerComponents != null) { - for (Class class1 : eagerComponents) { - eagerPaintables.add(class1); - } - } - Class[] lazyComponents = getEagerComponents(); - if (lazyComponents != null) { - for (Class class1 : lazyComponents) { - lazyPaintables.add(class1); - } - } - Class[] deferredComponents = getEagerComponents(); - if (deferredComponents != null) { - for (Class class1 : deferredComponents) { - deferredPaintables.add(class1); - } - } - } - - /** - * @return an array of components whose load style should be overridden to - * {@link LoadStyle#EAGER} - */ - protected abstract Class[] getEagerComponents(); - - /** - * @return an array of components whose load style should be overridden to - * {@link LoadStyle#LAZY} - */ - protected abstract Class[] getLazyComponents(); - - /** - * @return an array of components whose load style should be overridden to - * {@link LoadStyle#DEFERRED} - */ - protected abstract Class[] getDeferredComponents(); - -} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/EagerWidgetMapGenerator.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/EagerWidgetMapGenerator.java deleted file mode 100644 index 1ce59c6953..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/EagerWidgetMapGenerator.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2011 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.terminal.gwt.widgetsetutils; - -import com.vaadin.client.ServerConnector; -import com.vaadin.shared.ui.Connect.LoadStyle; - -/** - * WidgetMap generator that builds a widgetset that packs all included widgets - * into a single JavaScript file loaded at application initialization. Initially - * loaded data will be relatively large, but minimal amount of server requests - * will be done. - *

- * This is the default generator in version 6.4 and produces similar type of - * widgetset as in previous versions of Vaadin. To activate "code splitting", - * use the {@link WidgetMapGenerator} instead, that loads most components - * deferred. - * - * @see WidgetMapGenerator - * - */ -public class EagerWidgetMapGenerator extends WidgetMapGenerator { - - @Override - protected LoadStyle getLoadStyle(Class connector) { - return LoadStyle.EAGER; - } -} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/LazyWidgetMapGenerator.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/LazyWidgetMapGenerator.java deleted file mode 100644 index 2ea276bfcb..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/LazyWidgetMapGenerator.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2011 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.terminal.gwt.widgetsetutils; - -import com.vaadin.client.ServerConnector; -import com.vaadin.shared.ui.Connect.LoadStyle; - -/** - * WidgetMap generator that builds a widgetset that optimizes the transferred - * data. Widgets are loaded only when used if the widgetset is built with this - * generator. - * - * @see WidgetMapGenerator - * - */ -public class LazyWidgetMapGenerator extends WidgetMapGenerator { - @Override - protected LoadStyle getLoadStyle(Class connector) { - return LoadStyle.LAZY; - } - -} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java deleted file mode 100644 index f7fc3cf45a..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java +++ /dev/null @@ -1,434 +0,0 @@ -/* - * Copyright 2011 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.terminal.gwt.widgetsetutils; - -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.Map; -import java.util.TreeSet; - -import com.google.gwt.core.ext.Generator; -import com.google.gwt.core.ext.GeneratorContext; -import com.google.gwt.core.ext.TreeLogger; -import com.google.gwt.core.ext.TreeLogger.Type; -import com.google.gwt.core.ext.UnableToCompleteException; -import com.google.gwt.core.ext.typeinfo.JClassType; -import com.google.gwt.core.ext.typeinfo.TypeOracle; -import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; -import com.google.gwt.user.rebind.SourceWriter; -import com.vaadin.client.ServerConnector; -import com.vaadin.client.ui.UnknownComponentConnector; -import com.vaadin.client.ui.UI.UIConnector; -import com.vaadin.server.ClientConnector; -import com.vaadin.shared.Connector; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.Connect.LoadStyle; - -/** - * WidgetMapGenerator's are GWT generator to build WidgetMapImpl dynamically - * based on {@link Connect} annotations available in workspace. By modifying the - * generator it is possible to do some fine tuning for the generated widgetset - * (aka client side engine). The components to be included in the client side - * engine can modified be overriding {@link #getUsedConnectors()}. - *

- * The generator also decides how the client side component implementations are - * loaded to the browser. The default generator is - * {@link EagerWidgetMapGenerator} that builds a monolithic client side engine - * that loads all widget implementation on application initialization. This has - * been the only option until Vaadin 6.4. - *

- * This generator uses the loadStyle hints from the {@link Connect} annotations. - * Depending on the {@link LoadStyle} used, the widget may be included in the - * initially loaded JavaScript, loaded when the application has started and - * there is no communication to server or lazy loaded when the implementation is - * absolutely needed. - *

- * The GWT module description file of the widgetset ( - * ...Widgetset.gwt.xml) can be used to define the - * WidgetMapGenarator. An example that defines this generator to be used: - * - *

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

- * Vaadin package also includes {@link LazyWidgetMapGenerator}, which is a good - * option if the transferred data should be minimized, and - * {@link CustomWidgetMapGenerator} for easy overriding of loading strategies. - * - */ -public class WidgetMapGenerator extends Generator { - - private static String serverConnectorClassName = ServerConnector.class - .getName(); - - private String packageName; - private String className; - - @Override - public String generate(TreeLogger logger, GeneratorContext context, - String typeName) throws UnableToCompleteException { - - try { - TypeOracle typeOracle = context.getTypeOracle(); - - // get classType and save instance variables - JClassType classType = typeOracle.getType(typeName); - packageName = classType.getPackage().getName(); - className = classType.getSimpleSourceName() + "Impl"; - // Generate class source code - generateClass(logger, context); - } catch (Exception e) { - logger.log(TreeLogger.ERROR, "WidgetMap creation failed", e); - } - // return the fully qualifed name of the class generated - return packageName + "." + className; - } - - /** - * Generate source code for WidgetMapImpl - * - * @param logger - * Logger object - * @param context - * Generator context - * @throws UnableToCompleteException - */ - private void generateClass(TreeLogger logger, GeneratorContext context) - throws UnableToCompleteException { - // get print writer that receives the source code - PrintWriter printWriter = null; - printWriter = context.tryCreate(logger, packageName, className); - // print writer if null, source code has ALREADY been generated, - // return (WidgetMap is equal to all permutations atm) - if (printWriter == null) { - return; - } - logger.log(Type.INFO, - "Detecting Vaadin connectors in classpath to generate WidgetMapImpl.java ..."); - Date date = new Date(); - - // init composer, set class properties, create source writer - ClassSourceFileComposerFactory composer = null; - composer = new ClassSourceFileComposerFactory(packageName, className); - composer.addImport("com.google.gwt.core.client.GWT"); - composer.addImport("java.util.HashMap"); - composer.addImport("com.google.gwt.core.client.RunAsyncCallback"); - composer.setSuperclass("com.vaadin.client.WidgetMap"); - SourceWriter sourceWriter = composer.createSourceWriter(context, - printWriter); - - Collection> connectors = getUsedConnectors(context - .getTypeOracle()); - - validateConnectors(logger, connectors); - logConnectors(logger, context, connectors); - - // generator constructor source code - generateImplementationDetector(logger, sourceWriter, connectors); - generateInstantiatorMethod(sourceWriter, connectors); - // close generated class - sourceWriter.outdent(); - sourceWriter.println("}"); - // commit generated class - context.commit(logger, printWriter); - logger.log(Type.INFO, - "Done. (" + (new Date().getTime() - date.getTime()) / 1000 - + "seconds)"); - - } - - private void validateConnectors(TreeLogger logger, - Collection> connectors) { - - Iterator> iter = connectors.iterator(); - while (iter.hasNext()) { - Class connectorClass = iter.next(); - Connect annotation = connectorClass.getAnnotation(Connect.class); - if (!ClientConnector.class.isAssignableFrom(annotation.value())) { - logger.log( - Type.WARN, - "Connector class " - + annotation.value().getName() - + " defined in @Connect annotation is not a subclass of " - + ClientConnector.class.getName() - + ". The component connector " - + connectorClass.getName() - + " will not be included in the widgetset."); - iter.remove(); - } - } - - } - - private void logConnectors(TreeLogger logger, GeneratorContext context, - Collection> connectors) { - logger.log(Type.INFO, - "Widget set will contain implementations for following component connectors: "); - - TreeSet classNames = new TreeSet(); - HashMap loadStyle = new HashMap(); - for (Class connectorClass : connectors) { - String className = connectorClass.getCanonicalName(); - classNames.add(className); - if (getLoadStyle(connectorClass) == LoadStyle.DEFERRED) { - loadStyle.put(className, "DEFERRED"); - } else if (getLoadStyle(connectorClass) == LoadStyle.LAZY) { - loadStyle.put(className, "LAZY"); - } - - } - for (String className : classNames) { - String msg = className; - if (loadStyle.containsKey(className)) { - msg += " (load style: " + loadStyle.get(className) + ")"; - } - logger.log(Type.INFO, "\t" + msg); - } - } - - /** - * This method is protected to allow creation of optimized widgetsets. The - * Widgetset will contain only implementation returned by this function. If - * one knows which widgets are needed for the application, returning only - * them here will significantly optimize the size of the produced JS. - * - * @return a collections of Vaadin components that will be added to - * widgetset - */ - @SuppressWarnings("unchecked") - private Collection> getUsedConnectors( - TypeOracle typeOracle) { - JClassType connectorType = typeOracle.findType(Connector.class - .getName()); - Collection> connectors = new HashSet>(); - for (JClassType jClassType : connectorType.getSubtypes()) { - Connect annotation = jClassType.getAnnotation(Connect.class); - if (annotation != null) { - try { - Class clazz = (Class) Class - .forName(jClassType.getQualifiedSourceName()); - connectors.add(clazz); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - } - return connectors; - } - - /** - * Returns true if the widget for given component will be lazy loaded by the - * client. The default implementation reads the information from the - * {@link Connect} annotation. - *

- * The method can be overridden to optimize the widget loading mechanism. If - * the Widgetset is wanted to be optimized for a network with a high latency - * or for a one with a very fast throughput, it may be good to return false - * for every component. - * - * @param connector - * @return true iff the widget for given component should be lazy loaded by - * the client side engine - */ - protected LoadStyle getLoadStyle(Class connector) { - Connect annotation = connector.getAnnotation(Connect.class); - return annotation.loadStyle(); - } - - private void generateInstantiatorMethod( - SourceWriter sourceWriter, - Collection> connectorsHavingComponentAnnotation) { - - Collection> deferredWidgets = new LinkedList>(); - - // TODO detect if it would be noticably faster to instantiate with a - // lookup with index than with the hashmap - - sourceWriter.println("public void ensureInstantiator(Class classType) {"); - sourceWriter.println("if(!instmap.containsKey(classType)){"); - boolean first = true; - - ArrayList> lazyLoadedConnectors = new ArrayList>(); - - HashSet> connectorsWithInstantiator = new HashSet>(); - - for (Class class1 : connectorsHavingComponentAnnotation) { - Class clientClass = class1; - if (connectorsWithInstantiator.contains(clientClass)) { - continue; - } - if (clientClass == UIConnector.class) { - // Roots are not instantiated by widgetset - continue; - } - if (!first) { - sourceWriter.print(" else "); - } else { - first = false; - } - sourceWriter.print("if( classType == " + clientClass.getName() - + ".class) {"); - - String instantiator = "new WidgetInstantiator() {\n public " - + serverConnectorClassName - + " get() {\n return GWT.create(" + clientClass.getName() - + ".class );\n}\n}\n"; - - LoadStyle loadStyle = getLoadStyle(class1); - - if (loadStyle != LoadStyle.EAGER) { - sourceWriter - .print("ApplicationConfiguration.startWidgetLoading();\n" - + "GWT.runAsync( \n" - + "new WidgetLoader() { void addInstantiator() {instmap.put(" - + clientClass.getName() - + ".class," - + instantiator + ");}});\n"); - lazyLoadedConnectors.add(class1); - - if (loadStyle == LoadStyle.DEFERRED) { - deferredWidgets.add(class1); - } - - } else { - // widget implementation in initially loaded js script - sourceWriter.print("instmap.put("); - sourceWriter.print(clientClass.getName()); - sourceWriter.print(".class, "); - sourceWriter.print(instantiator); - sourceWriter.print(");"); - } - sourceWriter.print("}"); - connectorsWithInstantiator.add(clientClass); - } - - sourceWriter.println("}"); - - sourceWriter.println("}"); - - sourceWriter.println("public Class[] getDeferredLoadedConnectors() {"); - - sourceWriter.println("return new Class[] {"); - first = true; - for (Class class2 : deferredWidgets) { - if (!first) { - sourceWriter.println(","); - } - first = false; - sourceWriter.print(class2.getName() + ".class"); - } - - sourceWriter.println("};"); - sourceWriter.println("}"); - - // in constructor add a "thread" that lazyly loads lazy loaded widgets - // if communication to server idles - - // TODO an array of lazy loaded widgets - - // TODO an index of last ensured widget in array - - sourceWriter.println("public " + serverConnectorClassName - + " instantiate(Class classType) {"); - sourceWriter.indent(); - sourceWriter.println(serverConnectorClassName - + " p = super.instantiate(classType); if(p!= null) return p;"); - sourceWriter.println("return instmap.get(classType).get();"); - - sourceWriter.outdent(); - sourceWriter.println("}"); - - } - - /** - * - * @param logger - * logger to print messages to - * @param sourceWriter - * Source writer to output source code - * @param paintablesHavingWidgetAnnotation - * @throws UnableToCompleteException - */ - private void generateImplementationDetector( - TreeLogger logger, - SourceWriter sourceWriter, - Collection> paintablesHavingWidgetAnnotation) - throws UnableToCompleteException { - sourceWriter - .println("public Class " - + "getConnectorClassForServerSideClassName(String fullyQualifiedName) {"); - sourceWriter.indent(); - sourceWriter - .println("fullyQualifiedName = fullyQualifiedName.intern();"); - - // Keep track of encountered mappings to detect conflicts - Map, Class> mappings = new HashMap, Class>(); - - for (Class connectorClass : paintablesHavingWidgetAnnotation) { - Class clientConnectorClass = getClientConnectorClass(connectorClass); - - // Check for conflicts - Class prevousMapping = mappings.put( - clientConnectorClass, connectorClass); - if (prevousMapping != null) { - logger.log(Type.ERROR, - "Both " + connectorClass.getName() + " and " - + prevousMapping.getName() - + " have @Connect referring to " - + clientConnectorClass.getName() + "."); - throw new UnableToCompleteException(); - } - - sourceWriter.print("if ( fullyQualifiedName == \""); - sourceWriter.print(clientConnectorClass.getName()); - sourceWriter.print("\" ) { ensureInstantiator(" - + connectorClass.getName() + ".class); return "); - sourceWriter.print(connectorClass.getName()); - sourceWriter.println(".class;}"); - sourceWriter.print("else "); - } - sourceWriter.println("return " - + UnknownComponentConnector.class.getName() + ".class;"); - sourceWriter.outdent(); - sourceWriter.println("}"); - - } - - private static Class getClientConnectorClass( - Class connectorClass) { - Connect annotation = connectorClass.getAnnotation(Connect.class); - return (Class) annotation.value(); - } -} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetSetBuilder.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetSetBuilder.java deleted file mode 100644 index bcfa9990ec..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetSetBuilder.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright 2011 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.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.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. - * - *

- * 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 { - if (args.length == 0) { - printUsage(); - } else { - String widgetsetname = args[0]; - updateWidgetSet(widgetsetname); - - } - } - - public static void updateWidgetSet(final String widgetset) - throws IOException, FileNotFoundException { - boolean changed = false; - - Map availableWidgetSets = ClassPathExplorer - .getAvailableWidgetSets(); - - URL sourceUrl = availableWidgetSets.get(widgetset); - if (sourceUrl == null) { - // find first/default source directory - sourceUrl = ClassPathExplorer.getDefaultSourceDirectory(); - } - - String widgetsetfilename = sourceUrl.getFile() + "/" - + widgetset.replace(".", "/") + ".gwt.xml"; - - File widgetsetFile = new File(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(); - PrintStream printStream = new PrintStream(new FileOutputStream( - widgetsetFile)); - printStream.print("\n" - + "\n"); - printStream.print("\n"); - printStream - .print(" \n" - + " \n"); - printStream.print("\n\n"); - printStream.close(); - changed = true; - } - - String content = readFile(widgetsetFile); - if (isEditable(content)) { - String originalContent = content; - - Collection oldInheritedWidgetsets = getCurrentInheritedWidgetsets(content); - - // add widgetsets that do not exist - Iterator 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(widgetsetfilename, 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("", ""); - } - - 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("", "\n " + "\n"); - } - - private static Collection getCurrentInheritedWidgetsets( - String content) { - HashSet 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 { - 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"); - } - fi.close(); - 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"); - - } - -} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ArraySerializer.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ArraySerializer.java deleted file mode 100644 index 010503c508..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ArraySerializer.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2011 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.terminal.gwt.widgetsetutils.metadata; - -import com.google.gwt.core.ext.TreeLogger; -import com.google.gwt.core.ext.typeinfo.JArrayType; -import com.google.gwt.core.ext.typeinfo.JType; -import com.google.gwt.json.client.JSONArray; -import com.google.gwt.user.rebind.SourceWriter; -import com.vaadin.client.communication.JsonDecoder; -import com.vaadin.client.communication.JsonEncoder; -import com.vaadin.terminal.gwt.widgetsetutils.ConnectorBundleLoaderFactory; - -public class ArraySerializer extends JsonSerializer { - - private final JArrayType arrayType; - - public ArraySerializer(JArrayType arrayType) { - super(arrayType); - this.arrayType = arrayType; - } - - @Override - protected void printDeserializerBody(TreeLogger logger, SourceWriter w, - String type, String jsonValue, String connection) { - JType leafType = arrayType.getLeafType(); - int rank = arrayType.getRank(); - - w.println(JSONArray.class.getName() + " jsonArray = " + jsonValue - + ".isArray();"); - - // Type value = new Type[jsonArray.size()][][]; - w.print(arrayType.getQualifiedSourceName() + " value = new " - + leafType.getQualifiedSourceName() + "[jsonArray.size()]"); - for (int i = 1; i < rank; i++) { - w.print("[]"); - } - w.println(";"); - - w.println("for(int i = 0 ; i < value.length; i++) {"); - w.indent(); - - JType componentType = arrayType.getComponentType(); - - w.print("value[i] = (" - + ConnectorBundleLoaderFactory.getBoxedTypeName(componentType) - + ") " + JsonDecoder.class.getName() + ".decodeValue("); - ConnectorBundleLoaderFactory.writeTypeCreator(w, componentType); - w.print(", jsonArray.get(i), null, " + connection + ")"); - - w.println(";"); - - w.outdent(); - w.println("}"); - - w.println("return value;"); - } - - @Override - protected void printSerializerBody(TreeLogger logger, SourceWriter w, - String value, String applicationConnection) { - w.println(JSONArray.class.getName() + " values = new " - + JSONArray.class.getName() + "();"); - // JPrimitiveType primitive = componentType.isPrimitive(); - w.println("for (int i = 0; i < " + value + ".length; i++) {"); - w.indent(); - w.print("values.set(i, "); - w.print(JsonEncoder.class.getName() + ".encode(" + value - + "[i], false, " + applicationConnection + ")"); - w.println(");"); - w.outdent(); - w.println("}"); - w.println("return values;"); - } - -} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ClientRpcVisitor.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ClientRpcVisitor.java deleted file mode 100644 index d5a78b86b9..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ClientRpcVisitor.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2011 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.terminal.gwt.widgetsetutils.metadata; - -import java.util.Set; - -import com.google.gwt.core.ext.TreeLogger; -import com.google.gwt.core.ext.typeinfo.JClassType; -import com.google.gwt.core.ext.typeinfo.JMethod; -import com.google.gwt.core.ext.typeinfo.JType; - -public class ClientRpcVisitor extends TypeVisitor { - @Override - public void visitClientRpc(TreeLogger logger, JClassType type, - ConnectorBundle bundle) { - Set hierarchy = type - .getFlattenedSupertypeHierarchy(); - for (JClassType subType : hierarchy) { - JMethod[] methods = subType.getMethods(); - for (JMethod method : methods) { - bundle.setNeedsInvoker(type, method); - bundle.setNeedsParamTypes(type, method); - - JType[] parameterTypes = method.getParameterTypes(); - for (JType paramType : parameterTypes) { - bundle.setNeedsSerialize(paramType); - } - } - } - } -} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ConnectorBundle.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ConnectorBundle.java deleted file mode 100644 index 9fb08f720e..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ConnectorBundle.java +++ /dev/null @@ -1,611 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.terminal.gwt.widgetsetutils.metadata; - -import java.io.Serializable; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import com.google.gwt.core.ext.TreeLogger; -import com.google.gwt.core.ext.TreeLogger.Type; -import com.google.gwt.core.ext.UnableToCompleteException; -import com.google.gwt.core.ext.typeinfo.JArrayType; -import com.google.gwt.core.ext.typeinfo.JClassType; -import com.google.gwt.core.ext.typeinfo.JEnumType; -import com.google.gwt.core.ext.typeinfo.JMethod; -import com.google.gwt.core.ext.typeinfo.JParameterizedType; -import com.google.gwt.core.ext.typeinfo.JType; -import com.google.gwt.core.ext.typeinfo.NotFoundException; -import com.google.gwt.core.ext.typeinfo.TypeOracle; -import com.google.gwt.json.client.JSONValue; -import com.vaadin.client.ApplicationConnection; -import com.vaadin.client.ComponentConnector; -import com.vaadin.client.ServerConnector; -import com.vaadin.client.communication.JSONSerializer; -import com.vaadin.client.ui.UnknownComponentConnector; -import com.vaadin.shared.communication.ClientRpc; -import com.vaadin.shared.communication.ServerRpc; -import com.vaadin.shared.ui.Connect; - -public class ConnectorBundle { - private static final String FAIL_IF_NOT_SERIALIZABLE = "vFailIfNotSerializable"; - - private final String name; - private final ConnectorBundle previousBundle; - private final Collection visitors; - private final Map customSerializers; - - private final Set hasSerializeSupport = new HashSet(); - private final Set needsSerializeSupport = new HashSet(); - private final Map serializers = new HashMap(); - - private final Set needsPropertyList = new HashSet(); - private final Set needsGwtConstructor = new HashSet(); - private final Set visitedTypes = new HashSet(); - private final Set needsProxySupport = new HashSet(); - - private final Map> identifiers = new HashMap>(); - private final Map> needsReturnType = new HashMap>(); - private final Map> needsInvoker = new HashMap>(); - private final Map> needsParamTypes = new HashMap>(); - private final Map> needsDelayedInfo = new HashMap>(); - - private final Set needsSetter = new HashSet(); - private final Set needsType = new HashSet(); - private final Set needsGetter = new HashSet(); - private final Set needsDelegateToWidget = new HashSet(); - - private ConnectorBundle(String name, ConnectorBundle previousBundle, - Collection visitors, - Map customSerializers) { - this.name = name; - this.previousBundle = previousBundle; - this.visitors = visitors; - this.customSerializers = customSerializers; - } - - public ConnectorBundle(String name, ConnectorBundle previousBundle) { - this(name, previousBundle, previousBundle.visitors, - previousBundle.customSerializers); - } - - public ConnectorBundle(String name, Collection visitors, - TypeOracle oracle) throws NotFoundException { - this(name, null, visitors, findCustomSerializers(oracle)); - } - - private static Map findCustomSerializers( - TypeOracle oracle) throws NotFoundException { - Map serializers = new HashMap(); - - JClassType serializerInterface = oracle.findType(JSONSerializer.class - .getName()); - JType[] deserializeParamTypes = new JType[] { - oracle.findType(com.vaadin.client.metadata.Type.class - .getName()), - oracle.findType(JSONValue.class.getName()), - oracle.findType(ApplicationConnection.class.getName()) }; - String deserializeMethodName = "deserialize"; - // Just test that the method exists - serializerInterface.getMethod(deserializeMethodName, - deserializeParamTypes); - - for (JClassType serializer : serializerInterface.getSubtypes()) { - JMethod deserializeMethod = serializer.findMethod( - deserializeMethodName, deserializeParamTypes); - if (deserializeMethod == null) { - continue; - } - JType returnType = deserializeMethod.getReturnType(); - - serializers.put(returnType, serializer); - } - return serializers; - } - - public void setNeedsGwtConstructor(JClassType type) { - if (!needsGwtConstructor(type)) { - needsGwtConstructor.add(type); - } - } - - private boolean needsGwtConstructor(JClassType type) { - if (needsGwtConstructor.contains(type)) { - return true; - } else { - return previousBundle != null - && previousBundle.needsGwtConstructor(type); - } - } - - public void setIdentifier(JClassType type, String identifier) { - if (!hasIdentifier(type, identifier)) { - addMapping(identifiers, type, identifier); - } - } - - private boolean hasIdentifier(JClassType type, String identifier) { - if (hasMapping(identifiers, type, identifier)) { - return true; - } else { - return previousBundle != null - && previousBundle.hasIdentifier(type, identifier); - } - } - - public ConnectorBundle getPreviousBundle() { - return previousBundle; - } - - public String getName() { - return name; - } - - public Map> getIdentifiers() { - return Collections.unmodifiableMap(identifiers); - } - - public Set getGwtConstructors() { - return Collections.unmodifiableSet(needsGwtConstructor); - } - - public void processTypes(TreeLogger logger, Collection types) - throws UnableToCompleteException { - for (JClassType type : types) { - processType(logger, type); - } - } - - public void processType(TreeLogger logger, JClassType type) - throws UnableToCompleteException { - if (!isTypeVisited(type)) { - for (TypeVisitor typeVisitor : visitors) { - invokeVisitor(logger, type, typeVisitor); - } - visitedTypes.add(type); - purgeSerializeSupportQueue(logger); - } - } - - private boolean isTypeVisited(JClassType type) { - if (visitedTypes.contains(type)) { - return true; - } else { - return previousBundle != null && previousBundle.isTypeVisited(type); - } - } - - private void purgeSerializeSupportQueue(TreeLogger logger) - throws UnableToCompleteException { - while (!needsSerializeSupport.isEmpty()) { - Iterator iterator = needsSerializeSupport.iterator(); - JType type = iterator.next(); - iterator.remove(); - - if (hasSserializeSupport(type)) { - continue; - } - - addSerializeSupport(logger, type); - } - } - - private void addSerializeSupport(TreeLogger logger, JType type) - throws UnableToCompleteException { - hasSerializeSupport.add(type); - - JParameterizedType parametrized = type.isParameterized(); - if (parametrized != null) { - for (JClassType parameterType : parametrized.getTypeArgs()) { - setNeedsSerialize(parameterType); - } - } - - if (serializationHandledByFramework(type)) { - return; - } - - JClassType customSerializer = customSerializers.get(type); - JClassType typeAsClass = type.isClass(); - JEnumType enumType = type.isEnum(); - JArrayType arrayType = type.isArray(); - - if (customSerializer != null) { - logger.log(Type.INFO, "Will serialize " + type + " using " - + customSerializer.getName()); - setSerializer(type, new CustomSerializer(customSerializer)); - } else if (arrayType != null) { - logger.log(Type.INFO, "Will serialize " + type + " as an array"); - setSerializer(type, new ArraySerializer(arrayType)); - setNeedsSerialize(arrayType.getComponentType()); - } else if (enumType != null) { - logger.log(Type.INFO, "Will serialize " + type + " as an enum"); - setSerializer(type, new EnumSerializer(enumType)); - } else if (typeAsClass != null) { - // Bean - checkSerializable(logger, typeAsClass); - - logger.log(Type.INFO, "Will serialize " + type + " as a bean"); - - setNeedsPropertyList(typeAsClass); - - for (Property property : getProperties(typeAsClass)) { - setNeedsGwtConstructor(property.getBeanType()); - setNeedsSetter(property); - - // Getters needed for reading previous value that should be - // passed to sub encoder - setNeedsGetter(property); - setNeedsType(property); - - JType propertyType = property.getPropertyType(); - setNeedsSerialize(propertyType); - } - } - } - - private void checkSerializable(TreeLogger logger, JClassType type) - throws UnableToCompleteException { - JClassType javaSerializable = type.getOracle().findType( - Serializable.class.getName()); - boolean serializable = type.isAssignableTo(javaSerializable); - if (!serializable) { - boolean abortCompile = "true".equals(System - .getProperty(FAIL_IF_NOT_SERIALIZABLE)); - logger.log( - abortCompile ? Type.ERROR : Type.WARN, - type - + " is used in RPC or shared state but does not implement " - + Serializable.class.getName() - + ". Communication will work but the Application on server side cannot be serialized if it refers to objects of this type. " - + "If the system property " - + FAIL_IF_NOT_SERIALIZABLE - + " is set to \"true\", this causes the compilation to fail instead of just emitting a warning."); - if (abortCompile) { - throw new UnableToCompleteException(); - } - } - } - - private void setSerializer(JType type, GeneratedSerializer serializer) { - if (!hasSerializer(type)) { - serializers.put(type, serializer); - } - } - - private boolean hasSerializer(JType type) { - if (serializers.containsKey(type)) { - return true; - } else { - return previousBundle != null && previousBundle.hasSerializer(type); - } - } - - public Map getSerializers() { - return Collections.unmodifiableMap(serializers); - } - - private void setNeedsGetter(Property property) { - if (!isNeedsGetter(property)) { - needsGetter.add(property); - } - } - - private boolean isNeedsGetter(Property property) { - if (needsGetter.contains(property)) { - return true; - } else { - return previousBundle != null - && previousBundle.isNeedsGetter(property); - } - } - - public Set getNeedsGetter() { - return Collections.unmodifiableSet(needsGetter); - } - - private void setNeedsType(Property property) { - if (!isNeedsType(property)) { - needsType.add(property); - } - } - - public Set getNeedsType() { - return Collections.unmodifiableSet(needsType); - } - - private boolean isNeedsType(Property property) { - if (needsType.contains(property)) { - return true; - } else { - return previousBundle != null - && previousBundle.isNeedsType(property); - } - } - - public void setNeedsSetter(Property property) { - if (!isNeedsSetter(property)) { - needsSetter.add(property); - } - } - - private boolean isNeedsSetter(Property property) { - if (needsSetter.contains(property)) { - return true; - } else { - return previousBundle != null - && previousBundle.isNeedsSetter(property); - } - } - - public Set getNeedsSetter() { - return Collections.unmodifiableSet(needsSetter); - } - - private void setNeedsPropertyList(JClassType type) { - if (!isNeedsPropertyList(type)) { - needsPropertyList.add(type); - } - } - - private boolean isNeedsPropertyList(JClassType type) { - if (needsPropertyList.contains(type)) { - return true; - } else { - return previousBundle != null - && previousBundle.isNeedsPropertyList(type); - } - } - - public Set getNeedsPropertyListing() { - return Collections.unmodifiableSet(needsPropertyList); - } - - public Collection getProperties(JClassType type) { - HashSet properties = new HashSet(); - - properties.addAll(MethodProperty.findProperties(type)); - properties.addAll(FieldProperty.findProperties(type)); - - return properties; - } - - private void invokeVisitor(TreeLogger logger, JClassType type, - TypeVisitor typeVisitor) throws UnableToCompleteException { - TreeLogger subLogger = logger.branch(Type.TRACE, - "Visiting " + type.getName() + " with " - + typeVisitor.getClass().getSimpleName()); - if (isConnectedConnector(type)) { - typeVisitor.visitConnector(subLogger, type, this); - } - if (isClientRpc(type)) { - typeVisitor.visitClientRpc(subLogger, type, this); - } - if (isServerRpc(type)) { - typeVisitor.visitServerRpc(subLogger, type, this); - } - } - - public void processSubTypes(TreeLogger logger, JClassType type) - throws UnableToCompleteException { - processTypes(logger, Arrays.asList(type.getSubtypes())); - } - - public void setNeedsReturnType(JClassType type, JMethod method) { - if (!isNeedsReturnType(type, method)) { - addMapping(needsReturnType, type, method); - } - } - - private boolean isNeedsReturnType(JClassType type, JMethod method) { - if (hasMapping(needsReturnType, type, method)) { - return true; - } else { - return previousBundle != null - && previousBundle.isNeedsReturnType(type, method); - } - } - - public Map> getMethodReturnTypes() { - return Collections.unmodifiableMap(needsReturnType); - } - - private static boolean isClientRpc(JClassType type) { - return isType(type, ClientRpc.class); - } - - private static boolean isServerRpc(JClassType type) { - return isType(type, ServerRpc.class); - } - - public static boolean isConnectedConnector(JClassType type) { - return isConnected(type) && isType(type, ServerConnector.class); - } - - private static boolean isConnected(JClassType type) { - return type.isAnnotationPresent(Connect.class) - || type.getQualifiedSourceName().equals( - UnknownComponentConnector.class.getCanonicalName()); - } - - public static boolean isConnectedComponentConnector(JClassType type) { - return isConnected(type) && isType(type, ComponentConnector.class); - } - - private static boolean isType(JClassType type, Class class1) { - try { - return type.getOracle().getType(class1.getName()) - .isAssignableFrom(type); - } catch (NotFoundException e) { - throw new RuntimeException("Could not find " + class1.getName(), e); - } - } - - public void setNeedsInvoker(JClassType type, JMethod method) { - if (!isNeedsInvoker(type, method)) { - addMapping(needsInvoker, type, method); - } - } - - private void addMapping(Map> map, K key, V value) { - Set set = map.get(key); - if (set == null) { - set = new HashSet(); - map.put(key, set); - } - set.add(value); - } - - private boolean hasMapping(Map> map, K key, V value) { - return map.containsKey(key) && map.get(key).contains(value); - } - - private boolean isNeedsInvoker(JClassType type, JMethod method) { - if (hasMapping(needsInvoker, type, method)) { - return true; - } else { - return previousBundle != null - && previousBundle.isNeedsInvoker(type, method); - } - } - - public Map> getNeedsInvoker() { - return Collections.unmodifiableMap(needsInvoker); - } - - public void setNeedsParamTypes(JClassType type, JMethod method) { - if (!isNeedsParamTypes(type, method)) { - addMapping(needsParamTypes, type, method); - } - } - - private boolean isNeedsParamTypes(JClassType type, JMethod method) { - if (hasMapping(needsParamTypes, type, method)) { - return true; - } else { - return previousBundle != null - && previousBundle.isNeedsParamTypes(type, method); - } - } - - public Map> getNeedsParamTypes() { - return Collections.unmodifiableMap(needsParamTypes); - } - - public void setNeedsProxySupport(JClassType type) { - if (!isNeedsProxySupport(type)) { - needsProxySupport.add(type); - } - } - - private boolean isNeedsProxySupport(JClassType type) { - if (needsProxySupport.contains(type)) { - return true; - } else { - return previousBundle != null - && previousBundle.isNeedsProxySupport(type); - } - } - - public Set getNeedsProxySupport() { - return Collections.unmodifiableSet(needsProxySupport); - } - - public void setNeedsDelayedInfo(JClassType type, JMethod method) { - if (!isNeedsDelayedInfo(type, method)) { - addMapping(needsDelayedInfo, type, method); - } - } - - private boolean isNeedsDelayedInfo(JClassType type, JMethod method) { - if (hasMapping(needsDelayedInfo, type, method)) { - return true; - } else { - return previousBundle != null - && previousBundle.isNeedsDelayedInfo(type, method); - } - } - - public Map> getNeedsDelayedInfo() { - return Collections.unmodifiableMap(needsDelayedInfo); - } - - public void setNeedsSerialize(JType type) { - if (!hasSserializeSupport(type)) { - needsSerializeSupport.add(type); - } - } - - private static Set> frameworkHandledTypes = new HashSet>(); - { - frameworkHandledTypes.add(String.class); - frameworkHandledTypes.add(Boolean.class); - frameworkHandledTypes.add(Integer.class); - frameworkHandledTypes.add(Float.class); - frameworkHandledTypes.add(Double.class); - frameworkHandledTypes.add(Long.class); - frameworkHandledTypes.add(Enum.class); - frameworkHandledTypes.add(String[].class); - frameworkHandledTypes.add(Object[].class); - frameworkHandledTypes.add(Map.class); - frameworkHandledTypes.add(List.class); - frameworkHandledTypes.add(Set.class); - frameworkHandledTypes.add(Byte.class); - frameworkHandledTypes.add(Character.class); - - } - - private boolean serializationHandledByFramework(JType setterType) { - // Some types are handled by the framework at the moment. See #8449 - // This method should be removed at some point. - if (setterType.isPrimitive() != null) { - return true; - } - - String qualifiedName = setterType.getQualifiedSourceName(); - for (Class cls : frameworkHandledTypes) { - if (qualifiedName.equals(cls.getName())) { - return true; - } - } - - return false; - } - - private boolean hasSserializeSupport(JType type) { - if (hasSerializeSupport.contains(type)) { - return true; - } else { - return previousBundle != null - && previousBundle.hasSserializeSupport(type); - } - } - - public void setNeedsDelegateToWidget(Property property) { - if (!isNeedsDelegateToWidget(property)) { - needsDelegateToWidget.add(property); - } - } - - private boolean isNeedsDelegateToWidget(Property property) { - if (needsDelegateToWidget.contains(property)) { - return true; - } else { - return previousBundle != null - && previousBundle.isNeedsDelegateToWidget(property); - } - } - - public Set getNeedsDelegateToWidget() { - return Collections.unmodifiableSet(needsDelegateToWidget); - } -} \ No newline at end of file diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ConnectorInitVisitor.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ConnectorInitVisitor.java deleted file mode 100644 index fec337afd9..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ConnectorInitVisitor.java +++ /dev/null @@ -1,27 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.terminal.gwt.widgetsetutils.metadata; - -import com.google.gwt.core.ext.TreeLogger; -import com.google.gwt.core.ext.TreeLogger.Type; -import com.google.gwt.core.ext.typeinfo.JClassType; -import com.vaadin.shared.ui.Connect; - -public class ConnectorInitVisitor extends TypeVisitor { - - @Override - public void visitConnector(TreeLogger logger, JClassType type, - ConnectorBundle bundle) { - Connect connectAnnotation = type.getAnnotation(Connect.class); - if (connectAnnotation != null) { - logger.log(Type.INFO, type.getName() + " will be in the " - + bundle.getName().replaceAll("^_*", "") + " bundle"); - bundle.setIdentifier(type, connectAnnotation.value() - .getCanonicalName()); - bundle.setNeedsGwtConstructor(type); - } - } - -} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/CustomSerializer.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/CustomSerializer.java deleted file mode 100644 index 11252c4acb..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/CustomSerializer.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2011 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.terminal.gwt.widgetsetutils.metadata; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.core.ext.TreeLogger; -import com.google.gwt.core.ext.UnableToCompleteException; -import com.google.gwt.core.ext.typeinfo.JClassType; -import com.google.gwt.user.rebind.SourceWriter; -import com.vaadin.terminal.gwt.widgetsetutils.ConnectorBundleLoaderFactory; - -public class CustomSerializer implements GeneratedSerializer { - - private final JClassType serializerType; - - public CustomSerializer(JClassType serializerType) { - this.serializerType = serializerType; - } - - @Override - public void writeSerializerInstantiator(TreeLogger logger, SourceWriter w) - throws UnableToCompleteException { - w.print("return "); - w.print(GWT.class.getCanonicalName()); - w.print(".create("); - ConnectorBundleLoaderFactory.writeClassLiteral(w, serializerType); - w.println(");"); - } -} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/EnumSerializer.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/EnumSerializer.java deleted file mode 100644 index 324b555300..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/EnumSerializer.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2011 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.terminal.gwt.widgetsetutils.metadata; - -import com.google.gwt.core.ext.TreeLogger; -import com.google.gwt.core.ext.typeinfo.JEnumConstant; -import com.google.gwt.core.ext.typeinfo.JEnumType; -import com.google.gwt.json.client.JSONString; -import com.google.gwt.user.rebind.SourceWriter; - -public class EnumSerializer extends JsonSerializer { - - private final JEnumType enumType; - - public EnumSerializer(JEnumType type) { - super(type); - enumType = type; - } - - @Override - protected void printDeserializerBody(TreeLogger logger, SourceWriter w, - String type, String jsonValue, String connection) { - w.println("String enumIdentifier = ((" + JSONString.class.getName() - + ")" + jsonValue + ").stringValue();"); - for (JEnumConstant e : enumType.getEnumConstants()) { - w.println("if (\"" + e.getName() + "\".equals(enumIdentifier)) {"); - w.indent(); - w.println("return " + enumType.getQualifiedSourceName() + "." - + e.getName() + ";"); - w.outdent(); - w.println("}"); - } - w.println("return null;"); - } - - @Override - protected void printSerializerBody(TreeLogger logger, SourceWriter w, - String value, String applicationConnection) { - // return new JSONString(castedValue.name()); - w.println("return new " + JSONString.class.getName() + "(" + value - + ".name());"); - } - -} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/FieldProperty.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/FieldProperty.java deleted file mode 100644 index c4c2a50e1c..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/FieldProperty.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2011 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.terminal.gwt.widgetsetutils.metadata; - -import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import com.google.gwt.core.ext.TreeLogger; -import com.google.gwt.core.ext.typeinfo.JClassType; -import com.google.gwt.core.ext.typeinfo.JField; -import com.google.gwt.user.rebind.SourceWriter; - -public class FieldProperty extends Property { - - private final JField field; - - private FieldProperty(JClassType beanType, JField field) { - super(field.getName(), beanType, field.getType()); - this.field = field; - } - - @Override - public void writeSetterBody(TreeLogger logger, SourceWriter w, - String beanVariable, String valueVariable) { - w.print("((%s) %s).%s = (%s)%s;", getBeanType() - .getQualifiedSourceName(), beanVariable, getName(), - getUnboxedPropertyTypeName(), valueVariable); - } - - @Override - public void writeGetterBody(TreeLogger logger, SourceWriter w, - String beanVariable) { - w.print("return ((%s) %s).%s;", getBeanType().getQualifiedSourceName(), - beanVariable, getName()); - } - - public static Collection findProperties(JClassType type) { - Collection properties = new ArrayList(); - - List fields = getPublicFields(type); - for (JField field : fields) { - properties.add(new FieldProperty(type, field)); - } - - return properties; - } - - private static List getPublicFields(JClassType type) { - Set names = new HashSet(); - ArrayList fields = new ArrayList(); - for (JClassType subType : type.getFlattenedSupertypeHierarchy()) { - JField[] subFields = subType.getFields(); - for (JField field : subFields) { - if (field.isPublic() && !field.isStatic() - && names.add(field.getName())) { - fields.add(field); - } - } - } - return fields; - } - - @Override - public T getAnnotation(Class annotationClass) { - return field.getAnnotation(annotationClass); - } - -} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/GeneratedSerializer.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/GeneratedSerializer.java deleted file mode 100644 index 0cfde7748c..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/GeneratedSerializer.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2011 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.terminal.gwt.widgetsetutils.metadata; - -import com.google.gwt.core.ext.TreeLogger; -import com.google.gwt.core.ext.UnableToCompleteException; -import com.google.gwt.user.rebind.SourceWriter; - -public interface GeneratedSerializer { - public void writeSerializerInstantiator(TreeLogger logger, SourceWriter w) - throws UnableToCompleteException; -} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/JsonSerializer.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/JsonSerializer.java deleted file mode 100644 index 0beddeae8e..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/JsonSerializer.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2011 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.terminal.gwt.widgetsetutils.metadata; - -import com.google.gwt.core.ext.TreeLogger; -import com.google.gwt.core.ext.UnableToCompleteException; -import com.google.gwt.core.ext.typeinfo.JType; -import com.google.gwt.json.client.JSONValue; -import com.google.gwt.user.rebind.SourceWriter; -import com.vaadin.client.ApplicationConnection; -import com.vaadin.client.communication.JSONSerializer; - -public abstract class JsonSerializer implements GeneratedSerializer { - - private final JType type; - - public JsonSerializer(JType type) { - this.type = type; - } - - @Override - public void writeSerializerInstantiator(TreeLogger logger, SourceWriter w) - throws UnableToCompleteException { - - w.print("return new "); - w.print(JSONSerializer.class.getCanonicalName()); - w.print("<"); - w.print(type.getQualifiedSourceName()); - w.println(">() {"); - w.indent(); - - writeSerializerBody(logger, w); - - w.outdent(); - w.println("};"); - } - - protected void writeSerializerBody(TreeLogger logger, SourceWriter w) { - String qualifiedSourceName = type.getQualifiedSourceName(); - w.println("public " + JSONValue.class.getName() + " serialize(" - + qualifiedSourceName + " value, " - + ApplicationConnection.class.getName() + " connection) {"); - w.indent(); - // MouseEventDetails castedValue = (MouseEventDetails) value; - w.println(qualifiedSourceName + " castedValue = (" - + qualifiedSourceName + ") value;"); - - printSerializerBody(logger, w, "castedValue", "connection"); - - // End of serializer method - w.outdent(); - w.println("}"); - - // Deserializer - // T deserialize(Type type, JSONValue jsonValue, ApplicationConnection - // connection); - w.println("public " + qualifiedSourceName + " deserialize(Type type, " - + JSONValue.class.getName() + " jsonValue, " - + ApplicationConnection.class.getName() + " connection) {"); - w.indent(); - - printDeserializerBody(logger, w, "type", "jsonValue", "connection"); - - w.outdent(); - w.println("}"); - } - - protected abstract void printDeserializerBody(TreeLogger logger, - SourceWriter w, String type, String jsonValue, String connection); - - protected abstract void printSerializerBody(TreeLogger logger, - SourceWriter w, String value, String applicationConnection); - -} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/MethodProperty.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/MethodProperty.java deleted file mode 100644 index 431ead7f96..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/MethodProperty.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2011 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.terminal.gwt.widgetsetutils.metadata; - -import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import com.google.gwt.core.ext.TreeLogger; -import com.google.gwt.core.ext.typeinfo.JClassType; -import com.google.gwt.core.ext.typeinfo.JMethod; -import com.google.gwt.core.ext.typeinfo.JType; -import com.google.gwt.user.rebind.SourceWriter; - -public class MethodProperty extends Property { - - private final JMethod setter; - - private MethodProperty(JClassType beanType, JMethod setter) { - super(getTransportFieldName(setter), beanType, setter - .getParameterTypes()[0]); - this.setter = setter; - } - - public static Collection findProperties(JClassType type) { - Collection properties = new ArrayList(); - - List setters = getSetters(type); - for (JMethod setter : setters) { - properties.add(new MethodProperty(type, setter)); - } - - return properties; - } - - /** - * Returns a list of all setters found in the beanType or its parent class - * - * @param beanType - * The type to check - * @return A list of setter methods from the class and its parents - */ - private static List getSetters(JClassType beanType) { - List setterMethods = new ArrayList(); - - while (beanType != null - && !beanType.getQualifiedSourceName().equals( - Object.class.getName())) { - for (JMethod method : beanType.getMethods()) { - // Process all setters that have corresponding fields - if (!method.isPublic() || method.isStatic() - || !method.getName().startsWith("set") - || method.getParameterTypes().length != 1) { - // Not setter, skip to next method - continue; - } - setterMethods.add(method); - } - beanType = beanType.getSuperclass(); - } - - return setterMethods; - } - - @Override - public void writeSetterBody(TreeLogger logger, SourceWriter w, - String beanVariable, String valueVariable) { - w.print("(("); - w.print(getBeanType().getQualifiedSourceName()); - w.print(") "); - w.print(beanVariable); - w.print(")."); - w.print(setter.getName()); - w.print("(("); - w.print(getUnboxedPropertyTypeName()); - w.print(") "); - w.print(valueVariable); - w.println(");"); - } - - @Override - public void writeGetterBody(TreeLogger logger, SourceWriter w, - String beanVariable) { - w.print("return (("); - w.print(getBeanType().getQualifiedSourceName()); - w.print(") "); - w.print(beanVariable); - w.print(")."); - w.print(findGetter(getBeanType(), setter)); - w.print("();"); - } - - private String findGetter(JClassType beanType, JMethod setterMethod) { - JType setterParameterType = setterMethod.getParameterTypes()[0]; - String fieldName = setterMethod.getName().substring(3); - if (setterParameterType.getQualifiedSourceName().equals( - boolean.class.getName())) { - return "is" + fieldName; - } else { - return "get" + fieldName; - } - } - - private static String getTransportFieldName(JMethod setter) { - String baseName = setter.getName().substring(3); - return Character.toLowerCase(baseName.charAt(0)) - + baseName.substring(1); - } - - @Override - public T getAnnotation(Class annotationClass) { - return setter.getAnnotation(annotationClass); - } - -} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/Property.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/Property.java deleted file mode 100644 index 5ef0293688..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/Property.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2011 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.terminal.gwt.widgetsetutils.metadata; - -import java.lang.annotation.Annotation; - -import com.google.gwt.core.ext.TreeLogger; -import com.google.gwt.core.ext.typeinfo.JClassType; -import com.google.gwt.core.ext.typeinfo.JPrimitiveType; -import com.google.gwt.core.ext.typeinfo.JType; -import com.google.gwt.user.rebind.SourceWriter; - -public abstract class Property { - private final String name; - private final JClassType beanType; - private final JType propertyType; - - protected Property(String name, JClassType beanType, JType propertyType) { - this.name = name; - this.beanType = beanType; - this.propertyType = propertyType; - } - - public String getName() { - return name; - } - - public JType getPropertyType() { - return propertyType; - } - - public String getUnboxedPropertyTypeName() { - JType propertyType = getPropertyType(); - JPrimitiveType primitive = propertyType.isPrimitive(); - if (primitive != null) { - return primitive.getQualifiedBoxedSourceName(); - } else { - return propertyType.getQualifiedSourceName(); - } - } - - public JClassType getBeanType() { - return beanType; - } - - public abstract void writeSetterBody(TreeLogger logger, SourceWriter w, - String beanVariable, String valueVariable); - - public abstract void writeGetterBody(TreeLogger logger, SourceWriter w, - String beanVariable); - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } else if (obj instanceof Property) { - Property other = (Property) obj; - return other.getClass() == getClass() - && other.getBeanType().equals(getBeanType()) - && other.getName().equals(getName()); - } else { - return false; - } - } - - @Override - public int hashCode() { - return getClass().hashCode() * 31 ^ 2 + getBeanType().hashCode() * 31 - + getName().hashCode(); - } - - public abstract T getAnnotation( - Class annotationClass); - -} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ServerRpcVisitor.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ServerRpcVisitor.java deleted file mode 100644 index 4c0fc94500..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ServerRpcVisitor.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2011 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.terminal.gwt.widgetsetutils.metadata; - -import java.util.Set; - -import com.google.gwt.core.ext.TreeLogger; -import com.google.gwt.core.ext.typeinfo.JClassType; -import com.google.gwt.core.ext.typeinfo.JMethod; -import com.google.gwt.core.ext.typeinfo.JType; - -public class ServerRpcVisitor extends TypeVisitor { - @Override - public void visitServerRpc(TreeLogger logger, JClassType type, - ConnectorBundle bundle) { - bundle.setNeedsProxySupport(type); - - Set superTypes = type - .getFlattenedSupertypeHierarchy(); - for (JClassType subType : superTypes) { - if (subType.isInterface() != null) { - JMethod[] methods = subType.getMethods(); - for (JMethod method : methods) { - bundle.setNeedsDelayedInfo(type, method); - - JType[] parameterTypes = method.getParameterTypes(); - for (JType paramType : parameterTypes) { - bundle.setNeedsSerialize(paramType); - } - } - } - } - } -} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/StateInitVisitor.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/StateInitVisitor.java deleted file mode 100644 index 49cf687412..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/StateInitVisitor.java +++ /dev/null @@ -1,25 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.terminal.gwt.widgetsetutils.metadata; - -import com.google.gwt.core.ext.TreeLogger; -import com.google.gwt.core.ext.typeinfo.JClassType; -import com.google.gwt.core.ext.typeinfo.JMethod; -import com.google.gwt.core.ext.typeinfo.JType; - -public class StateInitVisitor extends TypeVisitor { - @Override - public void visitConnector(TreeLogger logger, JClassType type, - ConnectorBundle bundle) { - JMethod getState = findInheritedMethod(type, "getState"); - bundle.setNeedsReturnType(type, getState); - - bundle.setNeedsSerialize(getState.getReturnType()); - - JType stateType = getState.getReturnType(); - bundle.setNeedsGwtConstructor(stateType.isClass()); - } - -} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/TypeVisitor.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/TypeVisitor.java deleted file mode 100644 index cda849f564..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/TypeVisitor.java +++ /dev/null @@ -1,58 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.terminal.gwt.widgetsetutils.metadata; - -import com.google.gwt.core.ext.TreeLogger; -import com.google.gwt.core.ext.UnableToCompleteException; -import com.google.gwt.core.ext.typeinfo.JClassType; -import com.google.gwt.core.ext.typeinfo.JMethod; -import com.google.gwt.core.ext.typeinfo.JType; -import com.google.gwt.core.ext.typeinfo.NotFoundException; -import com.google.gwt.core.ext.typeinfo.TypeOracle; - -public abstract class TypeVisitor { - public void init(TypeOracle oracle) throws NotFoundException { - // Default does nothing - } - - public void visitConnector(TreeLogger logger, JClassType type, - ConnectorBundle bundle) throws UnableToCompleteException { - // Default does nothing - } - - public void visitClientRpc(TreeLogger logger, JClassType type, - ConnectorBundle bundle) { - // Default does nothing - } - - public void visitServerRpc(TreeLogger logger, JClassType type, - ConnectorBundle bundle) { - // Default does nothing - } - - protected JMethod findInheritedMethod(JClassType type, String methodName, - JType... params) { - - JClassType currentType = type; - while (currentType != null) { - JMethod method = currentType.findMethod(methodName, params); - if (method != null) { - return method; - } - currentType = currentType.getSuperclass(); - } - - JClassType[] interfaces = type.getImplementedInterfaces(); - for (JClassType iface : interfaces) { - JMethod method = iface.findMethod(methodName, params); - if (method != null) { - return method; - } - } - - return null; - } - -} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/WidgetInitVisitor.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/WidgetInitVisitor.java deleted file mode 100644 index 9df295c741..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/WidgetInitVisitor.java +++ /dev/null @@ -1,73 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.terminal.gwt.widgetsetutils.metadata; - -import java.util.Collection; - -import com.google.gwt.core.ext.TreeLogger; -import com.google.gwt.core.ext.TreeLogger.Type; -import com.google.gwt.core.ext.UnableToCompleteException; -import com.google.gwt.core.ext.typeinfo.JClassType; -import com.google.gwt.core.ext.typeinfo.JMethod; -import com.vaadin.client.ui.AbstractComponentConnector; -import com.vaadin.shared.annotations.DelegateToWidget; - -public class WidgetInitVisitor extends TypeVisitor { - - @Override - public void visitConnector(TreeLogger logger, JClassType type, - ConnectorBundle bundle) throws UnableToCompleteException { - if (ConnectorBundle.isConnectedComponentConnector(type)) { - JClassType createWidgetClass = findInheritedMethod(type, - "createWidget").getEnclosingType(); - boolean createWidgetOverridden = !createWidgetClass - .getQualifiedSourceName() - .equals(AbstractComponentConnector.class.getCanonicalName()); - if (createWidgetOverridden) { - // Don't generate if createWidget is already overridden - return; - } - - JMethod getWidget = findInheritedMethod(type, "getWidget"); - bundle.setNeedsReturnType(type, getWidget); - - JClassType widgetType = getWidget.getReturnType().isClass(); - bundle.setNeedsGwtConstructor(widgetType); - - JMethod getState = findInheritedMethod(type, "getState"); - JClassType stateType = getState.getReturnType().isClass(); - - Collection properties = bundle.getProperties(stateType); - for (Property property : properties) { - DelegateToWidget delegateToWidget = property - .getAnnotation(DelegateToWidget.class); - if (delegateToWidget != null) { - bundle.setNeedsDelegateToWidget(property); - String methodName = DelegateToWidget.Helper - .getDelegateTarget(property.getName(), - delegateToWidget.value()); - JMethod delegatedSetter = findInheritedMethod(widgetType, - methodName, property.getPropertyType()); - if (delegatedSetter == null) { - logger.log( - Type.ERROR, - widgetType.getName() - + "." - + methodName - + "(" - + property.getPropertyType() - .getSimpleSourceName() - + ") required by @DelegateToWidget for " - + stateType.getName() + "." - + property.getName() - + " can not be found."); - throw new UnableToCompleteException(); - } - bundle.setNeedsInvoker(widgetType, delegatedSetter); - } - } - } - } -} diff --git a/client-compiler/src/com/vaadin/tools/WidgetsetCompiler.java b/client-compiler/src/com/vaadin/tools/WidgetsetCompiler.java index 7e06dfc205..4de6847012 100755 --- a/client-compiler/src/com/vaadin/tools/WidgetsetCompiler.java +++ b/client-compiler/src/com/vaadin/tools/WidgetsetCompiler.java @@ -19,7 +19,7 @@ import java.lang.reflect.Method; import java.util.logging.Level; import java.util.logging.Logger; -import com.vaadin.terminal.gwt.widgetsetutils.WidgetSetBuilder; +import com.vaadin.server.widgetsetutils.WidgetSetBuilder; /** * A wrapper for the GWT 1.6 compiler that runs the compiler in a new thread. diff --git a/client/src/com/vaadin/Vaadin.gwt.xml b/client/src/com/vaadin/Vaadin.gwt.xml index 3e0f47f16d..cb6581f70e 100644 --- a/client/src/com/vaadin/Vaadin.gwt.xml +++ b/client/src/com/vaadin/Vaadin.gwt.xml @@ -35,7 +35,7 @@ + com.vaadin.server.widgetsetutils.ConnectorBundleLoaderFactory "> diff --git a/client/src/com/vaadin/client/ui/dd/VAcceptCriterionFactory.java b/client/src/com/vaadin/client/ui/dd/VAcceptCriterionFactory.java index 2141103a84..dee006805b 100644 --- a/client/src/com/vaadin/client/ui/dd/VAcceptCriterionFactory.java +++ b/client/src/com/vaadin/client/ui/dd/VAcceptCriterionFactory.java @@ -17,7 +17,7 @@ package com.vaadin.client.ui.dd; /** * Generated by - * {@link com.vaadin.terminal.gwt.widgetsetutils.AcceptCriteriaFactoryGenerator} + * {@link com.vaadin.server.widgetsetutils.AcceptCriteriaFactoryGenerator} */ public abstract class VAcceptCriterionFactory { diff --git a/shared/src/com/vaadin/shared/ui/Connect.java b/shared/src/com/vaadin/shared/ui/Connect.java index 7756eef890..17171ec843 100644 --- a/shared/src/com/vaadin/shared/ui/Connect.java +++ b/shared/src/com/vaadin/shared/ui/Connect.java @@ -46,9 +46,9 @@ public @interface Connect { * Depending on the used WidgetMap generator, these optional hints may be * used to define how the client side components are loaded by the browser. * The default is to eagerly load all widgets - * {@link com.vaadin.terminal.gwt.widgetsetutils.EagerWidgetMapGenerator}, + * {@link com.vaadin.server.widgetsetutils.EagerWidgetMapGenerator}, * but if the - * {@link com.vaadin.terminal.gwt.widgetsetutils.WidgetMapGenerator} is used + * {@link com.vaadin.server.widgetsetutils.WidgetMapGenerator} is used * by the widgetset, these load style hints are respected. *

* Lazy loading of a widget implementation means the client side component @@ -69,14 +69,14 @@ public @interface Connect { * the best of both worlds. *

* Fine tunings to widget loading can also be made by overriding - * {@link com.vaadin.terminal.gwt.widgetsetutils.WidgetMapGenerator} in the + * {@link com.vaadin.server.widgetsetutils.WidgetMapGenerator} in the * GWT module. Tunings might be helpful if the end users have slow * connections and especially if they have high latency in their network. * The - * {@link com.vaadin.terminal.gwt.widgetsetutils.CustomWidgetMapGenerator} + * {@link com.vaadin.server.widgetsetutils.CustomWidgetMapGenerator} * is an abstract generator implementation for easy customization. Vaadin * package also includes - * {@link com.vaadin.terminal.gwt.widgetsetutils.LazyWidgetMapGenerator} + * {@link com.vaadin.server.widgetsetutils.LazyWidgetMapGenerator} * that makes as many widgets lazily loaded as possible. * * @since 6.4 diff --git a/tests/server-side/com/vaadin/data/util/AbstractContainerTest.java b/tests/server-side/com/vaadin/data/util/AbstractContainerTest.java index ca5c344b2e..b0151a6690 100644 --- a/tests/server-side/com/vaadin/data/util/AbstractContainerTest.java +++ b/tests/server-side/com/vaadin/data/util/AbstractContainerTest.java @@ -598,9 +598,9 @@ public abstract class AbstractContainerTest extends TestCase { "com.vaadin.server.SystemMessageException", "com.vaadin.server.WebApplicationContext", "com.vaadin.server.WebBrowser", - "com.vaadin.terminal.gwt.widgetsetutils.ClassPathExplorer", - "com.vaadin.terminal.gwt.widgetsetutils.WidgetMapGenerator", - "com.vaadin.terminal.gwt.widgetsetutils.WidgetSetBuilder", + "com.vaadin.server.widgetsetutils.ClassPathExplorer", + "com.vaadin.server.widgetsetutils.WidgetMapGenerator", + "com.vaadin.server.widgetsetutils.WidgetSetBuilder", "com.vaadin.server.KeyMapper", "com.vaadin.server.Paintable", "com.vaadin.server.PaintException", "com.vaadin.server.PaintTarget", -- cgit v1.2.3