Skip to content

Commit

Permalink
Merge jboss-proxy with invocation-api to get jboss-invocation
Browse files Browse the repository at this point in the history
  • Loading branch information
dmlloyd committed Jan 22, 2011
2 parents 4bf4431 + 5514ca2 commit f048768
Show file tree
Hide file tree
Showing 23 changed files with 1,795 additions and 10 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/.idea
*.iml
target
.prject
.project
.settings
.classpath
48 changes: 38 additions & 10 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,21 @@
<modelVersion>4.0.0</modelVersion>

<!-- Artifact Information -->
<groupId>org.jboss</groupId>
<artifactId>invocation-api</artifactId>
<groupId>org.jboss.invocation</groupId>
<artifactId>jboss-invocation</artifactId>
<version>1.0.0.CR1-SNAPSHOT</version>
<name>Invocation API</name>
<description>Invocation Application Programming Interface</description>
<packaging>jar</packaging>

<!-- Properties -->
<properties>
<classwriter.version>1.0-SNAPSHOT</classwriter.version>
<javax.interceptor.version>1.0.0.Final</javax.interceptor.version>
<jboss.marshalling.version>1.3.0.CR8</jboss.marshalling.version>
<jboss.logging.version>3.0.0.Beta4</jboss.logging.version>
<jboss.logging.tools.version>1.0.0.Beta2</jboss.logging.tools.version>
<junit.version>4.8.2</junit.version>
</properties>

<!-- Build Information -->
Expand All @@ -53,33 +59,55 @@
<plugin>
<artifactId>maven-source-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<forkMode>once</forkMode>
<argLine>-XX:-FailOverToOldVerifier -Xverify:all</argLine>
</configuration>
</plugin>
</plugins>

</build>

