org.mozilla.javascript.optimizer.ClassCompiler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aem-sdk-api Show documentation
Show all versions of aem-sdk-api Show documentation
The Adobe Experience Manager SDK
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.javascript.optimizer;
import org.mozilla.javascript.*;
import org.mozilla.javascript.ast.AstRoot;
import org.mozilla.javascript.ast.FunctionNode;
import org.mozilla.javascript.ast.ScriptNode;
/**
* Generates class files from script sources.
*
* since 1.5 Release 5
* @author Igor Bukanov
*/
public class ClassCompiler
{
/**
* Construct ClassCompiler that uses the specified compiler environment
* when generating classes.
*/
public ClassCompiler(CompilerEnvirons compilerEnv)
{
if (compilerEnv == null) throw new IllegalArgumentException();
this.compilerEnv = compilerEnv;
this.mainMethodClassName = Codegen.DEFAULT_MAIN_METHOD_CLASS;
}
/**
* Set the class name to use for main method implementation.
* The class must have a method matching
* public static void main(Script sc, String[] args), it will be
* called when main(String[] args) is called in the generated
* class. The class name should be fully qulified name and include the
* package name like in org.foo.Bar.
*/
public void setMainMethodClass(String className)
{
// XXX Should this check for a valid class name?
mainMethodClassName = className;
}
/**
* Get the name of the class for main method implementation.
* @see #setMainMethodClass(String)
*/
public String getMainMethodClass()
{
return mainMethodClassName;
}
/**
* Get the compiler environment the compiler uses.
*/
public CompilerEnvirons getCompilerEnv()
{
return compilerEnv;
}
/**
* Get the class that the generated target will extend.
*/
public Class> getTargetExtends()
{
return targetExtends;
}
/**
* Set the class that the generated target will extend.
*
* @param extendsClass the class it extends
*/
public void setTargetExtends(Class> extendsClass)
{
targetExtends = extendsClass;
}
/**
* Get the interfaces that the generated target will implement.
*/
public Class>[] getTargetImplements()
{
return targetImplements == null ? null : (Class[])targetImplements.clone();
}
/**
* Set the interfaces that the generated target will implement.
*
* @param implementsClasses an array of Class objects, one for each
* interface the target will extend
*/
public void setTargetImplements(Class>[] implementsClasses)
{
targetImplements = implementsClasses == null ? null : (Class[])implementsClasses.clone();
}
/**
* Build class name for a auxiliary class generated by compiler.
* If the compiler needs to generate extra classes beyond the main class,
* it will call this function to build the auxiliary class name.
* The default implementation simply appends auxMarker to mainClassName
* but this can be overridden.
*/
protected String makeAuxiliaryClassName(String mainClassName,
String auxMarker)
{
return mainClassName+auxMarker;
}
/**
* Compile JavaScript source into one or more Java class files.
* The first compiled class will have name mainClassName.
* If the results of {@link #getTargetExtends()} or
* {@link #getTargetImplements()} are not null, then the first compiled
* class will extend the specified super class and implement
* specified interfaces.
*
* @return array where elements with even indexes specifies class name
* and the following odd index gives class file body as byte[]
* array. The initial element of the array always holds
* mainClassName and array[1] holds its byte code.
*/
public Object[] compileToClassFiles(String source,
String sourceLocation,
int lineno,
String mainClassName)
{
Parser p = new Parser(compilerEnv);
AstRoot ast = p.parse(source, sourceLocation, lineno);
IRFactory irf = new IRFactory(compilerEnv);
ScriptNode tree = irf.transformTree(ast);
// release reference to original parse tree & parser
irf = null;
ast = null;
p = null;
Class> superClass = getTargetExtends();
Class>[] interfaces = getTargetImplements();
String scriptClassName;
boolean isPrimary = (interfaces == null && superClass == null);
if (isPrimary) {
scriptClassName = mainClassName;
} else {
scriptClassName = makeAuxiliaryClassName(mainClassName, "1");
}
Codegen codegen = new Codegen();
codegen.setMainMethodClass(mainMethodClassName);
byte[] scriptClassBytes
= codegen.compileToClassFile(compilerEnv, scriptClassName,
tree, tree.getEncodedSource(),
false);
if (isPrimary) {
return new Object[] { scriptClassName, scriptClassBytes };
}
int functionCount = tree.getFunctionCount();
ObjToIntMap functionNames = new ObjToIntMap(functionCount);
for (int i = 0; i != functionCount; ++i) {
FunctionNode ofn = tree.getFunctionNode(i);
String name = ofn.getName();
if (name != null && name.length() != 0) {
functionNames.put(name, ofn.getParamCount());
}
}
if (superClass == null) {
superClass = ScriptRuntime.ObjectClass;
}
byte[] mainClassBytes
= JavaAdapter.createAdapterCode(
functionNames, mainClassName,
superClass, interfaces, scriptClassName);
return new Object[] { mainClassName, mainClassBytes,
scriptClassName, scriptClassBytes };
}
private String mainMethodClassName;
private CompilerEnvirons compilerEnv;
private Class> targetExtends;
private Class>[] targetImplements;
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy