/* * (c) Copyright 2010-2011 AgileBirds * * This file is part of OpenFlexo. * * OpenFlexo 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. * * OpenFlexo 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 OpenFlexo. If not, see <http://www.gnu.org/licenses/>. * */ package org.openflexo.velocity; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import org.apache.commons.collections.ExtendedProperties; import org.apache.velocity.exception.ResourceNotFoundException; import org.apache.velocity.runtime.resource.Resource; import org.apache.velocity.runtime.resource.loader.ResourceLoader; import org.openflexo.foundation.cg.templates.CGTemplate; import org.openflexo.generator.TemplateLocator; import org.openflexo.generator.exception.TemplateNotFoundException; public class FlexoTemplateResourceLoader extends ResourceLoader { private class _InputStream extends InputStream { int pushBack = -1; boolean newLine = true; InputStream is; public _InputStream(InputStream wrappedStream) { this.is = new BufferedInputStream(wrappedStream); } @Override public int read() throws IOException { if (newLine) { newLine = false; // We mark the input stream is.mark(Integer.MAX_VALUE); int c = is.read(); // We skip all the white characters (tab, newlines, spaces, ...) while (Character.isWhitespace(c)) { c = is.read(); } // If we have a '#' sign, then we return it if (c == '#') { return c; } else { // Else we reset the input stream and let the normal flow take over is.reset(); } } int c = pushBack; if (c != -1) { pushBack = -1; } else { c = is.read(); } switch (c) { case '\r': // OK, we got a '\r', so let's see ahead if we don't find a '\n' pushBack = is.read(); if (pushBack == '\n') { // 1. We have found the expected '\n', so we return it (because in Flexo '\r' are not handled in memory) pushBack = -1; }// 2. We haven't found the expected '\n', and so we will still return a '\n' this time but the next time we are called we // will return the char we just read. newLine = true; return '\n'; case '\n': newLine = true; return '\n'; } return c; } @Override public void close() throws IOException { super.close(); if (is != null) { is.close(); } } } private TemplateLocator getTemplateLocator() throws ResourceNotFoundException { TemplateLocator locator = (TemplateLocator) rsvc.getApplicationAttribute("templateLocator"); if (locator == null) { throw new ResourceNotFoundException("Template locator not initialized for FlexoTemplateResourceLoader !"); } return locator; } private CGTemplate getTemplate(String name) throws ResourceNotFoundException { try { return getTemplateLocator().templateWithName(name); } catch (TemplateNotFoundException e) { throw new ResourceNotFoundException(e); } } /** * {@inheritDoc} */ @Override public long getLastModified(Resource paramResource) { CGTemplate template = getTemplate(paramResource.getName()); if (paramResource instanceof FlexoTemplate && ((FlexoTemplate) paramResource).getSize() < 0) { ((FlexoTemplate) paramResource).setSize(template.getContent().length()); } return template.getLastUpdate().getTime(); } /** * {@inheritDoc} */ @Override public void init(ExtendedProperties paramExtendedProperties) { } /** * {@inheritDoc} */ @Override public boolean isSourceModified(Resource paramResource) { boolean modified = getLastModified(paramResource) != paramResource.getLastModified(); if (modified) { return true; } if (paramResource instanceof FlexoTemplate) { return ((FlexoTemplate) paramResource).getSize() != getTemplate(paramResource.getName()).getContent().length(); } return modified; } @Override public InputStream getResourceStream(String templateName) throws ResourceNotFoundException { CGTemplate template = getTemplate(templateName); try { return new _InputStream(new ByteArrayInputStream(template.getContent().toString().getBytes("UTF-8"))); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } }