/********************************************** * Copyright (C) 2009 Lukas Laag * This file is part of lib-gwt-svg-samples. * * libgwtsvg-samples is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * libgwtsvg-samples is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with libgwtsvg-samples. If not, see http://www.gnu.org/licenses/ **********************************************/ package org.vectomatic.svg.samples.generator; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import org.apache.tools.ant.filters.StringInputStream; import org.vectomatic.svg.samples.client.SampleBase; 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.UnableToCompleteException; import com.google.gwt.core.ext.typeinfo.JClassType; import com.google.gwt.core.ext.typeinfo.NotFoundException; import com.uwyn.jhighlight.renderer.Renderer; import com.uwyn.jhighlight.renderer.XhtmlRendererFactory; public class SourceGenerator extends Generator { /** * The class loader used to get resources. */ private ClassLoader classLoader = null; /** * The generator context. */ private GeneratorContext context = null; /** * The {@link TreeLogger} used to log messages. */ private TreeLogger logger = null; @Override public String generate(TreeLogger logger, GeneratorContext context, String typeName) throws UnableToCompleteException { this.logger = logger; this.context = context; this.classLoader = Thread.currentThread().getContextClassLoader(); // Only generate files on the first permutation if (!isFirstPass()) { return null; } JClassType sampleClass = null; try { sampleClass = context.getTypeOracle().getType( SampleBase.class.getName()); } catch (NotFoundException e) { logger.log(TreeLogger.ERROR, "Cannot find SampleBase class", e); throw new UnableToCompleteException(); } JClassType[] types = sampleClass.getSubtypes(); // Generate the source and raw source files for (JClassType type : types) { generateSourceFile(type); generateUiBinderFile(type); } return null; } private void generateSourceFile(JClassType type) throws UnableToCompleteException { Renderer javaRenderer = XhtmlRendererFactory.getRenderer(XhtmlRendererFactory.JAVA); String filename = type.getQualifiedSourceName().replace('.', '/') + ".java"; ByteArrayOutputStream byteArrayStream = null; InputStream javaStream = null; try { javaStream = new StringInputStream(getResourceContents(filename)); byteArrayStream = new ByteArrayOutputStream(); javaRenderer.highlight(null, javaStream, byteArrayStream, "UTF-8", true); javaStream.close(); byteArrayStream.close(); // Save the source code to a file String dstPath = SampleBase.HTML_SRC_DIR + type.getSimpleSourceName() + ".html"; String contents = new String(byteArrayStream.toByteArray(), "UTF-8"); createPublicResource(dstPath, contents); } catch (IOException e) { throw new RuntimeException(e); } } private void generateUiBinderFile(JClassType type) throws UnableToCompleteException { Renderer javaRenderer = XhtmlRendererFactory.getRenderer(XhtmlRendererFactory.XML); String filename = type.getQualifiedSourceName().replace('.', '/') + ".ui.xml"; ByteArrayOutputStream byteArrayStream = null; InputStream javaStream = null; try { javaStream = new StringInputStream(getResourceContents(filename)); byteArrayStream = new ByteArrayOutputStream(); javaRenderer.highlight(null, javaStream, byteArrayStream, "UTF-8", true); javaStream.close(); byteArrayStream.close(); // Save the source code to a file String dstPath = SampleBase.UIBINDER_SRC_DIR + type.getSimpleSourceName() + ".html"; String contents = new String(byteArrayStream.toByteArray(), "UTF-8"); createPublicResource(dstPath, contents); } catch (IOException e) { throw new RuntimeException(e); } } /** * Set the full contents of a resource in the public directory. * @param partialPath * the path to the file relative to the public directory * @param contents * the file contents */ private void createPublicResource(String partialPath, String contents) { try { logger.log(TreeLogger.INFO, "Generating " + partialPath); OutputStream outStream = context.tryCreateResource(logger, partialPath); outStream.write(contents.getBytes()); context.commitResource(logger, outStream); } catch (UnableToCompleteException e) { logger.log(TreeLogger.ERROR, "Failed while writing", e); } catch (IOException e) { logger.log(TreeLogger.ERROR, "Failed while writing", e); } } /** * Get the full contents of a resource. * @param path the path to the resource * @return the contents of the resource */ private String getResourceContents(String path) throws UnableToCompleteException { InputStream in = classLoader.getResourceAsStream(path); if (in == null) { logger.log(TreeLogger.ERROR, "Resource not found: " + path); throw new UnableToCompleteException(); } StringBuffer fileContentsBuf = new StringBuffer(); BufferedReader br = null; try { br = new BufferedReader(new InputStreamReader(in)); String temp; while ((temp = br.readLine()) != null) { fileContentsBuf.append(temp).append('\n'); } } catch (IOException e) { logger.log(TreeLogger.ERROR, "Cannot read resource", e); throw new UnableToCompleteException(); } finally { if (br != null) { try { br.close(); } catch (IOException e) { } } } // Return the file contents as a string return fileContentsBuf.toString(); } /** * Ensure that we only generate files once by creating a placeholder file, * then looking for it on subsequent generates. * * @return true if this is the first pass, false if not */ private boolean isFirstPass() { String placeholder = SampleBase.HTML_SRC_DIR + "generated"; try { OutputStream outStream = context.tryCreateResource(logger, placeholder); if (outStream == null) { return false; } else { context.commitResource(logger, outStream); } } catch (UnableToCompleteException e) { logger.log(TreeLogger.ERROR, "Unable to generate", e); return false; } return true; } }