| /******************************************************************************* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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 org.apache.sling.scripting.sightly.java.compiler; |
| |
| import java.io.IOException; |
| import java.util.Map; |
| |
| import org.apache.commons.io.IOUtils; |
| import org.apache.sling.scripting.sightly.compiler.backend.BackendCompiler; |
| import org.apache.sling.scripting.sightly.compiler.commands.CommandStream; |
| import org.apache.sling.scripting.sightly.compiler.commands.StatefulVisitor; |
| import org.apache.sling.scripting.sightly.java.compiler.impl.CodeGenVisitor; |
| import org.apache.sling.scripting.sightly.java.compiler.impl.CommandVisitorHandler; |
| import org.apache.sling.scripting.sightly.java.compiler.impl.JavaClassTemplate; |
| import org.apache.sling.scripting.sightly.java.compiler.impl.UnitBuilder; |
| |
| /** |
| * {@link BackendCompiler} that generates a Java class. |
| */ |
| public final class JavaClassBackendCompiler implements BackendCompiler { |
| |
| private static final String COMPILED_UNIT_TEMPLATE = "templates/compiled_unit_template.txt"; |
| private static final String SUBTEMPLATE = "templates/subtemplate.txt"; |
| private static final String mainTemplate; |
| private static final String childTemplate; |
| |
| private UnitBuilder unitBuilder; |
| private final JavaImportsAnalyzer JAVA_IMPORTS_ANALYZER; |
| |
| static { |
| try { |
| mainTemplate = IOUtils |
| .toString(JavaClassTemplate.class.getClassLoader().getResourceAsStream(COMPILED_UNIT_TEMPLATE), "UTF-8"); |
| childTemplate = IOUtils.toString(JavaClassTemplate.class.getClassLoader().getResourceAsStream(SUBTEMPLATE), "UTF-8"); |
| } catch (IOException e) { |
| throw new IllegalStateException(e); |
| } |
| } |
| |
| public JavaClassBackendCompiler() { |
| this(new JavaImportsAnalyzer() {}); |
| } |
| |
| public JavaClassBackendCompiler(JavaImportsAnalyzer javaImportsAnalyzer) { |
| JAVA_IMPORTS_ANALYZER = javaImportsAnalyzer; |
| unitBuilder = new UnitBuilder(JAVA_IMPORTS_ANALYZER); |
| } |
| |
| @Override |
| public void handle(CommandStream stream) { |
| StatefulVisitor statefulVisitor = new StatefulVisitor(); |
| final CodeGenVisitor visitor = new CodeGenVisitor(unitBuilder, statefulVisitor.getControl()); |
| statefulVisitor.initializeWith(visitor); |
| stream.addHandler(new CommandVisitorHandler(statefulVisitor) { |
| @Override |
| public void onDone() { |
| super.onDone(); |
| visitor.finish(); |
| } |
| }); |
| } |
| |
| /** |
| * Provided the class information, this method will build the source code for the generated Java class. |
| * |
| * @param classInfo the class information |
| * @return the generated Java class' source code |
| */ |
| public String build(ClassInfo classInfo) { |
| CompilationOutput compilationOutput = unitBuilder.build(); |
| JavaClassTemplate mainTemplate = newMainTemplate(); |
| mainTemplate.setPackageName(classInfo.getPackageName()); |
| mainTemplate.setClassName(classInfo.getSimpleClassName()); |
| StringBuilder imports = new StringBuilder(); |
| for (String importClass : unitBuilder.getImports()) { |
| if (JAVA_IMPORTS_ANALYZER.allowImport(importClass)) { |
| imports.append("import ").append(importClass).append(";").append(System.lineSeparator()); |
| } |
| } |
| mainTemplate.setImports(imports.toString()); |
| processCompilationResult(compilationOutput, mainTemplate); |
| return mainTemplate.toString(); |
| } |
| |
| private void processCompilationResult(CompilationOutput result, JavaClassTemplate mainTemplate) { |
| mainTemplate.writeMainBody(result.getMainBody()); |
| for (Map.Entry<String, CompilationOutput> entry : result.getSubTemplates().entrySet()) { |
| JavaClassTemplate childTemplate = newChildTemplate(); |
| processCompilationResult(entry.getValue(), childTemplate); |
| mainTemplate.writeSubTemplate(entry.getKey(), childTemplate.toString()); |
| } |
| } |
| |
| private JavaClassTemplate newMainTemplate() { |
| return new JavaClassTemplate(mainTemplate); |
| } |
| |
| private JavaClassTemplate newChildTemplate() { |
| return new JavaClassTemplate(childTemplate); |
| } |
| } |