Deprecating ClassOutput in favor of ClassRepository and Context methods to access ClassNameHelper functionality in favor of directly calling ClassNameHelper methods. For that I changed ClassNameHelper from interface to abstract class and added ClassNameHelper.get(Context cx) method to get name helper object that is used for the given Context object.

This commit is contained in:
igor%mir2.org 2002-12-31 18:21:32 +00:00
parent 884cdf7250
commit b0dd32ca85
6 changed files with 331 additions and 253 deletions

View File

@ -38,23 +38,227 @@
package org.mozilla.javascript;
public interface ClassNameHelper {
import java.io.*;
public String getTargetPackage();
public abstract class ClassNameHelper {
public void setTargetPackage(String targetPackage);
public static ClassNameHelper get(Context cx) {
ClassNameHelper helper = savedNameHelper;
if (helper == null && !helperNotAvailable) {
try {
Class nameHelperClass = Class.forName(
"org.mozilla.javascript.optimizer.OptClassNameHelper");
helper = (ClassNameHelper)nameHelperClass.newInstance();
} catch (ClassNotFoundException x) {
// ...must be running lite, that's ok
} catch (IllegalAccessException x) {
} catch (InstantiationException x) {
}
if (helper != null) {
savedNameHelper = helper;
} else {
helperNotAvailable = true;
}
}
return helper;
}
public void setTargetExtends(Class extendsClass);
static void clearCache() {
ClassNameHelper helper = savedNameHelper;
if (helper != null) {
helper.reset();
}
}
public void setTargetImplements(Class[] implementsClasses);
/**
* Get the current target class file name.
* <p>
* If nonnull, requests to compile source will result in one or
* more class files being generated.
*
* @since 1.5 Release 4
*/
public String getTargetClassFileName() {
ClassRepository repository = getClassRepository();
if (repository instanceof FileClassRepository) {
return ((FileClassRepository)repository).
getTargetClassFileName(getClassName());
}
return null;
}
public ClassRepository getClassRepository();
/**
* Set the current target class file name.
* <p>
* If nonnull, requests to compile source will result in one or
* more class files being generated. If null, classes will only
* be generated in memory.
*
* @since 1.5 Release 4
*/
public void setTargetClassFileName(String classFileName) {
if (classFileName != null) {
setClassRepository(new FileClassRepository(classFileName));
} else {
setClassName(null);
}
}
public void setClassRepository(ClassRepository repository);
/**
* @deprecated Application should use {@link ClassRepository} instead of
* {@link ClassOutput}.
*
* @see #getClassRepository
*/
public final ClassOutput getClassOutput() {
ClassRepository repository = getClassRepository();
if (repository instanceof ClassOutputWrapper) {
return ((ClassOutputWrapper)repository).classOutput;
}
return null;
}
public String getClassName();
/**
* @deprecated Application should use {@link ClassRepository} instead of
* {@link ClassOutput}.
*
* @see #setClassRepository
*/
public void setClassOutput(ClassOutput classOutput) {
if (classOutput != null) {
setClassRepository(new ClassOutputWrapper(classOutput));
} else {
setClassRepository(null);
}
}
public void setClassName(String initialName);
/**
* Get the current package to generate classes into.
*/
public abstract String getTargetPackage();
public void reset();
/**
* Set the package to generate classes into.
*/
public abstract void setTargetPackage(String targetPackage);
/**
* Set the class that the generated target will extend.
*
* @param extendsClass the class it extends
*/
public abstract void setTargetExtends(Class extendsClass);
/**
* 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 abstract void setTargetImplements(Class[] implementsClasses);
/**
* Get the current class repository.
*
* @see ClassRepository
* @since 30/10/01 tip + patch (Kemal Bayram)
*/
public abstract ClassRepository getClassRepository();
/**
* Set the current class repository.
*
* @see ClassRepository
* @since 30/10/01 tip + patch (Kemal Bayram)
*/
public abstract void setClassRepository(ClassRepository repository);
/**
* Get the current class name.
*
* @since 30/10/01 tip + patch (Kemal Bayram)
*/
public abstract String getClassName();
/**
* Set the current class name.
*
* @since 30/10/01 tip + patch (Kemal Bayram)
*/
public abstract void setClassName(String initialName);
public abstract void reset();
// Implement class file saving here instead of inside codegen.
private class FileClassRepository implements ClassRepository {
FileClassRepository(String classFileName) {
int lastSeparator = classFileName.lastIndexOf(File.separatorChar);
String initialName;
if (lastSeparator == -1) {
generatingDirectory = null;
initialName = classFileName;
} else {
generatingDirectory = classFileName.substring(0, lastSeparator);
initialName = classFileName.substring(lastSeparator+1);
}
if (initialName.endsWith(".class"))
initialName = initialName.substring(0, initialName.length()-6);
setClassName(initialName);
}
public boolean storeClass(String className, byte[] bytes, boolean tl)
throws IOException
{
// no "elegant" way of getting file name from fully
// qualified class name.
String targetPackage = getTargetPackage();
if ((targetPackage != null) && (targetPackage.length()>0) &&
className.startsWith(targetPackage+"."))
{
className = className.substring(targetPackage.length()+1);
}
FileOutputStream out = new FileOutputStream(getTargetClassFileName(className));
out.write(bytes);
out.close();
return false;
}
String getTargetClassFileName(String className) {
StringBuffer sb = new StringBuffer();
if (generatingDirectory != null) {
sb.append(generatingDirectory);
sb.append(File.separator);
}
sb.append(className);
sb.append(".class");
return sb.toString();
}
String generatingDirectory;
};
private static class ClassOutputWrapper implements ClassRepository {
ClassOutputWrapper(ClassOutput classOutput) {
this.classOutput = classOutput;
}
public boolean storeClass(String name, byte[] bytes, boolean tl)
throws IOException
{
OutputStream out = classOutput.getOutputStream(name, tl);
out.write(bytes);
out.close();
return true;
}
ClassOutput classOutput;
}
private static ClassNameHelper savedNameHelper;
private static boolean helperNotAvailable;
}

View File

@ -39,18 +39,13 @@ package org.mozilla.javascript;
import java.io.*;
/**
* This interface is implemented by classes interested in the bytecode
* generated by the rhino compiler for script objects.
*
* @see Context
* @author Andi Vajda
* @deprecated To store generated bytecode implement {@link ClassRepository}
* instead.
*/
public interface ClassOutput {
public interface ClassOutput {
/**
* @param className the name of the class for which bytecode is ready.
* @param isTopLevel if true, represents the top-level script being compiled
* @return a stream into which to write bytecode.
* @since 1.5 Release 2
* @deprecated
* @see ClassRepository#storeClass
*/
public OutputStream getOutputStream(String className, boolean isTopLevel)
throws IOException;

View File

@ -40,7 +40,7 @@ import java.io.*;
* This interface provides a means to store generated class and to
* allow selective class loading.
*
* @see Context
* @see ClassNameHelper
* @author Kemal Bayram
*/
public interface ClassRepository {
@ -51,5 +51,5 @@ public interface ClassRepository {
* @return true if the class should be loaded, false otherwise.
*/
public boolean storeClass(String className, byte[] classBytes,
boolean isTopLevel) throws IOException;
boolean isTopLevel) throws IOException;
}

View File

@ -169,7 +169,7 @@ public class Context {
}
} else {
if (cx.enterCount != 0) {
// The suplied context must be the context for
// The suplied context must be the context for
// the current thread if it is already entered
if (cx != old) {
throw new RuntimeException
@ -1344,142 +1344,111 @@ public class Context {
}
/**
* Get the current class name.
*
* @since 30/10/01 tip + patch (Kemal Bayram)
* @deprecated Use <tt>ClassNameHelper.get(cx).getClassName()</tt> instead.
* @see ClassNameHelper#getClassName
*/
public String getClassName() {
ClassNameHelper nameHelper = getNameHelper();
ClassNameHelper nameHelper = ClassNameHelper.get(this);
return nameHelper != null ? nameHelper.getClassName() : null;
}
/**
* Set the current class name.
*
* @since 30/10/01 tip + patch (Kemal Bayram)
* @deprecated Use <tt>ClassNameHelper.get(cx).setClassName(className)</tt> instead.
* @see ClassNameHelper#setClassName
*/
public void setClassName(String className) {
ClassNameHelper nameHelper = getNameHelper();
ClassNameHelper nameHelper = ClassNameHelper.get(this);
if (nameHelper != null)
nameHelper.setClassName(className);
}
/**
* Get the current target class file name.
* <p>
* If nonnull, requests to compile source will result in one or
* more class files being generated.
* @since 1.3
* @deprecated Use
* <tt>ClassNameHelper.get(cx).getTargetClassFileName()</tt> instead.
* @see ClassNameHelper#getTargetClassFileName
*/
public String getTargetClassFileName() {
ClassNameHelper nameHelper = getNameHelper();
ClassNameHelper nameHelper = ClassNameHelper.get(this);
if (nameHelper != null) {
ClassRepository repository = nameHelper.getClassRepository();
if (repository instanceof FileClassRepository)
return ((FileClassRepository)repository).getTargetClassFileName(nameHelper.getClassName());
}
return null;
}
/**
* Set the current target class file name.
* <p>
* If nonnull, requests to compile source will result in one or
* more class files being generated. If null, classes will only
* be generated in memory.
*
* @since 1.3
*/
public void setTargetClassFileName(String classFileName) {
ClassNameHelper nameHelper = getNameHelper();
if (nameHelper != null) {
if (classFileName != null)
nameHelper.setClassRepository(
new FileClassRepository(classFileName));
else
nameHelper.setClassName(null);
}
}
/**
* Get the current package to generate classes into.
*
* @since 1.3
*/
public String getTargetPackage() {
ClassNameHelper nameHelper = getNameHelper();
return nameHelper != null ? nameHelper.getTargetPackage() : null;
}
/**
* Set the package to generate classes into.
*
* @since 1.3
*/
public void setTargetPackage(String targetPackage) {
ClassNameHelper nameHelper = getNameHelper();
if (nameHelper != null)
nameHelper.setTargetPackage(targetPackage);
}
/**
* Get the current class repository.
*
* @see ClassRepository
* @since 30/10/01 tip + patch (Kemal Bayram)
*/
public ClassRepository getClassRepository() {
ClassNameHelper nameHelper = getNameHelper();
return nameHelper != null ? nameHelper.getClassRepository() : null;
}
/**
* Set the current class repository.
*
* @see ClassRepository
* @since 30/10/01 tip + patch (Kemal Bayram)
*/
public void setClassRepository(ClassRepository classRepository) {
ClassNameHelper nameHelper = getNameHelper();
if (nameHelper != null)
nameHelper.setClassRepository(classRepository);
}
/**
* Get the current interface to write class bytes into.
*
* @see ClassOutput
* @since 1.5 Release 2
*/
public ClassOutput getClassOutput() {
ClassNameHelper nameHelper = getNameHelper();
if (nameHelper != null) {
ClassRepository repository = nameHelper.getClassRepository();
if ((repository != null) &&
(repository instanceof ClassOutputWrapper))
{
return ((ClassOutputWrapper)repository).classOutput;
}
return nameHelper.getTargetClassFileName();
}
return null;
}
/**
* Set the interface to write class bytes into.
* Unless setTargetClassFileName() has been called classOutput will be
* used each time the javascript compiler has generated the bytecode for a
* script class.
*
* @see ClassOutput
* @since 1.5 Release 2
* @deprecated Use
* <tt>ClassNameHelper.get(cx).setTargetClassFileName(classFileName)</tt> instead.
* @see ClassNameHelper#setTargetClassFileName
*/
public void setTargetClassFileName(String classFileName) {
ClassNameHelper nameHelper = ClassNameHelper.get(this);
if (nameHelper != null) {
nameHelper.setTargetClassFileName(classFileName);
}
}
/**
* @deprecated Use <tt>ClassNameHelper.get(cx).getTargetPackage()</tt> instead.
* @see ClassNameHelper#getTargetPackage
*/
public String getTargetPackage() {
ClassNameHelper nameHelper = ClassNameHelper.get(this);
return nameHelper != null ? nameHelper.getTargetPackage() : null;
}
/**
* @deprecated Use <tt>ClassNameHelper.get(cx).setTargetPackage(targetPackage)</tt>
* instead.
* @see ClassNameHelper#setTargetPackage
*/
public void setTargetPackage(String targetPackage) {
ClassNameHelper nameHelper = ClassNameHelper.get(this);
if (nameHelper != null)
nameHelper.setTargetPackage(targetPackage);
}
/**
* @deprecated Use <tt>ClassNameHelper.get(cx).getClassRepository()</tt> instead.
* @see ClassNameHelper#getClassRepository
*/
public ClassRepository getClassRepository() {
ClassNameHelper nameHelper = ClassNameHelper.get(this);
return nameHelper != null ? nameHelper.getClassRepository() : null;
}
/**
* @deprecated Use
* <tt>ClassNameHelper.get(cx).setClassRepository(classRepository)</tt> instead.
* @see ClassNameHelper#setClassRepository
*/
public void setClassRepository(ClassRepository classRepository) {
ClassNameHelper nameHelper = ClassNameHelper.get(this);
if (nameHelper != null)
nameHelper.setClassRepository(classRepository);
}
/**
* @deprecated Use
* <tt>ClassNameHelper.get(cx).getClassOutput()</tt> instead.
* @see ClassNameHelper#getClassOutput
*/
public ClassOutput getClassOutput() {
ClassNameHelper nameHelper = ClassNameHelper.get(this);
if (nameHelper != null) {
return nameHelper.getClassOutput();
}
return null;
}
/**
* @deprecated Use
* <tt>ClassNameHelper.get(cx).setClassOutput(classOutput)</tt> instead.
* @see ClassNameHelper#setClassOutput
*/
public void setClassOutput(ClassOutput classOutput) {
ClassNameHelper nameHelper = getNameHelper();
ClassNameHelper nameHelper = ClassNameHelper.get(this);
if (nameHelper != null) {
if (classOutput != null)
nameHelper.setClassRepository(new ClassOutputWrapper(classOutput));
else
nameHelper.setClassRepository(null);
nameHelper.setClassOutput(classOutput);
}
}
@ -1524,30 +1493,30 @@ public class Context {
classShutter = shutter;
}
ClassShutter getClassShutter() {
final ClassShutter getClassShutter() {
return classShutter;
}
/**
* Set the class that the generated target will extend.
*
* @param extendsClass the class it extends
* @deprecated Use
* <tt>ClassNameHelper.get(cx).setTargetExtends(extendsClass)</tt> instead.
* @see ClassNameHelper#setTargetExtends
*/
public void setTargetExtends(Class extendsClass) {
ClassNameHelper nameHelper = getNameHelper();
ClassNameHelper nameHelper = ClassNameHelper.get(this);
if (nameHelper != null) {
nameHelper.setTargetExtends(extendsClass);
}
}
/**
* Set the interfaces that the generated target will implement.
*
* @param implementsClasses an array of Class objects, one for each
* interface the target will extend
* @deprecated Use
* <tt>ClassNameHelper.get(cx).setTargetImplements(implementsClasses)</tt>
* instead.
* @see ClassNameHelper#setTargetImplements
*/
public void setTargetImplements(Class[] implementsClasses) {
ClassNameHelper nameHelper = getNameHelper();
ClassNameHelper nameHelper = ClassNameHelper.get(this);
if (nameHelper != null) {
nameHelper.setTargetImplements(implementsClasses);
}
@ -1568,7 +1537,7 @@ public class Context {
* @param key the key used to lookup the value
* @return a value previously stored using putThreadLocal.
*/
public Object getThreadLocal(Object key) {
public final Object getThreadLocal(Object key) {
if (hashtable == null)
return null;
return hashtable.get(key);
@ -1606,7 +1575,7 @@ public class Context {
* This is useful for sharing functions across multiple scopes.
* @since 1.5 Release 1
*/
public boolean hasCompileFunctionsWithDynamicScope() {
public final boolean hasCompileFunctionsWithDynamicScope() {
return compileFunctionsWithDynamicScopeFlag;
}
@ -1644,8 +1613,7 @@ public class Context {
if (isCachingEnabled && !cachingEnabled) {
// Caching is being turned off. Empty caches.
JavaMembers.classTable = new Hashtable();
if (savedNameHelper != null)
savedNameHelper.reset();
ClassNameHelper.clearCache();
}
isCachingEnabled = cachingEnabled;
FunctionObject.setCachingEnabled(cachingEnabled);
@ -1727,7 +1695,7 @@ public class Context {
* @see org.mozilla.javascript.WrapHandler
* @since 1.5 Release 4
*/
public WrapFactory getWrapFactory() {
public final WrapFactory getWrapFactory() {
if (wrapFactory == null) {
wrapFactory = new WrapFactory();
}
@ -1738,7 +1706,7 @@ public class Context {
* Return the current debugger.
* @return the debugger, or null if none is attached.
*/
public Debugger getDebugger() {
public final Debugger getDebugger() {
return debugger;
}
@ -1746,7 +1714,7 @@ public class Context {
* Return the debugger context data associated with current context.
* @return the debugger data, or null if debugger is not attached
*/
public Object getDebuggerContextData() {
public final Object getDebuggerContextData() {
return debuggerData;
}
@ -1981,7 +1949,6 @@ public class Context {
}
private static Class codegenClass;
private static ClassNameHelper savedNameHelper;
static {
try {
codegenClass = Class.forName(
@ -1992,26 +1959,6 @@ public class Context {
}
}
private static ClassNameHelper getNameHelper() {
if (savedNameHelper != null)
return savedNameHelper;
if (codegenClass == null)
return null;
try {
Class nameHelperClass = Class.forName(
"org.mozilla.javascript.optimizer.OptClassNameHelper");
savedNameHelper = (ClassNameHelper)nameHelperClass.newInstance();
return savedNameHelper;
} catch (ClassNotFoundException x) {
// ...must be running lite, that's ok
return null;
} catch (IllegalAccessException x) {
return null;
} catch (InstantiationException x) {
return null;
}
}
private Interpreter getCompiler() {
if (codegenClass != null) {
try {
@ -2040,7 +1987,7 @@ public class Context {
: getCompiler();
ClassNameHelper nameHelper = optimizationLevel == -1
? null
: getNameHelper();
: ClassNameHelper.get(this);
errorCount = 0;
IRFactory irf = compiler.createIRFactory(ts, nameHelper, scope);
@ -2270,74 +2217,4 @@ public class Context {
// For instruction counting (interpreter only)
int instructionCount;
int instructionThreshold;
// Implement class file saving here instead of inside codegen.
private class FileClassRepository implements ClassRepository {
FileClassRepository(String classFileName) {
int lastSeparator = classFileName.lastIndexOf(File.separatorChar);
String initialName;
if (lastSeparator == -1) {
generatingDirectory = null;
initialName = classFileName;
} else {
generatingDirectory = classFileName.substring(0, lastSeparator);
initialName = classFileName.substring(lastSeparator+1);
}
if (initialName.endsWith(".class"))
initialName = initialName.substring(0, initialName.length()-6);
getNameHelper().setClassName(initialName);
}
public boolean storeClass(String className, byte[] bytes, boolean tl)
throws IOException
{
// no "elegant" way of getting file name from fully
// qualified class name.
String targetPackage = getNameHelper().getTargetPackage();
if ((targetPackage != null) && (targetPackage.length()>0) &&
className.startsWith(targetPackage+"."))
{
className = className.substring(targetPackage.length()+1);
}
FileOutputStream out = new FileOutputStream(getTargetClassFileName(className));
out.write(bytes);
out.close();
return false;
}
String getTargetClassFileName(String className) {
StringBuffer sb = new StringBuffer();
if (generatingDirectory != null) {
sb.append(generatingDirectory);
sb.append(File.separator);
}
sb.append(className);
sb.append(".class");
return sb.toString();
}
String generatingDirectory;
};
private static class ClassOutputWrapper implements ClassRepository {
ClassOutputWrapper(ClassOutput classOutput) {
this.classOutput = classOutput;
}
public boolean storeClass(String name, byte[] bytes, boolean tl)
throws IOException
{
OutputStream out = classOutput.getOutputStream(name, tl);
out.write(bytes);
out.close();
return true;
}
ClassOutput classOutput;
}
}

View File

@ -42,7 +42,7 @@ import org.mozilla.javascript.*;
import java.io.*;
import java.util.Hashtable;
public class OptClassNameHelper implements ClassNameHelper {
public class OptClassNameHelper extends ClassNameHelper {
public OptClassNameHelper() {
setClassName(null);

View File

@ -76,7 +76,8 @@ public class Main {
*
*/
public static String[] processOptions(Context cx, String args[]) {
cx.setTargetPackage(""); // default to no package
ClassNameHelper nameHelper = ClassNameHelper.get(cx);
nameHelper.setTargetPackage(""); // default to no package
cx.setGeneratingDebug(false); // default to no symbols
for (int i=0; i < args.length; i++) {
String arg = args[i];
@ -132,7 +133,7 @@ public class Main {
break;
}
}
cx.setTargetClassFileName(outFile);
nameHelper.setTargetClassFileName(outFile);
hasOutOption = true;
continue;
}
@ -163,13 +164,13 @@ public class Main {
continue;
}
}
cx.setTargetPackage(targetPackage);
nameHelper.setTargetPackage(targetPackage);
continue;
}
if (arg.equals("-extends") && ++i < args.length) {
String targetExtends = args[i];
try {
cx.setTargetExtends(Class.forName(targetExtends));
nameHelper.setTargetExtends(Class.forName(targetExtends));
} catch (ClassNotFoundException e) {
throw new Error(e.toString()); // TODO: better error
}
@ -191,7 +192,7 @@ public class Main {
}
Class[] implementsClasses = new Class[v.size()];
v.copyInto(implementsClasses);
cx.setTargetImplements(implementsClasses);
nameHelper.setTargetImplements(implementsClasses);
continue;
}
usage(arg);
@ -214,10 +215,11 @@ public class Main {
*
*/
public static void processSource(Context cx, String[] filenames) {
ClassNameHelper nameHelper = ClassNameHelper.get(cx);
if (hasOutOption && filenames.length > 1) {
cx.reportError(ToolErrorReporter.getMessage(
"msg.multiple.js.to.file",
cx.getTargetClassFileName()));
nameHelper.getTargetClassFileName()));
}
for (int i=0; i < filenames.length; i++) {
String filename = filenames[i];
@ -241,9 +243,9 @@ public class Main {
String className = getClassName(nojs) + ".class";
String out = f.getParent() == null ? className : f.getParent() +
File.separator + className;
cx.setTargetClassFileName(out);
nameHelper.setTargetClassFileName(out);
}
if (cx.getTargetClassFileName() == null) {
if (nameHelper.getTargetClassFileName() == null) {
cx.reportError(ToolErrorReporter.getMessage("msg.no-opt"));
}
try {