package org.tessell.generators.resources; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.Writer; import java.net.URL; import java.net.URLDecoder; import java.util.Arrays; import java.util.Set; import org.apache.tapestry.util.text.LocalizedProperties; import com.google.gwt.dev.util.Util; import com.google.gwt.dev.util.log.PrintWriterTreeLogger; import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; import com.google.gwt.user.rebind.SourceWriter; /** * Generates stub implementations of Messages interfaces. * * Should this use the default values of the messages instead of just the key name? */ public class MessagesStubGenerator { public static void main(final String[] args) throws Exception { // this is horribly hard-coded, but works for us final String sourceDir = args[0]; final String fullName = args[1]; final File resourceBundle = urlToResourceFile(fullName); final int lastDot = fullName.lastIndexOf("."); final String packageName = fullName.substring(0, lastDot); final String simpleName = fullName.substring(lastDot + 1); final File sourcePath = new File(new File(sourceDir).getCanonicalFile() + File.separator + packageName.replace('.', File.separatorChar) + File.separator + "Stub" + simpleName + ".java"); new MessagesStubGenerator(simpleName, "Stub" + simpleName, packageName, resourceBundle, sourcePath).generate(); } private final File resourceBundle; private final SourceWriter composer; public MessagesStubGenerator( final String className, final String stubName, final String packageName, final File resourceBundle, final File targetLocation) throws IOException { this.resourceBundle = resourceBundle; final ClassSourceFileComposerFactory factory = new ClassSourceFileComposerFactory(packageName, stubName); factory.addImplementedInterface(packageName + "." + className); final FileOutputStream file = new FileOutputStream(targetLocation); final Writer underlying = new OutputStreamWriter(file, Util.DEFAULT_ENCODING); composer = factory.createSourceWriter(new PrintWriter(underlying)); } @SuppressWarnings("unchecked") public void generate() throws IOException { final InputStream propStream = new FileInputStream(resourceBundle); final LocalizedProperties p = new LocalizedProperties(); p.load(propStream, Util.DEFAULT_ENCODING); // sort keys for deterministic results final Set<String> keySet = p.getPropertyMap().keySet(); final String[] keys = keySet.toArray(new String[keySet.size()]); Arrays.sort(keys); for (final String key : keys) { final String value = p.getProperty(key); // not doing dup/replace detection because they are private in the super class addMethod(key, value); } composer.commit(new PrintWriterTreeLogger()); } public void addMethod(final String key, final String defaultValue) { composer.indent(); composer.println("public String " + key + "() {"); composer.indentln("return \"" + key + "\";"); composer.println("}"); composer.outdent(); composer.println(); } // copy/paste from GWT private static File urlToResourceFile(final String className) throws IOException { if (className.endsWith(".java") || className.endsWith(".properties") || className.endsWith(".class") || className.indexOf(File.separator) > 0) { throw new IllegalArgumentException("class '" + className + "'should not contain an extension. \"com.google.gwt.SomeClass\" is an example of a correctly formed class string"); } final String resourcePath = className.replace('.', '/') + ".properties"; ClassLoader cl = Thread.currentThread().getContextClassLoader(); if (cl == null) { cl = ClassLoader.getSystemClassLoader(); } final URL r = cl.getResource(resourcePath); if (r == null) { throw new FileNotFoundException("Could not find the resource '" + resourcePath + " matching '" + className + "' did you remember to add it to your classpath?"); } final File resourceFile = new File(URLDecoder.decode(r.getPath(), "utf-8")); return resourceFile; } }