[jboss-cvs] JBoss Profiler SVN: r549 - in branches/JBossProfiler2: doc/userguide/en/modules and 5 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Sun Jun 21 13:24:31 EDT 2009
Author: jesper.pedersen
Date: 2009-06-21 13:24:30 -0400 (Sun, 21 Jun 2009)
New Revision: 549
Added:
branches/JBossProfiler2/src/etc/precompiler-manifest.mf
branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/
branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/ArchiveUtil.java
branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/ClassInstrumenter.java
branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/ClassScanner.java
branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/ExtensionScanner.java
branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/FileUtil.java
branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/JarScanner.java
branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/Precompiler.java
branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/SizeComparator.java
branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/package.html
Modified:
branches/JBossProfiler2/build.xml
branches/JBossProfiler2/doc/userguide/en/modules/client.xml
branches/JBossProfiler2/doc/userguide/en/modules/configuration.xml
branches/JBossProfiler2/src/etc/jboss-profiler.properties
branches/JBossProfiler2/src/main/org/jboss/profiler/agent/Agent.java
branches/JBossProfiler2/src/main/org/jboss/profiler/agent/ClassUtil.java
branches/JBossProfiler2/src/main/org/jboss/profiler/client/CombinedFrameInfo.java
branches/JBossProfiler2/src/main/org/jboss/profiler/client/SnapshotUtil.java
branches/JBossProfiler2/src/main/org/jboss/profiler/client/TimedClassInfo.java
branches/JBossProfiler2/src/main/org/jboss/profiler/shared/ClassInfo.java
branches/JBossProfiler2/src/main/org/jboss/profiler/shared/MethodInfo.java
Log:
[JBPROFILER-82] Precompiler
Modified: branches/JBossProfiler2/build.xml
===================================================================
--- branches/JBossProfiler2/build.xml 2009-06-16 01:51:25 UTC (rev 548)
+++ branches/JBossProfiler2/build.xml 2009-06-21 17:24:30 UTC (rev 549)
@@ -25,6 +25,7 @@
<property name="jboss-profiler-client.jar" value="jboss-profiler-client.jar"/>
<property name="jboss-profiler-embedded.jar" value="jboss-profiler-embedded.jar"/>
<property name="jboss-profiler-plugins.jar" value="jboss-profiler-plugins.jar"/>
+ <property name="jboss-profiler-precompiler.jar" value="jboss-profiler-precompiler.jar"/>
<property name="jboss-profiler-test.jar" value="jboss-profiler-test.jar"/>
<property name="jboss-profiler.war" value="jboss-profiler.war"/>
@@ -243,6 +244,36 @@
</target>
<!-- =================================================================== -->
+ <!-- Precompiler -->
+ <!-- =================================================================== -->
+ <target name="precompiler" depends="prepare">
+ <delete dir="${build.dir}"/>
+ <mkdir dir="${build.dir}"/>
+ <javac
+ destdir="${build.dir}"
+ classpathref="class.path"
+ debug="on"
+ deprecation="on"
+ optimize="off"
+ source="1.5"
+ target="1.5"
+ >
+ <src path="${src.main.dir}"/>
+ </javac>
+ <copy todir="${build.dir}">
+ <fileset dir="${etc.dir}">
+ <include name="**/log4j.xml"/>
+ </fileset>
+ </copy>
+
+ <jar destfile="${dist.dir}/${jboss-profiler-precompiler.jar}"
+ basedir="${build.dir}"
+ manifest="${etc.dir}/precompiler-manifest.mf"
+ includes="org/jboss/profiler/agent/**,org/jboss/profiler/client/precompiler/**,org/jboss/profiler/shared/**,**/*.xml"
+ excludes="**/*.java"/>
+ </target>
+
+ <!-- =================================================================== -->
<!-- Web -->
<!-- =================================================================== -->
<target name="web" depends="prepare">
@@ -406,7 +437,7 @@
<!-- =================================================================== -->
<!-- Dist -->
<!-- =================================================================== -->
- <target name="dist" depends="agent,connectors,ant,client,embedded,plugins,test,sar">
+ <target name="dist" depends="agent,connectors,ant,client,embedded,plugins,precompiler,test,sar">
<copy todir="${dist.dir}">
<fileset dir="${lib.dir}">
<include name="**/*.jar"/>
Modified: branches/JBossProfiler2/doc/userguide/en/modules/client.xml
===================================================================
--- branches/JBossProfiler2/doc/userguide/en/modules/client.xml 2009-06-16 01:51:25 UTC (rev 548)
+++ branches/JBossProfiler2/doc/userguide/en/modules/client.xml 2009-06-21 17:24:30 UTC (rev 549)
@@ -278,4 +278,27 @@
</programlisting>
</section>
+ <section id="precompiler">
+ <title>Using the precompiler</title>
+ <warning>The JBoss Profiler precompiler will overwrite the JAR files in your application, so
+ make sure that you keep a copy of the original files.</warning>
+
+ <para>The JBoss Profiler precompiler will precompile the JAR archives in the specifed directory
+ with instrumentation information used by the agent. This allows you to start up your
+ application quicker.</para>
+ <para>The precompiler is run using the following command:</para>
+ <programlisting>
+java -Xmx1024m -jar jboss-profiler-precompiler.jar \
+ <includes> <excludes> <visibility> <file|directory>
+ </programlisting>
+ <para>The includes, excludes and visibility flags are in the same format as the flags for the agent.
+ An example:</para>
+ <programlisting>
+java -Xmx1024m -jar jboss-profiler-precompiler.jar \
+ com.mycompany.* com.mycompany.highperformance.*,* private ~/myapplication
+ </programlisting>
+ <para>The precompiler will output any classes it can't precompile due to missing dependencies and the
+ statistics for the run.</para>
+ </section>
+
</chapter>
Modified: branches/JBossProfiler2/doc/userguide/en/modules/configuration.xml
===================================================================
--- branches/JBossProfiler2/doc/userguide/en/modules/configuration.xml 2009-06-16 01:51:25 UTC (rev 548)
+++ branches/JBossProfiler2/doc/userguide/en/modules/configuration.xml 2009-06-21 17:24:30 UTC (rev 549)
@@ -30,6 +30,13 @@
</entry>
</row>
<row>
+ <entry>precompiled</entry>
+ <entry>
+ <para>Use precompiled archives.</para>
+ <para>[yes|no] default: no.</para>
+ </entry>
+ </row>
+ <row>
<entry>cpu</entry>
<entry>
<para>Enable / disable CPU profiling.</para>
Modified: branches/JBossProfiler2/src/etc/jboss-profiler.properties
===================================================================
--- branches/JBossProfiler2/src/etc/jboss-profiler.properties 2009-06-16 01:51:25 UTC (rev 548)
+++ branches/JBossProfiler2/src/etc/jboss-profiler.properties 2009-06-21 17:24:30 UTC (rev 549)
@@ -1,4 +1,5 @@
enable=yes
+precompiled=no
cpu=yes
memory=yes
includes=org.jboss.profiler.*
Added: branches/JBossProfiler2/src/etc/precompiler-manifest.mf
===================================================================
--- branches/JBossProfiler2/src/etc/precompiler-manifest.mf (rev 0)
+++ branches/JBossProfiler2/src/etc/precompiler-manifest.mf 2009-06-21 17:24:30 UTC (rev 549)
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: org.jboss.profiler.client.precompiler.Precompiler
+Class-Path: jboss-profiler-precompiler.jar javassist.jar jboss-common.jar log4j.jar
Modified: branches/JBossProfiler2/src/main/org/jboss/profiler/agent/Agent.java
===================================================================
--- branches/JBossProfiler2/src/main/org/jboss/profiler/agent/Agent.java 2009-06-16 01:51:25 UTC (rev 548)
+++ branches/JBossProfiler2/src/main/org/jboss/profiler/agent/Agent.java 2009-06-21 17:24:30 UTC (rev 549)
@@ -63,6 +63,9 @@
/** Enabled */
private static boolean enabled = true;
+ /** Precompiled */
+ private static boolean precompiled = false;
+
/** CPU */
private static boolean cpu = true;
@@ -203,6 +206,7 @@
parse(properties.getProperty("includes"), properties.getProperty("excludes"));
enabled = parseBoolean(properties.getProperty("enable"), true);
+ precompiled = parseBoolean(properties.getProperty("precompiled"), false);
cpu = parseBoolean(properties.getProperty("cpu"), true);
memory = parseBoolean(properties.getProperty("memory"), true);
remote = parseBoolean(properties.getProperty("remote"), true);
@@ -454,6 +458,14 @@
}
/**
+ * Is the profiler in precompiled mode ?
+ * @return True if the profiler is in precompiled mode; otherwise false
+ */
+ public static boolean isPrecompiled() {
+ return precompiled;
+ }
+
+ /**
* Is the CPU profiling enabled ?
* @return True if enabled; otherwise false
*/
@@ -513,7 +525,7 @@
* @param className The class name
* @return True if the class is approved; otherwise false
*/
- private static boolean approve(String className) {
+ static boolean approve(String className) {
// We can't profile the profiler, Java / Sun classes
// nor Javassist
if (className.startsWith("org/jboss/profiler/agent/") ||
@@ -634,7 +646,7 @@
* @param v The visibility
*/
public static void addClasses(String classes, Visibility v) {
- if (isRepository()) {
+ if (isRepository() && !precompiled) {
if (classes.endsWith(".*")) {
classes = classes.substring(0, classes.indexOf(".*")) + "/";
@@ -702,7 +714,7 @@
* @param classes The classes
*/
public static void removeClasses(String classes) {
- if (isRepository()) {
+ if (isRepository() && !precompiled) {
boolean all = false;
if (classes.endsWith(".*")) {
@@ -756,19 +768,22 @@
* @return The classes
*/
public static String[] listClasses() {
- String[] result = new String[includeList.size()];
- for (int i = 0; i < includeList.size(); i++) {
- String s = includeList.get(i);
-
- if (s.endsWith("/")) {
- s = s.substring(0, s.length() - 1) + ".*";
+ if (!precompiled) {
+ String[] result = new String[includeList.size()];
+ for (int i = 0; i < includeList.size(); i++) {
+ String s = includeList.get(i);
+
+ if (s.endsWith("/")) {
+ s = s.substring(0, s.length() - 1) + ".*";
+ }
+
+ s = s.replace('/', '.');
+
+ result[i] = s;
}
-
- s = s.replace('/', '.');
-
- result[i] = s;
+ return result;
}
- return result;
+ return null;
}
/**
@@ -882,11 +897,13 @@
System.out.println("JBoss Profiler not enabled");
}
- checkInstrumentation();
- transformer = new JavassistTransformer();
instrumentation = inst;
- instrumentation.addTransformer(transformer);
+ if (!precompiled && checkInstrumentation()) {
+ transformer = new JavassistTransformer();
+ instrumentation.addTransformer(transformer);
+ }
+
if (save || remote) {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
Modified: branches/JBossProfiler2/src/main/org/jboss/profiler/agent/ClassUtil.java
===================================================================
--- branches/JBossProfiler2/src/main/org/jboss/profiler/agent/ClassUtil.java 2009-06-16 01:51:25 UTC (rev 548)
+++ branches/JBossProfiler2/src/main/org/jboss/profiler/agent/ClassUtil.java 2009-06-21 17:24:30 UTC (rev 549)
@@ -88,7 +88,9 @@
!c.isAnnotation() &&
!c.isSynthetic()) {
String className = c.getName().replace(".", "/");
- if (Agent.accept(className) && !processed.contains(className)) {
+ if (((Agent.isPrecompiled() && Agent.approve(className)) || Agent.accept(className)) &&
+ !processed.contains(className)) {
+
int ct = ClassType.POJO;
if (Agent.isEJB() && isSession(c)) {
Modified: branches/JBossProfiler2/src/main/org/jboss/profiler/client/CombinedFrameInfo.java
===================================================================
--- branches/JBossProfiler2/src/main/org/jboss/profiler/client/CombinedFrameInfo.java 2009-06-16 01:51:25 UTC (rev 548)
+++ branches/JBossProfiler2/src/main/org/jboss/profiler/client/CombinedFrameInfo.java 2009-06-21 17:24:30 UTC (rev 549)
@@ -139,4 +139,13 @@
public void increaseWaitTime(double t) {
wait += t;
}
+
+ /**
+ * Get the string representation
+ * @return The string
+ */
+ @Override
+ public String toString() {
+ return className + "," + prettyName + "," + count + "," + time + "," + percent + "," + wait;
+ }
}
Modified: branches/JBossProfiler2/src/main/org/jboss/profiler/client/SnapshotUtil.java
===================================================================
--- branches/JBossProfiler2/src/main/org/jboss/profiler/client/SnapshotUtil.java 2009-06-16 01:51:25 UTC (rev 548)
+++ branches/JBossProfiler2/src/main/org/jboss/profiler/client/SnapshotUtil.java 2009-06-21 17:24:30 UTC (rev 549)
@@ -881,7 +881,7 @@
bw.write("<h1>" + Util.getPrettyName(tci) + " (" + Util.getDescription(tci) + ")</h1>" + NEW_LINE);
DecimalFormat df = new DecimalFormat("#0.00");
-
+
bw.write("<table>" + NEW_LINE);
bw.write(" <tr class=\"rowodd\">" + NEW_LINE);
bw.write(" <td>Total time</td><td>" + df.format(tci.getTotalTime()) + " ms</td>" + NEW_LINE);
Modified: branches/JBossProfiler2/src/main/org/jboss/profiler/client/TimedClassInfo.java
===================================================================
--- branches/JBossProfiler2/src/main/org/jboss/profiler/client/TimedClassInfo.java 2009-06-16 01:51:25 UTC (rev 548)
+++ branches/JBossProfiler2/src/main/org/jboss/profiler/client/TimedClassInfo.java 2009-06-21 17:24:30 UTC (rev 549)
@@ -64,4 +64,13 @@
public double getWaitTime() {
return wait;
}
+
+ /**
+ * Get the string representation
+ * @return The string
+ */
+ @Override
+ public String toString() {
+ return super.toString() + "," + time + "," + wait;
+ }
}
Added: branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/ArchiveUtil.java
===================================================================
--- branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/ArchiveUtil.java (rev 0)
+++ branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/ArchiveUtil.java 2009-06-21 17:24:30 UTC (rev 549)
@@ -0,0 +1,161 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2007-2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.profiler.client.precompiler;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Enumeration;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+
+import org.jboss.logging.Logger;
+
+/**
+ * An archive utility for JAR type files
+ * @author <a href="mailto:jesper.pedersen at jboss.org">Jesper Pedersen</a>
+ */
+public class ArchiveUtil {
+
+ /**
+ * Constructor
+ */
+ private ArchiveUtil() {
+ }
+
+ /**
+ * Compress a directory to a file
+ * @param directory The directory
+ * @param file The file
+ * @exception IOException Thrown if an error occurs
+ */
+ public static void compress(File directory, File file) throws IOException {
+ FileOutputStream fos = new FileOutputStream(file);
+ BufferedOutputStream bos = new BufferedOutputStream(fos);
+ JarOutputStream jos = new JarOutputStream(bos);
+ jos.setLevel(9);
+
+ jarDirectory(directory.getPath(), directory.getPath(), jos);
+
+ jos.flush();
+ jos.close();
+ }
+
+ private static void jarDirectory(String root, String directory, JarOutputStream jos) throws IOException {
+ File jarDirectory = new File(directory);
+ String[] dirList = jarDirectory.list();
+ byte[] readBuffer = new byte[2156];
+ int bytesIn = 0;
+
+ for (int i = 0; i < dirList.length; i++) {
+ File f = new File(jarDirectory, dirList[i]);
+ if (f.isDirectory()) {
+ String filePath = f.getPath();
+ jarDirectory(root, filePath, jos);
+ continue;
+ }
+
+ FileInputStream fis = new FileInputStream(f);
+
+ String name = f.getPath();
+ if (name.startsWith(root)) {
+ int offset = root.length() + File.separator.length();
+ name = name.substring(offset);
+ }
+
+ JarEntry anEntry = new JarEntry(name);
+ jos.putNextEntry(anEntry);
+
+ while ((bytesIn = fis.read(readBuffer)) != -1) {
+ jos.write(readBuffer, 0, bytesIn);
+ }
+ fis.close();
+ }
+ }
+
+ /**
+ * Extract a JAR type file
+ * @param file The file
+ * @param directory The directory where the file should be extracted
+ * @return The root of the extracted JAR file
+ * @exception IOException Thrown if an error occurs
+ */
+ public static File extract(File file, File directory) throws IOException {
+ if (file == null) {
+ throw new IllegalArgumentException("File is null");
+ }
+
+ if (directory == null) {
+ throw new IllegalArgumentException("Directory is null");
+ }
+
+ File target = new File(directory, file.getName());
+
+ if (target.exists()) {
+ FileUtil.recursiveDelete(target);
+ }
+
+ target.mkdirs();
+
+ JarFile jar = new JarFile(file);
+ Enumeration<JarEntry> entries = jar.entries();
+
+ while (entries.hasMoreElements()) {
+ JarEntry je = entries.nextElement();
+ File copy = new File(target, je.getName());
+
+ int idx = copy.getAbsolutePath().lastIndexOf("/");
+ if (idx != -1) {
+ File f = new File(copy.getAbsolutePath().substring(0, idx));
+ f.mkdirs();
+ }
+
+ if (!je.isDirectory()) {
+ InputStream in = new BufferedInputStream(jar.getInputStream(je));
+ OutputStream out = new BufferedOutputStream(new FileOutputStream(copy));
+
+ byte[] buffer = new byte[4096];
+ for (;;) {
+ int nBytes = in.read(buffer);
+ if (nBytes <= 0) {
+ break;
+ }
+
+ out.write(buffer, 0, nBytes);
+ }
+ out.flush();
+ out.close();
+ in.close();
+ } else {
+ copy.mkdirs();
+ }
+ }
+
+ return target;
+ }
+}
Added: branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/ClassInstrumenter.java
===================================================================
--- branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/ClassInstrumenter.java (rev 0)
+++ branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/ClassInstrumenter.java 2009-06-21 17:24:30 UTC (rev 549)
@@ -0,0 +1,212 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2007-2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.profiler.client.precompiler;
+
+import org.jboss.profiler.shared.Visibility;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import javassist.CannotCompileException;
+import javassist.ClassPool;
+import javassist.CtBehavior;
+import javassist.CtClass;
+import javassist.CtConstructor;
+import javassist.CtMethod;
+import javassist.Modifier;
+import javassist.expr.ExprEditor;
+import javassist.expr.MethodCall;
+
+/**
+ * Instrument a class with profiler instructions
+ * @author Jesper Pedersen <jesper.pedersen at jboss.org>
+ */
+public class ClassInstrumenter {
+
+ /** Prefix */
+ private static final String PREFIX = "org.jboss.profiler.agent.Profiler.getProfilerThread(Thread.currentThread())";
+
+ /** */
+ private static final String CODE = "{" + PREFIX + ".beginWait(); $_ = $proceed($$); " + PREFIX + ".endWait();}";
+
+ /**
+ * Constructor
+ */
+ private ClassInstrumenter() {
+ }
+
+ /**
+ * Get the bytecode for the instrumented class
+ * @param cc The CtClass that is being instrumented
+ * @param v The visibility for the class
+ * @return The instrumented bytes
+ * @exception IOException If an error occurs
+ */
+ public static byte[] instrument(CtClass cc, Visibility v) throws IOException {
+ try {
+ String className = cc.getName().replace('.', '/');
+
+ if (Modifier.isInterface(cc.getModifiers())) {
+ return cc.toBytecode();
+ }
+
+ CtConstructor[] constructors = cc.getDeclaredConstructors();
+ for (int i = 0; i < constructors.length; i++) {
+ CtConstructor constructor = constructors[i];
+ if (!Modifier.isAbstract(constructor.getModifiers())) {
+ instrumentConstructor(constructor, className, v);
+ }
+ }
+
+ CtMethod[] methods = cc.getDeclaredMethods();
+ for (int i = 0; i < methods.length; i++) {
+ CtMethod method = methods[i];
+ if (!Modifier.isAbstract(method.getModifiers())) {
+ instrumentMethod(method, className, v);
+ }
+ }
+
+ return cc.toBytecode();
+
+ } catch (Exception e) {
+ IOException ioe = new IOException(e.getMessage());
+ ioe.initCause(e);
+ throw ioe;
+ }
+ }
+
+ /**
+ * Instrument constructor
+ * @param constructor The constructor
+ * @param className The class name
+ * @param v The visibility
+ * @exception CannotCompileException If the constructor cant be modified
+ */
+ private static void instrumentConstructor(CtConstructor constructor,
+ String className,
+ Visibility v)
+ throws CannotCompileException {
+
+ if (!constructor.isClassInitializer()) {
+ boolean include = true;
+
+ if (Modifier.isPrivate(constructor.getModifiers())) {
+ if (v == Visibility.PROTECTED ||
+ v == Visibility.PACKAGE ||
+ v == Visibility.PUBLIC) {
+ include = false;
+ }
+ } else if (Modifier.isProtected(constructor.getModifiers())) {
+ if (v == Visibility.PACKAGE ||
+ v == Visibility.PUBLIC) {
+ include = false;
+ }
+ } else if (Modifier.isPackage(constructor.getModifiers())) {
+ if (v == Visibility.PUBLIC) {
+ include = false;
+ }
+ }
+ // Modifier.PUBLIC -- no need to check for method visibility
+
+ if (include) {
+ constructor.insertBeforeBody("{ " +
+ PREFIX + ".allocation(\"" + className + "\");" +
+ PREFIX + ".start(\"" + className + "\", \"" + constructor.getLongName() + "\");" +
+ " }");
+
+ constructor.insertAfter("{ " +
+ PREFIX + ".end(\"" + className + "\", \"" + constructor.getLongName() + "\");" +
+ " }", true);
+
+ setup(constructor);
+ }
+ }
+ }
+
+ /**
+ * Instrument method
+ * @param method The method
+ * @param className The class name
+ * @param v The visibility
+ * @exception CannotCompileException If the constructor cant be modified
+ */
+ private static void instrumentMethod(CtMethod method, String className, Visibility v) throws CannotCompileException {
+ boolean include = true;
+
+ if (Modifier.isPrivate(method.getModifiers())) {
+ if (v == Visibility.PROTECTED ||
+ v == Visibility.PACKAGE ||
+ v == Visibility.PUBLIC) {
+ include = false;
+ }
+ } else if (Modifier.isProtected(method.getModifiers())) {
+ if (v == Visibility.PACKAGE ||
+ v == Visibility.PUBLIC) {
+ include = false;
+ }
+ } else if (Modifier.isPackage(method.getModifiers())) {
+ if (v == Visibility.PUBLIC) {
+ include = false;
+ }
+ }
+ // Modifier.PUBLIC -- no need to check for method visibility
+
+ if (include) {
+ method.insertBefore("{ " +
+ PREFIX + ".start(\"" + className + "\", \"" + method.getLongName() + "\");" +
+ " }");
+
+ method.insertAfter("{ " +
+ PREFIX + ".end(\"" + className + "\", \"" + method.getLongName() + "\");" +
+ " }", true);
+
+ setup(method);
+ }
+ }
+
+ /**
+ * Setup the beginWait/endWait methods
+ * @param ctb The behavior
+ */
+ private static void setup(CtBehavior ctb) {
+ try {
+ ctb.instrument(new ExprEditor() {
+ public void edit(MethodCall m) throws CannotCompileException {
+ if ("java.lang.Object".equals(m.getClassName())) {
+ if ("wait".equals(m.getMethodName())) {
+ m.replace(CODE);
+ }
+ } else if ("java.lang.Thread".equals(m.getClassName())) {
+ if ("join".equals(m.getMethodName()) ||
+ "sleep".equals(m.getMethodName()) ||
+ "yield".equals(m.getMethodName())) {
+ m.replace(CODE);
+ }
+ }
+ }
+ });
+
+ } catch (Exception e) {
+ e.printStackTrace(System.err);
+ }
+ }
+}
Added: branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/ClassScanner.java
===================================================================
--- branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/ClassScanner.java (rev 0)
+++ branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/ClassScanner.java 2009-06-21 17:24:30 UTC (rev 549)
@@ -0,0 +1,56 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.profiler.client.precompiler;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Class scanner
+ * @author Jesper Pedersen <jesper.pedersen at jboss.org>
+ */
+public class ClassScanner {
+
+ /**
+ * Constructor
+ */
+ private ClassScanner() {
+ }
+
+ /**
+ * Scan a directory for JAR files
+ * @param root The root directory
+ * @return The list of JAR files
+ */
+ public static List<File> scan(File root) {
+ try {
+ return ExtensionScanner.scan(root, ".class");
+ } catch (Exception e) {
+ System.err.println(e.getMessage());
+ }
+
+ return null;
+ }
+}
Added: branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/ExtensionScanner.java
===================================================================
--- branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/ExtensionScanner.java (rev 0)
+++ branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/ExtensionScanner.java 2009-06-21 17:24:30 UTC (rev 549)
@@ -0,0 +1,101 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.profiler.client.precompiler;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Extension scanner
+ * @author Jesper Pedersen <jesper.pedersen at jboss.org>
+ */
+public class ExtensionScanner {
+
+ /**
+ * Constructor
+ */
+ private ExtensionScanner() {
+ }
+
+ /**
+ * Scan a directory for files
+ * @param root The root directory
+ * @param extension The file extension
+ * @return The list of files
+ */
+ public static List<File> scan(File root, String extension) {
+ try {
+ return getFileListing(root, extension);
+ } catch (Exception e) {
+ System.err.println(e.getMessage());
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Recursively walk a directory tree and return a List of all
+ * Files found; the List is sorted using File.compareTo().
+ * @param aStartingDir is a valid directory, which can be read.
+ * @param extension The file extension
+ * @return The list of files
+ * @exception Exception Thrown if an error occurs
+ */
+ private static List<File> getFileListing(File aStartingDir, String extension) throws Exception {
+ List<File> result = getFileListingNoSort(aStartingDir, extension);
+ Collections.sort(result);
+ return result;
+ }
+
+ /**
+ * Recursively walk a directory tree and return a List of all
+ * Files found; the List is sorted using File.compareTo().
+ * @param aStartingDir is a valid directory, which can be read.
+ * @param extension The file extension
+ * @return The list of files
+ * @exception Exception Thrown if an error occurs
+ */
+ private static List<File> getFileListingNoSort(File aStartingDir, String extension) throws Exception {
+ List<File> result = new ArrayList<File>();
+
+ File[] filesAndDirs = aStartingDir.listFiles();
+
+ List<File> filesDirs = Arrays.asList(filesAndDirs);
+
+ for (File file : filesDirs) {
+ if (file.isFile()) {
+ if (file.getName().endsWith(extension)) {
+ result.add(file);
+ }
+ } else if (file.isDirectory()) {
+ List<File> deeperList = getFileListingNoSort(file, extension);
+ result.addAll(deeperList);
+ }
+ }
+
+ return result;
+ }
+}
Added: branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/FileUtil.java
===================================================================
--- branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/FileUtil.java (rev 0)
+++ branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/FileUtil.java 2009-06-21 17:24:30 UTC (rev 549)
@@ -0,0 +1,91 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2007-2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.profiler.client.precompiler;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+
+/**
+ * An utility for files and directories
+ * @author <a href="mailto:jesper.pedersen at jboss.org">Jesper Pedersen</a>
+ */
+public class FileUtil {
+
+ /**
+ * Constructor
+ */
+ private FileUtil() {
+ }
+
+ /**
+ * Recursive delete
+ * @param f The file handler
+ */
+ public static void recursiveDelete(File f) {
+ if (f.exists()) {
+ File[] files = f.listFiles();
+ if (files != null) {
+ for (int i = 0; i < files.length; i++) {
+ if (files[i].isDirectory()) {
+ recursiveDelete(files[i]);
+ } else {
+ files[i].delete();
+ }
+ }
+ }
+ f.delete();
+ }
+ }
+
+ /**
+ * Copy file
+ * @param from The from file
+ * @param to The to file
+ * @exception Exception Thrown if an error occurs
+ */
+ public static void copyFile(File from, File to) throws Exception {
+ FileInputStream fis = new FileInputStream(from);
+ BufferedInputStream bis = new BufferedInputStream(fis);
+ FileOutputStream fos = new FileOutputStream(to);
+ BufferedOutputStream bos = new BufferedOutputStream(fos);
+ try {
+ byte[] buf = new byte[4096];
+ int i = 0;
+ while ((i = bis.read(buf)) != -1) {
+ bos.write(buf, 0, i);
+ }
+ bos.flush();
+ } catch (Exception e) {
+ throw e;
+ } finally {
+ if (fis != null) {
+ fis.close();
+ }
+ if (fos != null) {
+ fos.close();
+ }
+ }
+ }
+}
Added: branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/JarScanner.java
===================================================================
--- branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/JarScanner.java (rev 0)
+++ branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/JarScanner.java 2009-06-21 17:24:30 UTC (rev 549)
@@ -0,0 +1,56 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.profiler.client.precompiler;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Jar scanner
+ * @author Jesper Pedersen <jesper.pedersen at jboss.org>
+ */
+public class JarScanner {
+
+ /**
+ * Constructor
+ */
+ private JarScanner() {
+ }
+
+ /**
+ * Scan a directory for JAR files
+ * @param root The root directory
+ * @return The list of JAR files
+ */
+ public static List<File> scan(File root) {
+ try {
+ return ExtensionScanner.scan(root, ".jar");
+ } catch (Exception e) {
+ System.err.println(e.getMessage());
+ }
+
+ return null;
+ }
+}
Added: branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/Precompiler.java
===================================================================
--- branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/Precompiler.java (rev 0)
+++ branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/Precompiler.java 2009-06-21 17:24:30 UTC (rev 549)
@@ -0,0 +1,504 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2007-2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.profiler.client.precompiler;
+
+import org.jboss.profiler.shared.Version;
+import org.jboss.profiler.shared.Visibility;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.TreeMap;
+
+import javassist.ClassPool;
+import javassist.CtClass;
+
+import org.jboss.logging.Logger;
+
+/**
+ * The precompiler tool
+ * @author Jesper Pedersen <jesper.pedersen at jboss.org>
+ */
+public class Precompiler {
+ /** The logger */
+ private static Logger log = Logger.getLogger(Precompiler.class);
+
+ /** Include all */
+ private static boolean includeAll = false;
+
+ /** The include list */
+ private static List<String> includeList = new ArrayList<String>();
+
+ /** Exclude all */
+ private static boolean excludeAll = true;
+
+ /** The exclude list */
+ private static List<String> excludeList = new ArrayList<String>();
+
+ /** Visibility tree */
+ private static TreeMap visibilityTree;
+
+ /** Visibility */
+ private static Visibility visibility;
+
+ /** Class pool */
+ private static ClassPool cp;
+
+ /** Instrumented count */
+ private static int instrumented;
+
+ /**
+ * Constructor
+ */
+ private Precompiler() {
+ }
+
+ /**
+ * Instrument
+ * @param include The include list
+ * @param exclude The exclude list
+ * @param vs The visibility setting
+ * @param f The file handler
+ * @exception Exception Thrown if an error occurs
+ */
+ private static void instrument(String include, String exclude, String vs, File f) throws Exception {
+ instrumented = 0;
+ initVisibility(vs);
+ initIncludeExclude(include, exclude);
+ initClassPool(f);
+
+ String tmpDirectoryLocation = System.getProperty("java.io.tmpdir");
+ File tmpDirectory = new File(tmpDirectoryLocation, "jboss-profiler-tmp");
+
+ if (tmpDirectory.exists()) {
+ FileUtil.recursiveDelete(tmpDirectory);
+ }
+
+ tmpDirectory.mkdirs();
+ tmpDirectory.deleteOnExit();
+
+ int archives = 0;
+
+ if (f.isDirectory()) {
+ List<File> jarFiles = JarScanner.scan(f);
+ archives = jarFiles.size();
+
+ if (jarFiles != null && jarFiles.size() > 0) {
+ for (File jarFile : jarFiles) {
+ log.info("Processing: " + jarFile.getAbsolutePath());
+
+ File extractedArchive = ArchiveUtil.extract(jarFile, tmpDirectory);
+
+ boolean modified = false;
+
+ List<File> classFiles = ClassScanner.scan(extractedArchive);
+ if (classFiles != null && classFiles.size() > 0) {
+ for (File classFile : classFiles) {
+ modified |= instrumentClass(classFile);
+ }
+ }
+
+ if (modified) {
+ File newJarFile = new File(tmpDirectory, jarFile.getName() + "~");
+ ArchiveUtil.compress(extractedArchive, newJarFile);
+
+ FileUtil.recursiveDelete(extractedArchive);
+
+ if (!newJarFile.renameTo(jarFile)) {
+ try {
+ FileUtil.copyFile(newJarFile, jarFile);
+ FileUtil.recursiveDelete(newJarFile);
+ } catch (Exception e) {
+ log.error("Couldn't move " + newJarFile.getAbsolutePath() + " to " + jarFile.getAbsolutePath(), e);
+ }
+ }
+ } else {
+ FileUtil.recursiveDelete(extractedArchive);
+ }
+ }
+ }
+ } else {
+ log.info("Processing: " + f.getAbsolutePath());
+
+ File extractedArchive = ArchiveUtil.extract(f, tmpDirectory);
+
+ boolean modified = false;
+
+ List<File> classFiles = ClassScanner.scan(extractedArchive);
+ if (classFiles != null && classFiles.size() > 0) {
+ for (File classFile : classFiles) {
+ modified |= instrumentClass(classFile);
+ }
+ }
+
+ if (modified) {
+ File newJarFile = new File(tmpDirectory, f.getName() + "~");
+ ArchiveUtil.compress(extractedArchive, newJarFile);
+
+ FileUtil.recursiveDelete(extractedArchive);
+
+ if (!newJarFile.renameTo(f)) {
+ try {
+ FileUtil.copyFile(newJarFile, f);
+ FileUtil.recursiveDelete(newJarFile);
+ } catch (Exception e) {
+ log.error("Couldn't move " + newJarFile.getAbsolutePath() + " to " + f.getAbsolutePath(), e);
+ }
+ }
+ } else {
+ FileUtil.recursiveDelete(extractedArchive);
+ }
+ }
+
+ log.info("Instrumented " + instrumented + " classes in " + archives + " archives.");
+ }
+
+ /**
+ * Instrument class
+ * @param file The class file
+ * @return True if the class was modified; otherwise false
+ * @exception Exception Thrown if an error occurs
+ */
+ private static boolean instrumentClass(File file) throws Exception {
+ FileInputStream fis = new FileInputStream(file);
+ BufferedInputStream bis = new BufferedInputStream(fis);
+
+ CtClass ctClass = cp.makeClass(bis, false);
+
+ bis.close();
+
+ String ctClassSlashName = ctClass.getName().replace('.', '/');
+ if (accept(ctClassSlashName)) {
+ Visibility v = getVisibility(ctClassSlashName);
+ try {
+ byte[] b = ClassInstrumenter.instrument(ctClass, v);
+
+ if (b != null && b.length > 0) {
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(file);
+ BufferedOutputStream bos = new BufferedOutputStream(fos, 16384);
+
+ bos.write(b);
+
+ bos.flush();
+ } finally {
+ if (fos != null) {
+ try {
+ fos.close();
+ } catch (IOException ioe) {
+ // Ignore
+ }
+ }
+ }
+
+ log.debug("Instrumented: " + ctClass.getName());
+
+ instrumented++;
+ return true;
+ }
+ } catch (Throwable t) {
+ log.warn("Can't precompile: " + ctClass.getName());
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Init class pool
+ * @param f The file handler
+ * @exception Exception Thrown if an error occurs
+ */
+ private static void initClassPool(File f) throws Exception {
+ cp = ClassPool.getDefault();
+
+ if (f.isDirectory()) {
+ Set<String> s = new HashSet<String>();
+
+ List<File> jarFiles = JarScanner.scan(f);
+
+ if (jarFiles != null && jarFiles.size() > 0) {
+ for (File jarFile : jarFiles) {
+ if (!s.contains(jarFile.getName())) {
+ cp.appendClassPath(jarFile.getAbsolutePath());
+ s.add(jarFile.getName());
+ }
+ }
+ }
+ } else {
+ cp.appendClassPath(f.getAbsolutePath());
+ }
+ }
+
+ /**
+ * Init visibility
+ */
+ private static void initVisibility(String vs) {
+ visibility = parseVisibility(vs);
+ visibilityTree = new TreeMap(new SizeComparator());
+ }
+
+ /**
+ * Parse visibility property
+ * @param vs The property
+ * @return The visibility
+ */
+ private static Visibility parseVisibility(String vs) {
+ log.debug("Visibility=" + vs);
+
+ if (vs != null) {
+ if ("public".equalsIgnoreCase(vs)) {
+ return Visibility.PUBLIC;
+ } else if ("package".equalsIgnoreCase(vs)) {
+ return Visibility.PACKAGE;
+ } else if ("protected".equalsIgnoreCase(vs)) {
+ return Visibility.PROTECTED;
+ }
+ }
+ return Visibility.PRIVATE;
+ }
+
+ /**
+ * Init include / exclude
+ * @param include The includes
+ * @param exclude The excludes
+ */
+ private static void initIncludeExclude(String include, String exclude) {
+ log.debug("Includes=" + include);
+ log.debug("Excludes=" + exclude);
+
+ if (include != null) {
+ StringTokenizer st = new StringTokenizer(include, ",");
+ List<String> l = new ArrayList<String>();
+ while (st.hasMoreTokens()) {
+ String s = st.nextToken();
+ s = s.trim();
+ if ("*".equals(s)) {
+ includeAll = true;
+ } else {
+ l.add(s);
+ }
+ }
+ Collections.sort(l, new SizeComparator());
+ Collections.reverse(l);
+
+ for (String s : l) {
+ String c = s;
+ String v = null;
+ if (s.indexOf("|") != -1) {
+ c = s.substring(0, s.indexOf("|"));
+ c = c.trim();
+ v = s.substring(s.indexOf("|") + 1);
+ v = v.trim();
+ }
+
+ if (c.endsWith(".*")) {
+ c = c.substring(0, c.indexOf(".*")) + "/";
+ }
+ if (c.endsWith(".class")) {
+ c = c.substring(0, c.indexOf(".class"));
+ }
+ c = c.replace('.', '/');
+
+ Iterator it = includeList.iterator();
+ while (it.hasNext()) {
+ String t = (String)it.next();
+
+ if (t.startsWith(c)) {
+ it.remove();
+ }
+ }
+ it = visibilityTree.keySet().iterator();
+ while (it.hasNext()) {
+ String t = (String)it.next();
+
+ if (t.startsWith(c)) {
+ it.remove();
+ }
+ }
+
+ includeList.add(c);
+ if (v != null) {
+ visibilityTree.put(c, parseVisibility(v));
+ }
+ }
+ }
+
+ if (exclude != null) {
+ excludeAll = false;
+ StringTokenizer st = new StringTokenizer(exclude, ",");
+ List<String> l = new ArrayList<String>();
+ while (st.hasMoreTokens()) {
+ String s = st.nextToken();
+ s = s.trim();
+ if ("*".equals(s)) {
+ excludeAll = true;
+ } else {
+ l.add(s);
+ }
+ }
+ Collections.sort(l, new SizeComparator());
+
+ for (String c : l) {
+ if (c.endsWith(".*")) {
+ c = c.substring(0, c.indexOf(".*")) + "/";
+ }
+ if (c.endsWith(".class")) {
+ c = c.substring(0, c.indexOf(".class"));
+ }
+ c = c.replace('.', '/');
+
+ Iterator it = excludeList.iterator();
+ while (it.hasNext()) {
+ String s = (String)it.next();
+
+ if (s.startsWith(c)) {
+ it.remove();
+ }
+ }
+
+ excludeList.add(c);
+ }
+ }
+
+ Collections.sort(includeList, new SizeComparator());
+ Collections.sort(excludeList, new SizeComparator());
+ }
+
+ /**
+ * Approve the following class for transformation
+ * @param className The class name
+ * @return True if the class is approved; otherwise false
+ */
+ private static boolean approve(String className) {
+ // We can't profile the profiler, Java / Sun classes
+ // nor Javassist
+ if (className.startsWith("org/jboss/profiler/agent/") ||
+ className.startsWith("org/jboss/profiler/as/") ||
+ className.startsWith("org/jboss/profiler/client/") ||
+ className.startsWith("org/jboss/profiler/connectors/") ||
+ className.startsWith("org/jboss/profiler/plugins/") ||
+ className.startsWith("org/jboss/profiler/shared/") ||
+ className.startsWith("java/") ||
+ className.startsWith("javax/") ||
+ className.startsWith("sun/") ||
+ className.startsWith("com/sun/") ||
+ className.startsWith("javassist/")) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Accept the following class for transformation
+ * @param className The class name
+ * @return True if the class should be transformed; otherwise false
+ */
+ public static boolean accept(String className) {
+ if (!approve(className)) {
+ return false;
+ }
+
+ for (String cl : excludeList) {
+ if (className.startsWith(cl)) {
+ return false;
+ }
+ }
+
+ if (includeAll && !excludeAll) {
+ return true;
+ }
+
+ for (String cl : includeList) {
+ if (className.startsWith(cl)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Get the visibility for class
+ * @param className The class name
+ * @return The visibility
+ */
+ private static Visibility getVisibility(String className) {
+ Iterator it = visibilityTree.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry entry = (Map.Entry)it.next();
+ String key = (String)entry.getKey();
+ if (className.startsWith(key)) {
+ return (Visibility)entry.getValue();
+ }
+ }
+
+ return visibility;
+ }
+
+ /**
+ * The main method
+ * @param args The arguments
+ */
+ public static void main(String[] args) {
+ if (args.length == 4) {
+ try {
+ log.info(Version.VENDOR + " Profiler Precompiler " + Version.VERSION);
+
+ String include = args[0];
+ String exclude = args[1];
+ String vs = args[2];
+ File f = new File(args[3]);
+
+ if (f.exists()) {
+ Precompiler.instrument(include, exclude, vs, f);
+ } else {
+ log.fatal("Can't locate " + f.getAbsolutePath());
+ }
+
+ } catch (Throwable t) {
+ t.printStackTrace(System.err);
+ }
+ } else {
+ usage();
+ }
+ }
+
+ /**
+ * The usage method
+ */
+ private static void usage() {
+ System.out.println("Usage: Precompiler <includes> <excludes> <visibility> <directory>");
+ }
+}
Added: branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/SizeComparator.java
===================================================================
--- branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/SizeComparator.java (rev 0)
+++ branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/SizeComparator.java 2009-06-21 17:24:30 UTC (rev 549)
@@ -0,0 +1,48 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2007-2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.profiler.client.precompiler;
+
+import java.io.Serializable;
+import java.util.Comparator;
+
+/**
+ * Size comparator
+ * @author Jesper Pedersen <jesper.pedersen at jboss.org>
+ */
+public class SizeComparator implements Comparator<String>, Serializable {
+
+ /**
+ * Compare two objects
+ * @param sa String
+ * @param sb String
+ * @return Positive if sb greater than sa; zero if equal; otherwise negative
+ */
+ public int compare(String sa, String sb) {
+ if (sa.length() < sb.length()) {
+ return 1;
+ } else if (sa.length() == sb.length()) {
+ return sa.compareTo(sb);
+ } else {
+ return -1;
+ }
+ }
+}
Added: branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/package.html
===================================================================
--- branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/package.html (rev 0)
+++ branches/JBossProfiler2/src/main/org/jboss/profiler/client/precompiler/package.html 2009-06-21 17:24:30 UTC (rev 549)
@@ -0,0 +1,4 @@
+<body>
+The precompiler injects profiling information into JAR files, so they don't
+have to be instrumented during startup.
+</body>
Modified: branches/JBossProfiler2/src/main/org/jboss/profiler/shared/ClassInfo.java
===================================================================
--- branches/JBossProfiler2/src/main/org/jboss/profiler/shared/ClassInfo.java 2009-06-16 01:51:25 UTC (rev 548)
+++ branches/JBossProfiler2/src/main/org/jboss/profiler/shared/ClassInfo.java 2009-06-21 17:24:30 UTC (rev 549)
@@ -87,4 +87,13 @@
public int hashCode() {
return className.hashCode();
}
+
+ /**
+ * Get the string representation
+ * @return The string
+ */
+ @Override
+ public String toString() {
+ return className + "," + classType;
+ }
}
Modified: branches/JBossProfiler2/src/main/org/jboss/profiler/shared/MethodInfo.java
===================================================================
--- branches/JBossProfiler2/src/main/org/jboss/profiler/shared/MethodInfo.java 2009-06-16 01:51:25 UTC (rev 548)
+++ branches/JBossProfiler2/src/main/org/jboss/profiler/shared/MethodInfo.java 2009-06-21 17:24:30 UTC (rev 549)
@@ -88,4 +88,13 @@
public int hashCode() {
return methodName.hashCode() + className.hashCode();
}
+
+ /**
+ * Get the string representation
+ * @return The string
+ */
+ @Override
+ public String toString() {
+ return methodName + "," + className;
+ }
}
More information about the jboss-cvs-commits
mailing list