<!-- Dependencies -->
<dependencies>
<dependency>
<groupId>org.jboss.marshalling</groupId>
<artifactId>jboss-marshalling</artifactId>
<version>1.3.0.CR8</version>
<groupId>org.jboss.spec.javax.interceptor</groupId>
<artifactId>jboss-interceptors-api_1.1_spec</artifactId>
<version>${javax.interceptor.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.spec.javax.interceptor</groupId>
<artifactId>jboss-interceptors-api_1.1_spec</artifactId>
<version>1.0.0.Final</version>
<groupId>org.jboss.marshalling</groupId>
<artifactId>jboss-marshalling</artifactId>
<version>${jboss.marshalling.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<version>3.0.0.Beta4</version>
<version>${jboss.logging.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging-tools</artifactId>
<version>1.0.0.Beta2</version>
<version>${jboss.logging.tools.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.classwriter</groupId>
<artifactId>classwriter</artifactId>
<version>${classwriter.version}</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
151 changes: 151 additions & 0 deletions src/main/java/org/jboss/invocation/proxy/AbstractClassFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2010, Red Hat Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package org.jboss.invocation.proxy;

import java.security.ProtectionDomain;

import org.jboss.classfilewriter.ClassFile;

/**
* Base class for all class factories.
* <p>
* Sub classes should override {@link #generateClass()} to perform the actual class generation. The class will only be generated
* once at most
*
* @author Stuart Douglas
*
*/
public abstract class AbstractClassFactory<T> {

/**
* The name of the generated class
*/
private final String className;

/**
* superclass of the generated class
*/
private final Class<T> superClass;

/**
* The class loader that is used to load the class
*/
private final ClassLoader classLoader;

/**
* The ProtectionDomain that the generated class will be definied in
*/
private final ProtectionDomain protectionDomain;

/**
* The class object for the generated class
*/
private volatile Class<? extends T> generatedClass;

/**
* The class file that is used to generate the class.
* <p>
* Note that this object is not thread safe, so care should be taken by subclasses to ensure that no more than one thread
* accesses this at once. In normal use this should not be an issue, as {@link #defineClass()} will only be called once by a
* single thread.
* <p>
* This is set to null after the class is generated
*/
protected ClassFile classFile;

public AbstractClassFactory(String className, Class<T> superClass, ClassLoader classLoader,
ProtectionDomain protectionDomain) {
this.className = className;
this.superClass = superClass;
this.classLoader = classLoader;
this.protectionDomain = protectionDomain;
this.classFile = new ClassFile(className, superClass.getName());
}

public AbstractClassFactory(String className, Class<T> superClass, ClassLoader classLoader) {
this(className, superClass, classLoader, null);
}

public AbstractClassFactory(String className, Class<T> superClass) {
this(className, superClass, superClass.getClassLoader(), null);
}

protected abstract void generateClass();

/**
* Cleans up any resources left over from generating the class. Implementors should ensure they call super.cleanup();
*/
protected abstract void cleanup();

/**
* Returns the {@link Class} object for the generated class, creating it if it does not exist
*
*/
public Class<? extends T> defineClass() {
if (generatedClass == null) {
synchronized (this) {
if (generatedClass == null) {
generateClass();
if (protectionDomain == null) {
generatedClass = (Class<? extends T>)classFile.define(classLoader);
} else {
generatedClass = (Class<? extends T>)classFile.define(classLoader, protectionDomain);
}
cleanup();
classFile = null;
}
}
}
return generatedClass;
}

/**
* Creates a new instance of the generated class by invoking the default constructor.
* <p>
* If the generated class has not been defined it will be created
*
*/
public T newInstance() throws InstantiationException, IllegalAccessException {
return defineClass().newInstance();
}

public String getClassName() {
return className;
}

public String getSuperClassName() {
return superClass.getName();
}

public Class<T> getSuperClass() {
return superClass;
}

public ClassLoader getClassLoader() {
return classLoader;
}

public ProtectionDomain getProtectionDomain() {
return protectionDomain;
}
}
112 changes: 112 additions & 0 deletions src/main/java/org/jboss/invocation/proxy/AbstractProxyFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2010, Red Hat Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package org.jboss.invocation.proxy;

import java.lang.reflect.Method;
import java.security.ProtectionDomain;
import java.util.HashMap;
import java.util.Map;

import org.jboss.classfilewriter.AccessFlag;
import org.jboss.classfilewriter.ClassMethod;
import org.jboss.classfilewriter.code.CodeAttribute;
import org.jboss.invocation.MethodIdentifier;

public abstract class AbstractProxyFactory<T> extends AbstractSubclassFactory<T> {

private static final String METHOD_IDENTIFIER_FIELD_PREFIX = "METHOD$$IDENTIFIER";

private static final String METHID_IDENTIFIER_FIELD_DESCRIPTOR = "Lorg/jboss/invocation/MethodIdentifier;";

private final Map<Method, String> methodIdentifiers = new HashMap<Method, String>();

private int identifierCount = 0;

private ClassMethod staticConstructor;

public AbstractProxyFactory(String className, Class<T> superClass, ClassLoader classLoader) {
super(className, superClass, classLoader);
staticConstructor = classFile.addMethod(AccessFlag.of(AccessFlag.PUBLIC, AccessFlag.STATIC), "<clinit>", "V");
}

public AbstractProxyFactory(String className, Class<T> superClass, ClassLoader classLoader,
ProtectionDomain protectionDomain) {
super(className, superClass, classLoader, protectionDomain);
staticConstructor = classFile.addMethod(AccessFlag.of(AccessFlag.PUBLIC, AccessFlag.STATIC), "<clinit>", "V");
}

public AbstractProxyFactory(String className, Class<T> superClass) {
super(className, superClass);
staticConstructor = classFile.addMethod(AccessFlag.of(AccessFlag.PUBLIC, AccessFlag.STATIC), "<clinit>", "V");
}

/**
* This method must be called by subclasses after they have finished generating the class
*/
protected void finalizeStaticConstructor() {
staticConstructor.getCodeAttribute().returnInstruction();
}

@Override
protected void cleanup() {
staticConstructor = null;
super.cleanup();
}

/**
* Writes the bytecode to load an instance of MethodIdentifier for the given method onto the stack.
* <p>
* If loadMethodIdentifier has not already been called for the given identifier then a static field to hold the identifier
* is added to the class, and code is added to the static constructor to initalize the field to the correct MethodIdentifier
*
*/
protected void loadMethodIdentifier(Method methodToLoad, ClassMethod method) {
if (!methodIdentifiers.containsKey(methodToLoad)) {
int identifierNo = identifierCount++;
String fieldName = METHOD_IDENTIFIER_FIELD_PREFIX + identifierNo;
classFile.addField(AccessFlag.PRIVATE | AccessFlag.STATIC, fieldName, MethodIdentifier.class);
methodIdentifiers.put(methodToLoad, fieldName);
// we need to create the method identifier in the static constructor
CodeAttribute ca = staticConstructor.getCodeAttribute();
//push the method return type onto the stack
ca.ldc(methodToLoad.getReturnType().getName());
// push the method name onto the stack
ca.ldc(methodToLoad.getName());
Class<?>[] parameters = methodToLoad.getParameterTypes();
// now we need a new array
ca.iconst(parameters.length);
ca.anewarray(String.class.getName());
for (int i = 0; i < parameters.length; ++i) {
ca.dup(); //dup the array
ca.iconst(i); //the array index to store it
ca.ldc(parameters[i].getName());
ca.aastore();
}
ca.invokestatic(MethodIdentifier.class.getName(), "getIdentifier", "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)Lorg/jboss/invocation/MethodIdentifier;");
ca.putstatic(getClassName(), fieldName, METHID_IDENTIFIER_FIELD_DESCRIPTOR);
}
String fieldName = methodIdentifiers.get(methodToLoad);
method.getCodeAttribute().getstatic(getClassName(), fieldName, METHID_IDENTIFIER_FIELD_DESCRIPTOR);
}

}
Loading

0 comments on commit f048768

Please sign in to comment.