Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*****************************************************************************
* 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. *
* *
* *
* This file is part of the BeanShell Java Scripting distribution. *
* Documentation and updates may be found at http://www.beanshell.org/ *
* Patrick Niemeyer ([email protected]) *
* Author of Learning Java, O'Reilly & Associates *
* *
*****************************************************************************/
package bsh;
import java.io.*;
import java.util.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
This class is an implementation of the ClassGenerator interface which
contains generally bsh related code. The actual bytecode generation is
done by ClassGeneratorUtil.
@author Pat Niemeyer ([email protected])
*/
public class ClassGeneratorImpl extends ClassGenerator
{
public Class generateClass(
String name, Modifiers modifiers,
Class [] interfaces, Class superClass, BSHBlock block,
boolean isInterface, CallStack callstack, Interpreter interpreter
)
throws EvalError
{
// Delegate to the static method
return generateClassImpl( name, modifiers, interfaces, superClass,
block, isInterface, callstack, interpreter );
}
public Object invokeSuperclassMethod(
BshClassManager bcm, Object instance, String methodName, Object [] args
)
throws UtilEvalError, ReflectError, InvocationTargetException
{
// Delegate to the static method
return invokeSuperclassMethodImpl( bcm, instance, methodName, args );
}
/**
Change the parent of the class instance namespace.
This is currently used for inner class support.
Note: This method will likely be removed in the future.
*/
// This could be static
public void setInstanceNameSpaceParent(
Object instance, String className, NameSpace parent )
{
This ithis =
ClassGeneratorUtil.getClassInstanceThis( instance, className );
ithis.getNameSpace().setParent( parent );
}
/**
If necessary, parse the BSHBlock for for the class definition and
generate the class using ClassGeneratorUtil.
This method also initializes the static block namespace and sets it
in the class.
*/
public static Class generateClassImpl(
String name, Modifiers modifiers,
Class [] interfaces, Class superClass, BSHBlock block,
boolean isInterface, CallStack callstack, Interpreter interpreter
)
throws EvalError
{
// Scripting classes currently requires accessibility
// This can be eliminated with a bit more work.
try {
Capabilities.setAccessibility( true );
} catch ( Capabilities.Unavailable e )
{
throw new EvalError(
"Defining classes currently requires reflective Accessibility.",
block, callstack );
}
NameSpace enclosingNameSpace = callstack.top();
String packageName = enclosingNameSpace.getPackage();
String className = enclosingNameSpace.isClass ?
( enclosingNameSpace.getName()+"$"+name ) : name;
String fqClassName =
packageName == null ? className : packageName + "." + className;
String bshStaticFieldName = ClassGeneratorUtil.BSHSTATIC+className;
BshClassManager bcm = interpreter.getClassManager();
// Race condition here...
bcm.definingClass( fqClassName );
// Create the class static namespace
NameSpace classStaticNameSpace =
new NameSpace( enclosingNameSpace, className);
classStaticNameSpace.isClass = true;
callstack.push( classStaticNameSpace );
// Evaluate any inner class class definitions in the block
// effectively recursively call this method for contained classes first
block.evalBlock(
callstack, interpreter, true/*override*/,
ClassNodeFilter.CLASSCLASSES );
// Generate the type for our class
Variable [] variables =
getDeclaredVariables( block, callstack, interpreter, packageName );
DelayedEvalBshMethod [] methods =
getDeclaredMethods( block, callstack, interpreter, packageName );
// Create the class generator, which encapsulates all knowledge of the
// structure of the class
ClassGeneratorUtil classGenerator = new ClassGeneratorUtil(
modifiers, className, packageName, superClass, interfaces,
variables, methods, isInterface );
// Check for existing class (saved class file)
Class clas = bcm.getAssociatedClass( fqClassName );
// If the class isn't there then generate it.
// Else just let it be initialized below.
if ( clas == null )
{
// generate bytecode, optionally with static init hooks to
// bootstrap the interpreter
byte [] code = classGenerator.generateClass(
Interpreter.getSaveClasses()/*init code*/ );
if ( Interpreter.getSaveClasses() )
saveClasses( className, code );
else
clas = bcm.defineClass( fqClassName, code );
}
// If we're just saving clases then don't actually execute the static
// code for the class here.
if ( !Interpreter.getSaveClasses() )
{
// Let the class generator install hooks relating to the structure of
// the class into the class static namespace. e.g. the constructor
// array. This is necessary whether we are generating code or just
// reinitializing a previously generated class.
classGenerator.initStaticNameSpace(
classStaticNameSpace, block/*instance initializer*/ );
// import the unqualified class name into parent namespace
enclosingNameSpace.importClass( fqClassName.replace('$','.') );
// Give the static space its class static import
// important to do this after all classes are defined
classStaticNameSpace.setClassStatic( clas );
// evaluate the static portion of the block in the static space
block.evalBlock(
callstack, interpreter, true/*override*/,
ClassNodeFilter.CLASSSTATIC );
if ( !clas.isInterface() )
installStaticBlock( clas, bshStaticFieldName,
classStaticNameSpace, interpreter );
}
callstack.pop();
bcm.doneDefiningClass( fqClassName );
return clas;
}
private static void installStaticBlock(
Class genClass, String bshStaticFieldName,
NameSpace classStaticNameSpace, Interpreter interpreter )
{
// Set the static bsh This callback
try {
LHS lhs = Reflect.getLHSStaticField( genClass, bshStaticFieldName );
lhs.assign(
classStaticNameSpace.getThis( interpreter ), false/*strict*/ );
} catch ( Exception e ) {
throw new InterpreterError("Error in class gen setup: "+e );
}
}
private static void saveClasses( String className, byte[] code )
{
String dir = Interpreter.getSaveClassesDir();
if ( dir != null )
try {
FileOutputStream out=
new FileOutputStream( dir+"/"+className+".class" );
out.write(code);
out.close();
} catch ( IOException e ) {
e.printStackTrace();
}
}
static Variable [] getDeclaredVariables(
BSHBlock body, CallStack callstack, Interpreter interpreter,
String defaultPackage
)
{
List vars = new ArrayList();
for( int child=0; child