/* * Copyright 2013 eXo Platform SAS * * 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 juzu.impl.plugin.template.metamodel; import juzu.impl.common.FileKey; import juzu.impl.compiler.BaseProcessor; import juzu.impl.template.spi.EmitContext; import juzu.impl.template.spi.TemplateProvider; import juzu.impl.common.Logger; import juzu.impl.common.Path; import juzu.impl.common.Tools; import juzu.template.TagHandler; import javax.lang.model.element.Element; import javax.tools.FileObject; import javax.tools.StandardLocation; import java.io.IOException; import java.io.Serializable; import java.io.Writer; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.Callable; /** * The template emitter. * * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */ abstract class AbstractEmitter implements Serializable { /** . */ private static final Logger log = BaseProcessor.getLogger(AbstractEmitter.class); /** . */ final AbstractContainerMetaModel owner; /** . */ private Set<Path.Absolute> emitted; /** . */ private Map<Path.Absolute, FileObject> classCache; AbstractEmitter(AbstractContainerMetaModel owner) { this.owner = owner; this.emitted = new HashSet<Path.Absolute>(); this.classCache = new HashMap<Path.Absolute, FileObject>(); } void prePassivate() { log.info("Evicting cache " + emitted); emitted.clear(); classCache.clear(); } void emit(TemplateMetaModel template, Element[] elements) { TemplateProvider<?> provider = owner.resolveTemplateProvider(template.getPath().getExt()); resolvedQualified(provider, template, elements); emitScript(template, provider, elements); } private void emitScript(final TemplateMetaModel template, final TemplateProvider provider, final Element[] elements) { owner.application.getProcessingContext().executeWithin(elements[0], new Callable<Void>() { public Void call() throws Exception { // Path.Absolute path = template.getPath(); // If it's the cache we do nothing if (!emitted.contains(path)) { // try { EmitContext emitCtx = new EmitContext() { @Override public TagHandler resolveTagHandler(String name) { return owner.resolveTagHandler(name); } @Override public void createResource(Path.Absolute path, CharSequence content) throws IOException { FileKey key = FileKey.newName(path); FileObject scriptFile = owner.application.getProcessingContext().createResource(StandardLocation.CLASS_OUTPUT, key, elements); Writer writer = null; try { writer = scriptFile.openWriter(); writer.append(content); log.info("Generated template script " + path.getCanonical() + " as " + scriptFile.toUri() + " with originating elements " + Arrays.asList(elements)); } finally { Tools.safeClose(writer); } } }; // provider.emit(emitCtx, template.templateModel); // Put it in cache emitted.add(path); } catch (Exception e) { throw TemplateMetaModel.CANNOT_WRITE_TEMPLATE_SCRIPT.failure(e, template.getPath()); } } else { log.info("Template " + template.getPath() + " was found in cache"); } return null; } }); } protected abstract void emitClass( TemplateProvider<?> provider, TemplateMetaModel template, Element[] elements, Writer writer) throws IOException; private void resolvedQualified( TemplateProvider<?> provider, TemplateMetaModel template, Element[] elements) { // Path.Absolute path = template.getPath(); if (classCache.containsKey(path)) { log.info("Template class " + path + " was found in cache"); } else { Path.Absolute resolvedPath = owner.resolvePath(path); Writer writer = null; try { FileObject classFile = owner.application.getProcessingContext().createSourceFile(resolvedPath.getName(), elements); writer = classFile.openWriter(); emitClass(provider, template, elements, writer); classCache.put(path, classFile); log.info("Generated template class " + path + " as " + classFile.toUri() + " with originating elements " + Arrays.asList(elements)); } catch (IOException e) { e.printStackTrace(); throw TemplateMetaModel.CANNOT_WRITE_TEMPLATE_CLASS.failure(e, elements[0], path); } finally { Tools.safeClose(writer); } } } }