Seam SVN: r10148 - trunk/src/wicket/org/jboss/seam/wicket/ioc.
by seam-commits@lists.jboss.org
Author: cpopetz
Date: 2009-03-12 13:28:57 -0400 (Thu, 12 Mar 2009)
New Revision: 10148
Modified:
trunk/src/wicket/org/jboss/seam/wicket/ioc/JavassistInstrumentor.java
Log:
JBSEAM-4001 Wicket Instrumentation Annotation
Modified: trunk/src/wicket/org/jboss/seam/wicket/ioc/JavassistInstrumentor.java
===================================================================
--- trunk/src/wicket/org/jboss/seam/wicket/ioc/JavassistInstrumentor.java 2009-03-12 17:22:18 UTC (rev 10147)
+++ trunk/src/wicket/org/jboss/seam/wicket/ioc/JavassistInstrumentor.java 2009-03-12 17:28:57 UTC (rev 10148)
@@ -141,9 +141,9 @@
}
}
- public JavassistInstrumentor(ClassPool classPool, Set<String> packagesToInstrument)
+ public JavassistInstrumentor(ClassPool classPool, Set<String> packagesToInstrument, boolean scanAnnotations)
{
- this(classPool);
+ this(classPool,scanAnnotations);
this.packagesToInstrument = packagesToInstrument;
}
@@ -441,6 +441,8 @@
{
Set<String> packagesToInstrument = new HashSet<String>();
String list = System.getProperty("org.jboss.seam.wicket.instrumented-packages");
+ String scanAnnotationsProperty = System.getProperty("org.jboss.seam.wicket.scanAnnotations");
+ boolean scanAnnotations = scanAnnotationsProperty == null ? false : scanAnnotationsProperty.equals("true");
if (list == null)
return;
for (String packageName : list.split(","))
@@ -450,6 +452,6 @@
ClassPool classPool = new ClassPool();
classPool.appendSystemPath();
- instrumentation.addTransformer(new JavassistInstrumentor(classPool, packagesToInstrument));
+ instrumentation.addTransformer(new JavassistInstrumentor(classPool, packagesToInstrument, scanAnnotations));
}
}
15 years, 9 months
Seam SVN: r10147 - trunk/src/wicket/org/jboss/seam/wicket/ioc.
by seam-commits@lists.jboss.org
Author: cpopetz
Date: 2009-03-12 13:22:18 -0400 (Thu, 12 Mar 2009)
New Revision: 10147
Added:
trunk/src/wicket/org/jboss/seam/wicket/ioc/SeamWicketComponent.java
Modified:
trunk/src/wicket/org/jboss/seam/wicket/ioc/JavassistInstrumentor.java
trunk/src/wicket/org/jboss/seam/wicket/ioc/WicketInstrumentationTask.java
Log:
JBSEAM-4001 Wicket Instrumentation Annotation
Modified: trunk/src/wicket/org/jboss/seam/wicket/ioc/JavassistInstrumentor.java
===================================================================
--- trunk/src/wicket/org/jboss/seam/wicket/ioc/JavassistInstrumentor.java 2009-03-12 15:51:07 UTC (rev 10146)
+++ trunk/src/wicket/org/jboss/seam/wicket/ioc/JavassistInstrumentor.java 2009-03-12 17:22:18 UTC (rev 10147)
@@ -116,10 +116,21 @@
*/
private CtClass instrumentedComponent;
+ /**
+ * If true, only instrument classes annotated with @WicketComponent and their non-static inner classes.
+ */
+ private boolean scanAnnotations;
public JavassistInstrumentor(ClassPool classPool)
{
+ this(classPool,false);
+ }
+
+ public JavassistInstrumentor(ClassPool classPool, boolean scanAnnotations)
+ {
this.classPool = classPool;
+ this.scanAnnotations = scanAnnotations;
+
try
{
instrumentedComponent = classPool.get(InstrumentedComponent.class.getName());
@@ -138,10 +149,11 @@
public CtClass instrumentClass(String className) throws NotFoundException, CannotCompileException
{
- log.debug("Instrumenting " + className);
+ log.debug("Examining " + className);
CtClass implementation = classPool.get(className);
if (isInstrumentable(implementation))
{
+ log.debug("Instrumenting " + className);
instrumentClass(implementation);
}
return implementation;
@@ -324,7 +336,7 @@
* @param clazz The class to check
* @return
*/
- private boolean isInstrumentable(CtClass clazz)
+ public boolean isInstrumentable(CtClass clazz)
{
int modifiers = clazz.getModifiers();
if (Modifier.isInterface(modifiers) || Modifier.isEnum(modifiers))
@@ -335,8 +347,9 @@
try
{
// do not instrument @Named components or nested non-static classes
- // inside named components
+ // inside named components.
CtClass checkName = clazz;
+ boolean hasWicketComponentAnnotation = false;
do
{
for (Object a : checkName.getAnnotations())
@@ -345,11 +358,20 @@
{
return false;
}
+ else if (scanAnnotations && a instanceof SeamWicketComponent)
+ {
+ hasWicketComponentAnnotation = true;
+ }
}
checkName = Modifier.isStatic(clazz.getModifiers()) ? null : checkName.getDeclaringClass();
}
while (checkName != null);
+ if (scanAnnotations && !hasWicketComponentAnnotation)
+ {
+ return false;
+ }
+
// do not instrument something we've already instrumented.
// can't use 'isSubtype' because the superclass may be instrumented
// while we are not
Added: trunk/src/wicket/org/jboss/seam/wicket/ioc/SeamWicketComponent.java
===================================================================
--- trunk/src/wicket/org/jboss/seam/wicket/ioc/SeamWicketComponent.java (rev 0)
+++ trunk/src/wicket/org/jboss/seam/wicket/ioc/SeamWicketComponent.java 2009-03-12 17:22:18 UTC (rev 10147)
@@ -0,0 +1,22 @@
+package org.jboss.seam.wicket.ioc;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Specifies that a class should be instrumented to allow for use as a Seam Wicket component
+ * @author Clint Popetz
+ *
+ */
+@Target(TYPE)
+@Retention(RUNTIME)
+@Documented
+public @interface SeamWicketComponent
+{
+}
+
+
Modified: trunk/src/wicket/org/jboss/seam/wicket/ioc/WicketInstrumentationTask.java
===================================================================
--- trunk/src/wicket/org/jboss/seam/wicket/ioc/WicketInstrumentationTask.java 2009-03-12 15:51:07 UTC (rev 10146)
+++ trunk/src/wicket/org/jboss/seam/wicket/ioc/WicketInstrumentationTask.java 2009-03-12 17:22:18 UTC (rev 10147)
@@ -49,7 +49,19 @@
{
this.fileset = fileset;
}
+
+ private boolean useAnnotations = false;
+ public boolean isUseAnnotations()
+ {
+ return useAnnotations;
+ }
+
+ public void setUseAnnotations(boolean useAnnotations)
+ {
+ this.useAnnotations = useAnnotations;
+ }
+
@Override
public void execute()
{
@@ -58,10 +70,10 @@
ClassPool classPool = new ClassPool();
classPool.insertClassPath(new LoaderClassPath(getProject().createClassLoader(buildPath)));
-
+
List<CtClass> instrumentedClasses = new ArrayList<CtClass>();
- JavassistInstrumentor instrumentor = new JavassistInstrumentor(classPool);
+ JavassistInstrumentor instrumentor = new JavassistInstrumentor(classPool,useAnnotations);
for (String file : fileset.getDirectoryScanner(getProject()).getIncludedFiles())
{
15 years, 9 months
Seam SVN: r10146 - trunk/src/wicket/META-INF.
by seam-commits@lists.jboss.org
Author: cpopetz
Date: 2009-03-12 11:51:07 -0400 (Thu, 12 Mar 2009)
New Revision: 10146
Removed:
trunk/src/wicket/META-INF/seam-deployment.properties
Log:
defunct
Deleted: trunk/src/wicket/META-INF/seam-deployment.properties
===================================================================
--- trunk/src/wicket/META-INF/seam-deployment.properties 2009-03-11 15:42:07 UTC (rev 10145)
+++ trunk/src/wicket/META-INF/seam-deployment.properties 2009-03-12 15:51:07 UTC (rev 10146)
@@ -1 +0,0 @@
-org.jboss.seam.deployment.deploymentHandlers=org.jboss.seam.wicket.two.WicketComponentDeploymentHandler
\ No newline at end of file
15 years, 9 months
Seam SVN: r10145 - trunk/src/main/org/jboss/seam/transaction.
by seam-commits@lists.jboss.org
Author: norman.richards(a)jboss.com
Date: 2009-03-11 11:42:07 -0400 (Wed, 11 Mar 2009)
New Revision: 10145
Modified:
trunk/src/main/org/jboss/seam/transaction/TransactionInterceptor.java
Log:
JBSEAM-3984
Modified: trunk/src/main/org/jboss/seam/transaction/TransactionInterceptor.java
===================================================================
--- trunk/src/main/org/jboss/seam/transaction/TransactionInterceptor.java 2009-03-10 16:18:04 UTC (rev 10144)
+++ trunk/src/main/org/jboss/seam/transaction/TransactionInterceptor.java 2009-03-11 15:42:07 UTC (rev 10145)
@@ -60,29 +60,29 @@
}
}
- private TransactionMetadata lookupTransactionMetadata(AnnotatedElement element)
- {
- TransactionMetadata metadata = transactionMetadata.get(element);
-
- if (metadata == null)
- {
- metadata = loadMetadata(element);
- }
-
- return metadata;
- }
+ private TransactionMetadata lookupTransactionMetadata(AnnotatedElement element) {
+ if (transactionMetadata == null) {
+ transactionMetadata = new HashMap<AnnotatedElement, TransactionMetadata>();
+ }
+
+ TransactionMetadata metadata = transactionMetadata.get(element);
+
+ if (metadata == null) {
+ metadata = loadMetadata(element);
+ }
+
+ return metadata;
+ }
- private synchronized TransactionMetadata loadMetadata(AnnotatedElement element)
- {
- if (!transactionMetadata.containsKey(element))
- {
- TransactionMetadata metadata = new TransactionMetadata(element);
- transactionMetadata.put(element, metadata);
- return metadata;
- }
-
- return transactionMetadata.get(element);
- }
+ private synchronized TransactionMetadata loadMetadata(AnnotatedElement element) {
+ if (!transactionMetadata.containsKey(element)) {
+ TransactionMetadata metadata = new TransactionMetadata(element);
+ transactionMetadata.put(element, metadata);
+ return metadata;
+ }
+
+ return transactionMetadata.get(element);
+ }
@AroundInvoke
15 years, 9 months
Seam SVN: r10144 - maven-plugins/trunk/seam-instrument-wicket.
by seam-commits@lists.jboss.org
Author: cpopetz
Date: 2009-03-10 12:18:04 -0400 (Tue, 10 Mar 2009)
New Revision: 10144
Modified:
maven-plugins/trunk/seam-instrument-wicket/
Log:
ignore target
Property changes on: maven-plugins/trunk/seam-instrument-wicket
___________________________________________________________________
Name: svn:ignore
- .classpath
.settings
.project
+ .classpath
.settings
.project
target
15 years, 9 months
Seam SVN: r10143 - maven-plugins/trunk/seam-instrument-wicket.
by seam-commits@lists.jboss.org
Author: cpopetz
Date: 2009-03-10 12:17:10 -0400 (Tue, 10 Mar 2009)
New Revision: 10143
Modified:
maven-plugins/trunk/seam-instrument-wicket/pom.xml
Log:
Inherit from seam root pom.
Modified: maven-plugins/trunk/seam-instrument-wicket/pom.xml
===================================================================
--- maven-plugins/trunk/seam-instrument-wicket/pom.xml 2009-03-10 15:47:08 UTC (rev 10142)
+++ maven-plugins/trunk/seam-instrument-wicket/pom.xml 2009-03-10 16:17:10 UTC (rev 10143)
@@ -10,6 +10,11 @@
<description>
A maven mojo to instrument wicket components to work with Seam's wicket integration.
</description>
+ <parent>
+ <artifactId>root</artifactId>
+ <groupId>org.jboss.seam</groupId>
+ <version>2.1.2-SNAPSHOT</version>
+ </parent>
<contributors>
<contributor>
@@ -74,7 +79,6 @@
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
- <version>3.8.0.GA</version>
</dependency>
<dependency>
<groupId>org.jboss.seam</groupId>
@@ -84,7 +88,6 @@
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
- <version>1.2.14</version>
</dependency>
<dependency>
<groupId>org.jboss.seam</groupId>
@@ -92,32 +95,4 @@
<version>2.1.2-SNAPSHOT</version>
</dependency>
</dependencies>
-
- <build>
-
- <pluginManagement>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration>
- <source>1.6</source>
- <target>1.6</target>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-source-plugin</artifactId>
- <executions>
- <execution>
- <goals>
- <goal>jar</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
-
- </plugins>
- </pluginManagement>
- </build>
- </project>
+</project>
15 years, 9 months
Seam SVN: r10142 - in maven-plugins/trunk: seam-instrument-wicket and 7 other directories.
by seam-commits@lists.jboss.org
Author: cpopetz
Date: 2009-03-10 11:47:08 -0400 (Tue, 10 Mar 2009)
New Revision: 10142
Added:
maven-plugins/trunk/seam-instrument-wicket/
maven-plugins/trunk/seam-instrument-wicket/pom.xml
maven-plugins/trunk/seam-instrument-wicket/src/
maven-plugins/trunk/seam-instrument-wicket/src/main/
maven-plugins/trunk/seam-instrument-wicket/src/main/java/
maven-plugins/trunk/seam-instrument-wicket/src/main/java/org/
maven-plugins/trunk/seam-instrument-wicket/src/main/java/org/jboss/
maven-plugins/trunk/seam-instrument-wicket/src/main/java/org/jboss/seam/
maven-plugins/trunk/seam-instrument-wicket/src/main/java/org/jboss/seam/wicket/
maven-plugins/trunk/seam-instrument-wicket/src/main/java/org/jboss/seam/wicket/InstrumentationMojo.java
Log:
Initial commit of seam-instrument-wicket maven plugin
Property changes on: maven-plugins/trunk/seam-instrument-wicket
___________________________________________________________________
Name: svn:ignore
+ .classpath
.settings
.project
Added: maven-plugins/trunk/seam-instrument-wicket/pom.xml
===================================================================
--- maven-plugins/trunk/seam-instrument-wicket/pom.xml (rev 0)
+++ maven-plugins/trunk/seam-instrument-wicket/pom.xml 2009-03-10 15:47:08 UTC (rev 10142)
@@ -0,0 +1,123 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.jboss.seam</groupId>
+ <artifactId>seam-instrument-wicket</artifactId>
+ <packaging>maven-plugin</packaging>
+ <version>2.1.2-SNAPSHOT</version>
+ <name>Seam Wicket Instrumentation</name>
+ <url>http://www.seamframework.org</url>
+ <description>
+ A maven mojo to instrument wicket components to work with Seam's wicket integration.
+ </description>
+
+ <contributors>
+ <contributor>
+ <name>Clint Popetz</name>
+ </contributor>
+ </contributors>
+
+ <scm>
+ <developerConnection>scm:svn:https://svn.jboss.org/repos/seam/maven-plugins/trunk</developerConnection>
+ <connection>scm:svn:http://anonsvn.jboss.org/repos/seam/maven-plugins</connection>
+ <url>http://fisheye.jboss.org/browse/Seam/maven-plugins</url>
+ </scm>
+
+ <pluginRepositories>
+ <pluginRepository>
+ <id>repository.jboss.org</id>
+ <name>JBoss Repository</name>
+ <url>http://repository.jboss.org/maven2</url>
+ </pluginRepository>
+ </pluginRepositories>
+ <repositories>
+ <repository>
+ <id>repository.jboss.org</id>
+ <name>JBoss Repository</name>
+ <url>http://repository.jboss.org/maven2</url>
+ </repository>
+ </repositories>
+
+ <distributionManagement>
+ <repository>
+ <!-- Copy the dist to the local checkout of the JBoss maven2 repo ${maven.repository.root} -->
+ <!-- It is anticipated that ${maven.repository.root} be set in user's settings.xml -->
+ <!-- todo : replace this with direct svn access once the svnkit providers are available -->
+ <id>repository.jboss.org</id>
+ <url>file://${maven.repository.root}</url>
+ </repository>
+ <snapshotRepository>
+ <id>snapshots.jboss.org</id>
+ <name>JBoss Snapshot Repository</name>
+ <url>dav:https://snapshots.jboss.org/maven2</url>
+ </snapshotRepository>
+ </distributionManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-plugin-api</artifactId>
+ <version>2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-project</artifactId>
+ <version>2.0</version>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>javassist</groupId>
+ <artifactId>javassist</artifactId>
+ <version>3.8.0.GA</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.seam</groupId>
+ <artifactId>jboss-seam-wicket</artifactId>
+ <version>2.1.2-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.14</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.seam</groupId>
+ <artifactId>jboss-seam</artifactId>
+ <version>2.1.2-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ </plugins>
+ </pluginManagement>
+ </build>
+ </project>
Added: maven-plugins/trunk/seam-instrument-wicket/src/main/java/org/jboss/seam/wicket/InstrumentationMojo.java
===================================================================
--- maven-plugins/trunk/seam-instrument-wicket/src/main/java/org/jboss/seam/wicket/InstrumentationMojo.java (rev 0)
+++ maven-plugins/trunk/seam-instrument-wicket/src/main/java/org/jboss/seam/wicket/InstrumentationMojo.java 2009-03-10 15:47:08 UTC (rev 10142)
@@ -0,0 +1,172 @@
+package org.jboss.seam.wicket;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.LoaderClassPath;
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.project.MavenProject;
+import org.jboss.seam.wicket.ioc.JavassistInstrumentor;
+
+/**
+ * This mojo takes classes specified with the "includes" parameter in the plugin configuration
+ * and instruments them with Seam's Wicket JavassistInstrumentor.
+ * @goal instrument
+ * @requiresDependencyResolution
+ * @phase process-classes
+ */
+public class InstrumentationMojo extends AbstractMojo
+{
+ /**
+ * Location of the file.
+ *
+ * @parameter expression="${project.build.directory}/classes"
+ * @required
+ */
+ private File classesDirectory;
+
+ public File getClassesDirectory()
+ {
+ return classesDirectory;
+ }
+
+ public void setClassesDirectory(File classesDirectory)
+ {
+ this.classesDirectory = classesDirectory;
+ }
+
+ /**
+ * Maven project we are building
+ *
+ * @parameter expression="${project}"
+ * @required
+ */
+ private MavenProject project;
+
+ /**
+ * A set of file patterns representing classes to instrument
+ *
+ * @parameter alias="includes"
+ */
+ private String[] includes = new String[0];
+
+ public String[] getIncludes()
+ {
+ return includes;
+ }
+
+ public void setIncludes(String[] includes)
+ {
+ this.includes = includes;
+ }
+
+ /**
+ * @parameter default-value="${project.runtimeClasspathElements}"
+ * @readonly
+ */
+ private List<String> runtimeClassPath;
+
+ /**
+ * Same as above, but compiled regexps
+ */
+ private List<Pattern> mIncludePatterns;
+
+ public void execute() throws MojoExecutionException
+ {
+
+ try
+ {
+ // make sure target/classes has been created
+ if (!classesDirectory.exists())
+ {
+ throw new IllegalStateException("target/classes directory does not exist");
+ }
+
+ ClassPool classPool = new ClassPool();
+ classPool.insertClassPath(classesDirectory.getPath());
+ // append system classpath
+ ClassLoader system = Object.class.getClassLoader();
+ if (system == null)
+ {
+ system = Thread.currentThread().getContextClassLoader();
+ }
+ classPool.insertClassPath(new LoaderClassPath(system));
+
+ for (Object path : project.getCompileClasspathElements())
+ {
+ File dir = new File((String) path);
+ if (dir.exists())
+ {
+ classPool.insertClassPath((String) path);
+ }
+ }
+ for (String path : runtimeClassPath)
+ {
+ classPool.insertClassPath((String) path);
+ }
+
+ mIncludePatterns = new ArrayList<Pattern>();
+ for (String pat : includes)
+ {
+ mIncludePatterns.add(Pattern.compile(pat));
+ }
+
+ Map<String, CtClass> instrumentedClasses = new HashMap<String, CtClass>();
+
+ JavassistInstrumentor instrumentor = new JavassistInstrumentor(classPool);
+
+ List<String> classes = new ArrayList<String>();
+ visitDir(classesDirectory, classes);
+
+ for (String path : classes)
+ {
+ instrumentedClasses.put(path, instrumentor.instrumentClass(filenameToClassname(path)));
+ }
+ for (Map.Entry<String, CtClass> entry : instrumentedClasses.entrySet())
+ {
+ if (entry.getValue().isModified())
+ entry.getValue().writeFile(classesDirectory.getPath());
+ }
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ throw new MojoExecutionException("Error instrumenting wicket code", e);
+ }
+ }
+
+ private void visitDir(File classesDir, List<String> classes)
+ {
+ for (File file : classesDir.listFiles())
+ {
+ if (file.getPath().endsWith(".class"))
+ {
+ for (Pattern pat : mIncludePatterns)
+ {
+ if (pat.matcher(file.getPath()).find())
+ {
+ classes.add(file.getPath());
+ break;
+ }
+ }
+ }
+ else if (file.isDirectory())
+ visitDir(file, classes);
+ }
+ }
+
+ protected String filenameToClassname(String filename)
+ {
+ filename = filename.substring(classesDirectory.getPath().length() + 1);
+ return filename.substring(0, filename.lastIndexOf(".class")).replace('/', '.').replace('\\', '.');
+ }
+
+}
15 years, 9 months
Seam SVN: r10141 - in trunk/src/wicket/org/jboss/seam/wicket: ioc and 1 other directory.
by seam-commits@lists.jboss.org
Author: cpopetz
Date: 2009-03-10 09:39:26 -0400 (Tue, 10 Mar 2009)
New Revision: 10141
Added:
trunk/src/wicket/org/jboss/seam/wicket/SeamEnforceConversationListener.java
Removed:
trunk/src/wicket/org/jboss/seam/wicket/SeamComponentInstantiationListener.java
Modified:
trunk/src/wicket/org/jboss/seam/wicket/WicketComponent.java
trunk/src/wicket/org/jboss/seam/wicket/ioc/ConversationInterceptor.java
Log:
JBSEAM-3724: Wicket NoConversationPage is often ignored
Deleted: trunk/src/wicket/org/jboss/seam/wicket/SeamComponentInstantiationListener.java
===================================================================
--- trunk/src/wicket/org/jboss/seam/wicket/SeamComponentInstantiationListener.java 2009-03-10 13:39:03 UTC (rev 10140)
+++ trunk/src/wicket/org/jboss/seam/wicket/SeamComponentInstantiationListener.java 2009-03-10 13:39:26 UTC (rev 10141)
@@ -1,38 +0,0 @@
-package org.jboss.seam.wicket;
-
-import org.apache.wicket.AbortException;
-import org.apache.wicket.Component;
-import org.apache.wicket.Page;
-import org.apache.wicket.RequestCycle;
-import org.apache.wicket.application.IComponentInstantiationListener;
-import org.jboss.seam.core.Manager;
-import org.jboss.seam.international.StatusMessage;
-import org.jboss.seam.international.StatusMessages;
-
-public class SeamComponentInstantiationListener implements IComponentInstantiationListener
-{
-
- public void onInstantiation(Component component)
- {
- if (!Manager.instance().isLongRunningConversation())
- {
- WicketComponent<?> wicketComponent = WicketComponent.getInstance(component.getClass());
- if (wicketComponent != null)
- {
- Class<? extends Page> noConversationPage = wicketComponent.getNoConversationPage();
- if (noConversationPage != null)
- {
- final RequestCycle cycle = RequestCycle.get();
- StatusMessages.instance().addFromResourceBundleOrDefault(
- StatusMessage.Severity.WARN,
- "org.jboss.seam.NoConversation",
- "The conversation ended or timed"
- );
- cycle.redirectTo(component.getPageFactory().newPage(noConversationPage));
- throw new AbortException();
- }
- }
- }
- }
-
-}
Copied: trunk/src/wicket/org/jboss/seam/wicket/SeamEnforceConversationListener.java (from rev 9819, trunk/src/wicket/org/jboss/seam/wicket/SeamComponentInstantiationListener.java)
===================================================================
--- trunk/src/wicket/org/jboss/seam/wicket/SeamEnforceConversationListener.java (rev 0)
+++ trunk/src/wicket/org/jboss/seam/wicket/SeamEnforceConversationListener.java 2009-03-10 13:39:26 UTC (rev 10141)
@@ -0,0 +1,41 @@
+package org.jboss.seam.wicket;
+
+import org.apache.wicket.AbortException;
+import org.apache.wicket.Component;
+import org.apache.wicket.Page;
+import org.apache.wicket.RequestCycle;
+import org.apache.wicket.application.IComponentOnBeforeRenderListener;
+import org.jboss.seam.core.Manager;
+import org.jboss.seam.international.StatusMessage;
+import org.jboss.seam.international.StatusMessages;
+
+/**
+ * A listener registered by SeamWebApplication which ensures that a long-running conversation exists when a page
+ * annotated with NoConversationPage is rendered
+ *
+ */
+public class SeamEnforceConversationListener implements IComponentOnBeforeRenderListener
+{
+ public void onBeforeRender(Component component)
+ {
+ if (!Manager.instance().isLongRunningConversation())
+ {
+ WicketComponent<?> wicketComponent = WicketComponent.getInstance(component.getClass());
+ if (wicketComponent != null)
+ {
+ Class<? extends Page> noConversationPage = wicketComponent.getNoConversationPage();
+ if (noConversationPage != null)
+ {
+ final RequestCycle cycle = RequestCycle.get();
+ StatusMessages.instance().addFromResourceBundleOrDefault(
+ StatusMessage.Severity.WARN,
+ "org.jboss.seam.NoConversation",
+ "The conversation ended or timed"
+ );
+ cycle.redirectTo(component.getPageFactory().newPage(noConversationPage));
+ throw new AbortException();
+ }
+ }
+ }
+ }
+}
Property changes on: trunk/src/wicket/org/jboss/seam/wicket/SeamEnforceConversationListener.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:mergeinfo
+
Modified: trunk/src/wicket/org/jboss/seam/wicket/WicketComponent.java
===================================================================
--- trunk/src/wicket/org/jboss/seam/wicket/WicketComponent.java 2009-03-10 13:39:03 UTC (rev 10140)
+++ trunk/src/wicket/org/jboss/seam/wicket/WicketComponent.java 2009-03-10 13:39:26 UTC (rev 10141)
@@ -21,6 +21,7 @@
import org.jboss.seam.RequiredException;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Begin;
+import org.jboss.seam.annotations.Conversational;
import org.jboss.seam.annotations.End;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
@@ -367,7 +368,8 @@
method.isAnnotationPresent(End.class) ||
method.isAnnotationPresent(StartTask.class) ||
method.isAnnotationPresent(BeginTask.class) ||
- method.isAnnotationPresent(EndTask.class) )
+ method.isAnnotationPresent(EndTask.class) ||
+ method.isAnnotationPresent(Conversational.class))
{
conversationManagementMembers.add(method);
}
Modified: trunk/src/wicket/org/jboss/seam/wicket/ioc/ConversationInterceptor.java
===================================================================
--- trunk/src/wicket/org/jboss/seam/wicket/ioc/ConversationInterceptor.java 2009-03-10 13:39:03 UTC (rev 10140)
+++ trunk/src/wicket/org/jboss/seam/wicket/ioc/ConversationInterceptor.java 2009-03-10 13:39:26 UTC (rev 10141)
@@ -3,8 +3,14 @@
import java.lang.reflect.Method;
import java.util.Arrays;
+import org.apache.wicket.AbortException;
+import org.apache.wicket.Page;
+import org.apache.wicket.RequestCycle;
+import org.apache.wicket.Session;
+import org.jboss.seam.NoConversationException;
import org.jboss.seam.annotations.ApplicationException;
import org.jboss.seam.annotations.Begin;
+import org.jboss.seam.annotations.Conversational;
import org.jboss.seam.annotations.End;
import org.jboss.seam.annotations.FlushModeType;
import org.jboss.seam.annotations.bpm.BeginTask;
@@ -15,6 +21,8 @@
import org.jboss.seam.core.ConversationPropagation;
import org.jboss.seam.core.Interpolator;
import org.jboss.seam.core.Manager;
+import org.jboss.seam.international.StatusMessage;
+import org.jboss.seam.international.StatusMessages;
import org.jboss.seam.navigation.ConversationIdParameter;
import org.jboss.seam.navigation.Pages;
import org.jboss.seam.pageflow.Pageflow;
@@ -32,11 +40,7 @@
throw new IllegalStateException("begin method invoked from a long-running conversation, try using @Begin(join=true) on method: " + invocationContext.getMember().getName());
}
-
- /*if ( redirectToExistingConversation(invocationContext.getMethod()) )
- {
- return null;
- }*/
+ checkForConversation(invocationContext);
}
}
@@ -134,7 +138,32 @@
invocationContext.getAccessibleObject().isAnnotationPresent(StartTask.class)
);
}
+
+ private void checkForConversation(InvocationContext<T> invocationContext)
+ {
+ if (!Manager.instance().isLongRunningConversation() &&
+ invocationContext.getAccessibleObject().isAnnotationPresent(Conversational.class))
+ {
+ Class<? extends Page> noConversationPage = invocationContext.getComponent().getNoConversationPage();
+ if (noConversationPage != null)
+ {
+ final RequestCycle cycle = RequestCycle.get();
+ StatusMessages.instance().addFromResourceBundleOrDefault(
+ StatusMessage.Severity.WARN,
+ "org.jboss.seam.NoConversation",
+ "The conversation ended or timed"
+ );
+ cycle.redirectTo(Session.get().getPageFactory().newPage(noConversationPage));
+ throw new AbortException();
+ }
+ else
+ {
+ throw new NoConversationException( "no long-running conversation for @Conversational wicket component: " + invocationContext.getComponent().getClass().getName());
+ }
+ }
+ }
+
@SuppressWarnings("deprecation")
private void beginConversationIfNecessary(InvocationContext invocationContext, Object result)
{
15 years, 9 months
Seam SVN: r10140 - trunk/src/wicket/org/jboss/seam/wicket/ioc.
by seam-commits@lists.jboss.org
Author: cpopetz
Date: 2009-03-10 09:39:03 -0400 (Tue, 10 Mar 2009)
New Revision: 10140
Modified:
trunk/src/wicket/org/jboss/seam/wicket/ioc/JavassistInstrumentor.java
Log:
JBSEAM-3981, JBSEAM-3979
Modified: trunk/src/wicket/org/jboss/seam/wicket/ioc/JavassistInstrumentor.java
===================================================================
--- trunk/src/wicket/org/jboss/seam/wicket/ioc/JavassistInstrumentor.java 2009-03-10 13:38:00 UTC (rev 10139)
+++ trunk/src/wicket/org/jboss/seam/wicket/ioc/JavassistInstrumentor.java 2009-03-10 13:39:03 UTC (rev 10140)
@@ -1,5 +1,14 @@
package org.jboss.seam.wicket.ioc;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.security.ProtectionDomain;
+import java.util.HashSet;
+import java.util.Set;
+
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtBehavior;
@@ -17,96 +26,231 @@
import org.jboss.seam.log.Logging;
import org.jboss.seam.wicket.WicketComponent;
+/**
+ * This class is responsible for instrumenting wicket component classes so that
+ * they can be seam-enabled. The exact notion of what "seam-enabled" means is
+ * left to the implementation in WicketComponent and WicketHandler and their
+ * delegate classes, in particular the interceptor chains they create.
+ *
+ * The instrumentations that take place are:
+ *
+ * <ul>
+ * <li> Add a to add a synthetic WicketHandler field similar to:
+ * <pre>
+ * WicketHandler handler = WicketHandler.create(this);
+ * </pre>
+ * as well as a synthetic getter for this field </li>
+ *
+ * <li> Add a static reference to WicketComponent is created, to ensure that the instrumented
+ * class is registered with WicketComponent:
+ * <pre>
+ * static WicketComponent component = new org.jboss.seam.wicket.WicketComponent(ThisClassName.class);
+ * </pre>
+ * </li>
+ * <li> Make the instrumented class implement org.jboss.seam.wicket.ioc.InstrumentedComponent, which includes
+ * adding this method:
+ * <pre>
+ * public InstrumentedComponent getEnclosingInstance()
+ * {
+ * return handler == null ? null : handler.getEnclosingInstance(this);
+ * }</pre></li>
+ * <li>For each non-abstract non-synthetic, non-static method (not constructor) named foobar() in this class, create
+ * a synthetic private instance method, call it foobar$100, which contains the original code from foobar(). Then instrument
+ * foobar to do the following:
+ * <pre>
+ * SomeReturnType foobar(arguments)
+ * {
+ * Method method = OurClass.class.getDeclaredMethod("foobar",argumentSignature);
+ * if (this.handler != null)
+ * this.handler.beforeInvoke(this,method);
+ * SomeReturnType result;
+ * try {
+ * result = foobar$100(arguments);
+ * } catch (Exception e) {
+ * throw new RuntimeException(this.handler == null ? e : this.handler.handleException(this, method, e));
+ * }
+ * if (this.handler != null)
+ * this.handler.affterInvoke(this,method,result);
+ * return SomeReturnType;
+ *}
+ *</pre></li>
+ *
+ * <li>A similar instrumentation occurs for constructors, with the except that a super() or this() call must precede the
+ * invocation of the handler.</li>
+ * </ul>
+ *
+ * This instrumentor can be activated in several ways:
+ * <ul>
+ * <li>The WicketClassLoader will use it to instrument any class in WEB-INF/wicket</li>
+ * <li>The WicketInstrumentationTask (an ant task) will use it to instrument classes specified in ant</li>
+ * <li>The seam-wicket maven plugin will use it to instrument classes specified by maven configuration properties</li>
+ * <li>This class implements the ClassFileTransformer interface from the java.lang.instrument package,
+ * which means it can be specified with -javaagent:path/to/jboss-seam-wicket.jar. In this case, the system
+ * property "org.jboss.seam.wicket.instrumented-packages" should specify a comma-separated list of package names
+ * to instrument</li></ul>
+ *
+ * @see java.lang.instrument.ClassFileTransformer
+ * @see org.jboss.seam.wicket.ioc.WicketClassLoader
+ * @see org.jboss.seam.wicket.ioc.WicketInstrumentationTask
+ * @author pmuir, cpopetz
+ *
+ */
+public class JavassistInstrumentor implements ClassFileTransformer
+{
-public class JavassistInstrumentor
-{
-
private static LogProvider log = Logging.getLogProvider(JavassistInstrumentor.class);
-
+
+ /**
+ * The javassist Classpool, used for obtaining references to needed CtClasses
+ */
private ClassPool classPool;
+ /**
+ * If the constructor is used which specifies a list of packages to instrument, for example when
+ * using the -javaagent startup option, this is the list of packages
+ */
+ private Set<String> packagesToInstrument;
+
+ /**
+ * The CtClass for the InstrumentedComponent interface
+ */
+ private CtClass instrumentedComponent;
+
+
public JavassistInstrumentor(ClassPool classPool)
{
- this.classPool = classPool;
+ this.classPool = classPool;
+ try
+ {
+ instrumentedComponent = classPool.get(InstrumentedComponent.class.getName());
+ }
+ catch (NotFoundException e)
+ {
+ throw new RuntimeException(e);
+ }
}
-
+
+ public JavassistInstrumentor(ClassPool classPool, Set<String> packagesToInstrument)
+ {
+ this(classPool);
+ this.packagesToInstrument = packagesToInstrument;
+ }
+
public CtClass instrumentClass(String className) throws NotFoundException, CannotCompileException
{
log.debug("Instrumenting " + className);
CtClass implementation = classPool.get(className);
if (isInstrumentable(implementation))
{
- CtClass handlerClass = classPool.get(WicketHandler.class.getName());
- CtClass componentClass = classPool.get(WicketComponent.class.getName());
-
- CtField handlerField = new CtField(handlerClass, "handler", implementation);
- Initializer handlerInitializer = Initializer.byCall(handlerClass, "create");
- implementation.addField(handlerField, handlerInitializer);
-
- CtField wicketComponentField = new CtField(componentClass,"component",implementation);
- wicketComponentField.setModifiers(Modifier.STATIC);
- Initializer componentInit = Initializer.byExpr("new org.jboss.seam.wicket.WicketComponent(" + className + ".class)");
- implementation.addField(wicketComponentField,componentInit);
+ instrumentClass(implementation);
+ }
+ return implementation;
+ }
+ public CtClass instrumentClass(byte[] bytes) throws IOException, RuntimeException, NotFoundException, CannotCompileException
+ {
+ CtClass clazz = classPool.makeClass(new ByteArrayInputStream(bytes));
+ if (isInstrumentable(clazz))
+ {
+ instrumentClass(clazz);
+ return clazz;
+ }
+ else
+ {
+ return null;
+ }
+ }
- CtClass exception = classPool.get(Exception.class.getName());
-
- CtClass instrumentedComponent = classPool.get(InstrumentedComponent.class.getName());
- implementation.addInterface(instrumentedComponent);
- CtMethod getHandlerMethod = CtNewMethod.getter("getHandler", handlerField);
- CtMethod getEnclosingInstance = CtNewMethod.make("public " + InstrumentedComponent.class.getName() +" getEnclosingInstance() { return handler == null ? null : handler.getEnclosingInstance(this); }", implementation);
- implementation.addMethod(getEnclosingInstance);
- implementation.addMethod(getHandlerMethod);
-
- for (CtMethod method : implementation.getDeclaredMethods())
+ /**
+ * The main entry point for instrumenting a given class. Note that this will not check if the class is instrumentable,
+ * but will assume that you have.
+ * @param implementation The CtClass representing the class to instrument.
+ * @throws NotFoundException
+ * @throws CannotCompileException
+ */
+ public void instrumentClass(CtClass implementation) throws NotFoundException, CannotCompileException
+ {
+ String className = implementation.getName();
+ CtClass handlerClass = classPool.get(WicketHandler.class.getName());
+ CtClass componentClass = classPool.get(WicketComponent.class.getName());
+
+ CtField handlerField = new CtField(handlerClass, "handler", implementation);
+ Initializer handlerInitializer = Initializer.byCall(handlerClass, "create");
+ implementation.addField(handlerField, handlerInitializer);
+
+ CtField wicketComponentField = new CtField(componentClass, "component", implementation);
+ wicketComponentField.setModifiers(Modifier.STATIC);
+ Initializer componentInit = Initializer.byExpr("new org.jboss.seam.wicket.WicketComponent(" + className + ".class)");
+ implementation.addField(wicketComponentField, componentInit);
+
+ CtClass exception = classPool.get(Exception.class.getName());
+
+ implementation.addInterface(instrumentedComponent);
+ CtMethod getHandlerMethod = CtNewMethod.getter("getHandler", handlerField);
+ CtMethod getEnclosingInstance = CtNewMethod.make("public " + InstrumentedComponent.class.getName() + " getEnclosingInstance() { return handler == null ? null : handler.getEnclosingInstance(this); }", implementation);
+ implementation.addMethod(getEnclosingInstance);
+ implementation.addMethod(getHandlerMethod);
+
+ for (CtMethod method : implementation.getDeclaredMethods())
+ {
+ if (!Modifier.isStatic(method.getModifiers()) && !Modifier.isAbstract(method.getModifiers()))
{
- if (!Modifier.isStatic(method.getModifiers()) && !Modifier.isAbstract(method.getModifiers()))
+ if (!("getHandler".equals(method.getName()) || "getEnclosingInstance".equals(method.getName())))
{
- if (!("getHandler".equals(method.getName()) || "getEnclosingInstance".equals(method.getName())))
- {
- String newName = implementation.makeUniqueName(method.getName());
-
- CtMethod newMethod = CtNewMethod.copy(method, newName, implementation, null);
- newMethod.setModifiers(Modifier.PRIVATE);
- implementation.addMethod(newMethod);
- method.setBody(createBody(implementation, method, newMethod));
- log.trace("instrumented method " + method.getName());
- }
+ String newName = implementation.makeUniqueName(method.getName());
+
+ CtMethod newMethod = CtNewMethod.copy(method, newName, implementation, null);
+ newMethod.setModifiers(Modifier.PRIVATE);
+ implementation.addMethod(newMethod);
+ method.setBody(createBody(implementation, method, newMethod));
+ log.trace("instrumented method " + method.getName());
}
}
- for (CtConstructor constructor : implementation.getConstructors())
+ }
+ for (CtConstructor constructor : implementation.getConstructors())
+ {
+ if (constructor.isConstructor())
{
- if (constructor.isConstructor())
{
- {
- String constructorObject = createConstructorObject(className,constructor);
- constructor.insertBeforeBody(constructorObject + "handler.beforeInvoke(this, constructor);");
- constructor.addCatch("{" + constructorObject + "throw new RuntimeException(handler.handleException(this, constructor, e));}", exception, "e");
- constructor.insertAfter(constructorObject + "handler.afterInvoke(this, constructor);");
- log.trace("instrumented constructor " + constructor.getName());
- }
+ String constructorObject = createConstructorObject(className, constructor);
+ constructor.insertBeforeBody(constructorObject + "handler.beforeInvoke(this, constructor);");
+ constructor.addCatch("{" + constructorObject + "throw new RuntimeException(handler.handleException(this, constructor, e));}", exception, "e");
+ constructor.insertAfter(constructorObject + "handler.afterInvoke(this, constructor);");
+ log.trace("instrumented constructor " + constructor.getName());
}
}
}
- return implementation;
}
-
-
+
+ /**
+ * Create the body of the synthetic method
+ * @param clazz in this class
+ * @param method for this method
+ * @param newMethod the synthetic method
+ * @return the string of code for the body
+ * @throws NotFoundException
+ */
private static String createBody(CtClass clazz, CtMethod method, CtMethod newMethod) throws NotFoundException
{
- String src = "{" + createMethodObject(clazz,method) + "if (this.handler != null) this.handler.beforeInvoke(this, method);" + createMethodDelegation(newMethod) + "if (this.handler != null) result = ($r) this.handler.afterInvoke(this, method, ($w) result); return ($r) result;}";
+ String src = "{" + createMethodObject(clazz, method) + "if (this.handler != null) this.handler.beforeInvoke(this, method);" + createMethodDelegation(newMethod) + "if (this.handler != null) result = ($r) this.handler.afterInvoke(this, method, ($w) result); return ($r) result;}";
log.trace("Creating method " + clazz.getName() + "." + newMethod.getName() + "(" + newMethod.getSignature() + ")" + src);
return src;
}
-
+
+ /**
+ * Create the code for delegating to a given method, including handling exceptions
+ * @param method The method to which we are delegating
+ * @return the string of code for the delegation
+ * @throws NotFoundException
+ */
private static String createMethodDelegation(CtMethod method) throws NotFoundException
{
- CtClass returnType = method.getReturnType();
+ CtClass returnType = method.getReturnType();
if (returnType.equals(CtClass.voidType))
{
return "Object result = null; " + wrapInExceptionHandler(method.getName() + "($$);");
- }
+ }
else
{
String src = returnType.getName() + " result;";
@@ -114,29 +258,54 @@
return src;
}
}
-
+
+ /**
+ * Wrap some code in an exception handler that uses the WicketHandler to handle the exception
+ * @param src The code to wrap
+ * @return The wrapped code
+ */
private static String wrapInExceptionHandler(String src)
{
return "try {" + src + "} catch (Exception e) { throw new RuntimeException(this.handler == null ? e : this.handler.handleException(this, method, e)); }";
}
-
+
+ /**
+ * Create an arrray of parameter types for a given method or constructor.
+ * @param behavior The method or constructor
+ * @return The source string representing the declaration and initialization of the parameterTypes array
+ * @throws NotFoundException
+ */
private static String createParameterTypesArray(CtBehavior behavior) throws NotFoundException
{
String src = "Class[] parameterTypes = new Class[" + behavior.getParameterTypes().length + "];";
for (int i = 0; i < behavior.getParameterTypes().length; i++)
{
- src += "parameterTypes[" + i + "] = " + behavior.getParameterTypes()[i].getName() + ".class;";
+ src += "parameterTypes[" + i + "] = " + behavior.getParameterTypes()[i].getName() + ".class;";
}
return src;
}
-
+
+ /**
+ * Create the code for initializing a Method object for a given method
+ * @param clazz The class in which the method can be looked up
+ * @param method The method in question
+ * @return Source for looking up the method and declaring/initializing the "method" local variable
+ * @throws NotFoundException
+ */
private static String createMethodObject(CtClass clazz, CtMethod method) throws NotFoundException
{
String src = createParameterTypesArray(method);
- src += "java.lang.reflect.Method method = " + clazz.getName() +".class.getDeclaredMethod(\""+ method.getName() + "\", parameterTypes);";
+ src += "java.lang.reflect.Method method = " + clazz.getName() + ".class.getDeclaredMethod(\"" + method.getName() + "\", parameterTypes);";
return src;
}
-
+
+ /**
+ * Create the code for initializing a Constructor object for a given constructor
+ * @param className The name of the class in which the constructor can be looked up
+ * @param constructor The constructor to look up
+ * @return Source for looking up the constructor and declaring/initializing the "consturctor" local variable
+ * @throws NotFoundException
+ */
private static String createConstructorObject(String className, CtConstructor constructor) throws NotFoundException
{
String src = createParameterTypesArray(constructor);
@@ -144,29 +313,121 @@
return src;
}
- private static boolean isInstrumentable(CtClass clazz)
+ /**
+ * Returns true if the given class can be instrumented. This will return false if:
+ * <ul>
+ * <li> The class is an interface or an enum
+ * <li> The class is annotated with Seam's @Name annotationa or is a non-static inner class of a @Named class
+ * <li> The class is already instrumented. We check this by checking if it already implements the InstrumentedComponent
+ * interface
+ * </ul>
+ * @param clazz The class to check
+ * @return
+ */
+ private boolean isInstrumentable(CtClass clazz)
{
int modifiers = clazz.getModifiers();
if (Modifier.isInterface(modifiers) || Modifier.isEnum(modifiers))
{
return false;
}
-
- try
- {
- for (Object a : clazz.getAnnotations())
- {
- if (a instanceof Name)
- {
- return false;
- }
- }
+
+ try
+ {
+ // do not instrument @Named components or nested non-static classes
+ // inside named components
+ CtClass checkName = clazz;
+ do
+ {
+ for (Object a : checkName.getAnnotations())
+ {
+ if (a instanceof Name)
+ {
+ return false;
+ }
+ }
+ checkName = Modifier.isStatic(clazz.getModifiers()) ? null : checkName.getDeclaringClass();
+ }
+ while (checkName != null);
+
+ // do not instrument something we've already instrumented.
+ // can't use 'isSubtype' because the superclass may be instrumented
+ // while we are not
+ for (String inf : clazz.getClassFile2().getInterfaces())
+ if (inf.equals(instrumentedComponent.getName()))
+ return false;
}
- catch (ClassNotFoundException e)
+ catch (Exception e)
{
throw new RuntimeException(e);
}
+
return true;
}
-
+
+ /**
+ * This is the implementation of the ClassFileTransformer interface.
+ * @see java.lang.instrument.ClassFileTransformer
+ */
+ public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException
+ {
+ int index = className.lastIndexOf("/");
+ if (index < 1)
+ return null;
+ String packageName = className.substring(0, index);
+ if (!packagesToInstrument.contains(packageName) || className.contains("_javassist_"))
+ {
+ return null;
+ }
+ try
+ {
+ CtClass result = instrumentClass(classfileBuffer);
+ if (result == null)
+ return null;
+ else
+ return result.toBytecode();
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * This premain will be called if the vm is started with -javaagent:/path/to/jar/with/this/class
+ */
+ public static void premain(String args, Instrumentation instrumentation)
+ {
+ initAgent(instrumentation);
+ }
+
+ /**
+ * This premain will be called if the vm is told to use this agent after startup, which is done
+ * in a vm-dependent way
+ */
+ public static void agentmain(String args, Instrumentation instrumentation)
+ {
+ initAgent(instrumentation);
+ }
+
+ /**
+ * Set up instrumentation. This adds ourselves as a transformer to the instrumentation, and
+ * loads the set of packages to transform from the "org.jboss.seam.wicket.instrumented-packages"
+ * System property.
+ */
+ private static void initAgent(Instrumentation instrumentation)
+ {
+ Set<String> packagesToInstrument = new HashSet<String>();
+ String list = System.getProperty("org.jboss.seam.wicket.instrumented-packages");
+ if (list == null)
+ return;
+ for (String packageName : list.split(","))
+ {
+ packagesToInstrument.add(packageName.replaceAll("\\.", "/"));
+ }
+
+ ClassPool classPool = new ClassPool();
+ classPool.appendSystemPath();
+ instrumentation.addTransformer(new JavassistInstrumentor(classPool, packagesToInstrument));
+ }
}
15 years, 9 months
Seam SVN: r10139 - in trunk: src/wicket/org/jboss/seam/wicket and 1 other directories.
by seam-commits@lists.jboss.org
Author: cpopetz
Date: 2009-03-10 09:38:00 -0400 (Tue, 10 Mar 2009)
New Revision: 10139
Added:
trunk/src/wicket/org/jboss/seam/wicket/SeamWebSession.java
Removed:
trunk/src/wicket/org/jboss/seam/wicket/web/WicketRedirectFilter.java
Modified:
trunk/build/root.pom.xml
trunk/src/wicket/org/jboss/seam/wicket/SeamWebApplication.java
Log:
JBSEAM-3181: Add conversation management metadata to Wicket component model
JBSEAM-3980: Move Seam session subclass to its own top level class
Modified: trunk/build/root.pom.xml
===================================================================
--- trunk/build/root.pom.xml 2009-03-10 13:27:54 UTC (rev 10138)
+++ trunk/build/root.pom.xml 2009-03-10 13:38:00 UTC (rev 10139)
@@ -39,7 +39,7 @@
<!-- Externalize some version numbers here -->
<properties>
<version.richfaces>3.3.0.GA</version.richfaces>
- <version.wicket>1.3.3</version.wicket>
+ <version.wicket>1.3-SNAPSHOT</version.wicket>
<version.drools>4.0.4</version.drools>
</properties>
Modified: trunk/src/wicket/org/jboss/seam/wicket/SeamWebApplication.java
===================================================================
--- trunk/src/wicket/org/jboss/seam/wicket/SeamWebApplication.java 2009-03-10 13:27:54 UTC (rev 10138)
+++ trunk/src/wicket/org/jboss/seam/wicket/SeamWebApplication.java 2009-03-10 13:38:00 UTC (rev 10139)
@@ -2,30 +2,24 @@
import javax.servlet.http.HttpServletRequest;
-import org.apache.wicket.IRedirectListener;
+import org.apache.wicket.IRequestTarget;
+import org.apache.wicket.MetaDataKey;
+import org.apache.wicket.Page;
import org.apache.wicket.Request;
import org.apache.wicket.RequestCycle;
import org.apache.wicket.Response;
import org.apache.wicket.Session;
-import org.apache.wicket.behavior.IBehaviorListener;
-import org.apache.wicket.markup.html.form.IFormSubmitListener;
-import org.apache.wicket.markup.html.form.IOnChangeListener;
-import org.apache.wicket.markup.html.link.ILinkListener;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.protocol.http.WebRequest;
import org.apache.wicket.protocol.http.WebRequestCycle;
import org.apache.wicket.protocol.http.WebRequestCycleProcessor;
import org.apache.wicket.protocol.http.WebResponse;
-import org.apache.wicket.protocol.http.WebSession;
-import org.apache.wicket.protocol.http.request.WebRequestCodingStrategy;
-import org.apache.wicket.request.IRequestCodingStrategy;
import org.apache.wicket.request.IRequestCycleProcessor;
-import org.apache.wicket.request.target.component.IBookmarkablePageRequestTarget;
-import org.apache.wicket.request.target.component.listener.IListenerInterfaceRequestTarget;
+import org.apache.wicket.request.target.component.BookmarkablePageRequestTarget;
+import org.apache.wicket.request.target.component.IPageRequestTarget;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.contexts.Lifecycle;
import org.jboss.seam.contexts.ServletLifecycle;
-import org.jboss.seam.core.Conversation;
import org.jboss.seam.core.ConversationPropagation;
import org.jboss.seam.core.Events;
import org.jboss.seam.core.Manager;
@@ -38,7 +32,7 @@
/**
* The base class for Seam Web Applications
*
- * @author Pete Muir
+ * @author Pete Muir, Clint Popetz
*
*/
public abstract class SeamWebApplication extends WebApplication
@@ -66,85 +60,57 @@
/**
* Custom session with invalidation override. We can't just let Wicket
* invalidate the session as Seam might have to do some cleaning up to do.
+ * We provide SeamWebSession as a separate class to allow for user subclasssing.
*/
@Override
public Session newSession(Request request, Response response)
{
- return new WebSession(request)
- {
-
- @Override
- public void invalidate()
- {
- org.jboss.seam.web.Session.getInstance().invalidate();
- }
-
- @Override
- public void invalidateNow()
- {
- // sorry, can't support this with Seam
- org.jboss.seam.web.Session.getInstance().invalidate();
- }
- };
+ return new SeamWebSession(request);
}
+
+ /**
+ * This is the key we will use to to store the conversation metadata in the wicket page.
+ */
+ private static MetaDataKey CID = new MetaDataKey(String.class) { };
- @Override
+
/**
* Seam's hooks into Wicket. Required for proper functioning
*/
+ @Override
protected IRequestCycleProcessor newRequestCycleProcessor()
{
return new WebRequestCycleProcessor()
{
+ /**
+ * If a long running conversation has been started, store its id into page metadata
+ */
@Override
- protected IRequestCodingStrategy newRequestCodingStrategy()
+ public void respond(RequestCycle requestCycle)
{
- return new WebRequestCodingStrategy()
+ super.respond(requestCycle);
+ if (Manager.instance().isLongRunningConversation())
{
- @Override
- protected CharSequence encode(RequestCycle requestCycle, final IListenerInterfaceRequestTarget requestTarget)
+ Page page = RequestCycle.get().getResponsePage();
+ if (page != null)
{
- String name = requestTarget.getRequestListenerInterface().getName();
- CharSequence url = super.encode(requestCycle, requestTarget);
- if ( Manager.instance().isReallyLongRunningConversation() && (
- IFormSubmitListener.INTERFACE.getName().equals(name) ||
- ILinkListener.INTERFACE.getName().equals(name) ||
- IBehaviorListener.INTERFACE.getName().equals(name) ||
- IOnChangeListener.INTERFACE.getName().equals(name) ||
- IRedirectListener.INTERFACE.getName().equals(name) ))
- {
- // TODO Do this nicely
- StringBuilder stringBuilder = new StringBuilder(url);
- stringBuilder.append("&" + Manager.instance().getConversationIdParameter() + "=" + Conversation.instance().getId());
- url = stringBuilder.subSequence(0, stringBuilder.length());
- }
-
- return url;
+ page.setMetaData(CID, Manager.instance().getCurrentConversationId());
}
-
- @Override
- protected CharSequence encode(RequestCycle requestCycle, IBookmarkablePageRequestTarget requestTarget)
- {
- // TODO Do this nicely
- StringBuilder stringBuilder = new StringBuilder(super.encode(requestCycle, requestTarget));
- if (Manager.instance().isLongRunningConversation())
- {
- stringBuilder.append("&" + Manager.instance().getConversationIdParameter() + "=" + Conversation.instance().getId());
- }
- return stringBuilder.subSequence(0, stringBuilder.length());
- }
- };
+ }
}
};
}
+ /**
+ * Override to set up seam security, seam status messages, and add the SeamEnforceConversationListener
+ */
@Override
protected void init()
{
super.init();
inititializeSeamSecurity();
initializeSeamStatusMessages();
- addComponentInstantiationListener(new SeamComponentInstantiationListener());
+ addComponentOnBeforeRenderListener(new SeamEnforceConversationListener());
}
/**
@@ -160,7 +126,7 @@
}
/**
- * Add Seam status message transport support to youur app.
+ * Add Seam status message transport support to your app.
*/
protected void initializeSeamStatusMessages()
{
@@ -182,7 +148,6 @@
/**
* A WebRequestCycle that sets up seam requests. Essentially this
* is similiar to the work of ContextualHttpServletRequest, but using the wicket API
- * @author cpopetz
*
*/
protected static class SeamWebRequestCycle extends WebRequestCycle {
@@ -192,7 +157,40 @@
super(application, request, response);
}
+ /**
+ * Override this so that we can pull out the conversation id from page metadata
+ * when a new page is chosen as the target
+ */
@Override
+ protected void onRequestTargetSet(IRequestTarget target)
+ {
+ super.onRequestTargetSet(target);
+ Page page = null;
+ if (target instanceof BookmarkablePageRequestTarget)
+ {
+ page = ((BookmarkablePageRequestTarget)target).getPage();
+ }
+ else if (target instanceof IPageRequestTarget)
+ {
+ page = ((IPageRequestTarget)target).getPage();
+ }
+ if (page != null)
+ {
+ String cid = (String) page.getMetaData(CID);
+ if (cid != null)
+ {
+ ConversationPropagation cp = ConversationPropagation.instance();
+ cp.setConversationId(cid);
+ Manager.instance().restoreConversation();
+ }
+ }
+ }
+
+ /**
+ * Override to destroy the old seam contexts if we are destroying lazily and they still exist, and
+ * to set up the new seam contexts.
+ */
+ @Override
protected void onBeginRequest()
{
HttpServletRequest httpRequest = ((WebRequest)request).getHttpServletRequest();
@@ -221,10 +219,12 @@
Events.instance().raiseEvent("org.jboss.seam.wicket.beforeRequest");
}
+ /**
+ * Override to tear down seam contexts unless we are destroying lazily
+ */
@Override
protected void onEndRequest()
{
- // TODO Auto-generated method stub
try
{
super.onEndRequest();
@@ -239,6 +239,9 @@
}
}
+ /**
+ * The actual work of destroying the seam contexts.
+ */
private void destroyContexts()
{
try {
Added: trunk/src/wicket/org/jboss/seam/wicket/SeamWebSession.java
===================================================================
--- trunk/src/wicket/org/jboss/seam/wicket/SeamWebSession.java (rev 0)
+++ trunk/src/wicket/org/jboss/seam/wicket/SeamWebSession.java 2009-03-10 13:38:00 UTC (rev 10139)
@@ -0,0 +1,32 @@
+package org.jboss.seam.wicket;
+
+import org.apache.wicket.Request;
+import org.apache.wicket.protocol.http.WebSession;
+
+/**
+ * This subclass of WebSession exists so that calls to invalidate the wicket session
+ * result in a delegation to the seam session invalidation code.
+ * @author cpopetz
+ *
+ */
+public class SeamWebSession extends WebSession
+{
+ public
+ SeamWebSession(Request request)
+ {
+ super(request);
+ }
+
+ @Override
+ public void invalidate()
+ {
+ org.jboss.seam.web.Session.getInstance().invalidate();
+ }
+
+ @Override
+ public void invalidateNow()
+ {
+ // sorry, can't support this with Seam
+ org.jboss.seam.web.Session.getInstance().invalidate();
+ }
+}
\ No newline at end of file
Deleted: trunk/src/wicket/org/jboss/seam/wicket/web/WicketRedirectFilter.java
===================================================================
--- trunk/src/wicket/org/jboss/seam/wicket/web/WicketRedirectFilter.java 2009-03-10 13:27:54 UTC (rev 10138)
+++ trunk/src/wicket/org/jboss/seam/wicket/web/WicketRedirectFilter.java 2009-03-10 13:38:00 UTC (rev 10139)
@@ -1,63 +0,0 @@
-package org.jboss.seam.wicket.web;
-
-import static org.jboss.seam.ScopeType.APPLICATION;
-import static org.jboss.seam.annotations.Install.FRAMEWORK;
-
-import java.io.IOException;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpServletResponseWrapper;
-
-import org.apache.wicket.Application;
-import org.jboss.seam.annotations.Install;
-import org.jboss.seam.annotations.Name;
-import org.jboss.seam.annotations.Scope;
-import org.jboss.seam.annotations.intercept.BypassInterceptors;
-import org.jboss.seam.annotations.web.Filter;
-import org.jboss.seam.contexts.Contexts;
-import org.jboss.seam.web.AbstractFilter;
-import org.jboss.seam.wicket.WicketManager;
-
-/**
- * Disable the redirect filter when using Wicket (as JSF is an EE library, we
- * can't rely on classDependencies to disable it)
- *
- * @author
- */
-@Scope(APPLICATION)
-@Name("org.jboss.seam.wicket.web.redirectFilter")
-@Install(precedence = FRAMEWORK, classDependencies="org.apache.wicket.Application")
-@BypassInterceptors
-@Filter
-public class WicketRedirectFilter extends AbstractFilter
-{
-
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain chain) throws IOException, ServletException
- {
- chain.doFilter( request, wrapResponse( (HttpServletResponse) response ) );
- }
-
- private static ServletResponse wrapResponse(HttpServletResponse response)
- {
- return new HttpServletResponseWrapper(response)
- {
- @Override
- public void sendRedirect(String url) throws IOException
- {
- if ( Application.exists() && Contexts.isEventContextActive())
- {
- if ( Contexts.isConversationContextActive() )
- {
- url = WicketManager.instance().appendConversationIdFromRedirectFilter(url);
- }
- }
- super.sendRedirect(url);
- }
- };
- }
-}
15 years, 9 months