From: <fd...@us...> - 2007-08-20 20:44:12
|
Revision: 3399 http://jnode.svn.sourceforge.net/jnode/?rev=3399&view=rev Author: fduminy Date: 2007-08-20 13:44:06 -0700 (Mon, 20 Aug 2007) Log Message: ----------- - refactored some JNode ant tasks around abstract class FileSetTask - created ant task to add annotations on classes (useful for adding @SharedStatics on openjdk classes without modifying the original source code) Modified Paths: -------------- trunk/all/build.xml trunk/builder/src/builder/org/jnode/ant/taskdefs/HeaderTask.java trunk/builder/src/builder/org/jnode/ant/taskdefs/Native2AsciiTask.java trunk/core/.classpath trunk/core/descriptors/org.objectweb.asm.xml trunk/core/src/openjdk/sun/sun/misc/SharedSecrets.java Added Paths: ----------- trunk/all/conf/openjdk-annotations.properties trunk/builder/src/builder/org/jnode/ant/taskdefs/AnnotateTask.java trunk/builder/src/builder/org/jnode/ant/taskdefs/FileSetTask.java trunk/core/lib/asm-1.5.3.jar trunk/core/lib/asm-attrs-1.5.3.jar Removed Paths: ------------- trunk/core/lib/asm.jar Modified: trunk/all/build.xml =================================================================== --- trunk/all/build.xml 2007-08-15 18:21:25 UTC (rev 3398) +++ trunk/all/build.xml 2007-08-20 20:44:06 UTC (rev 3399) @@ -55,9 +55,10 @@ <property name="jmock-cglib.jar" value="${root.dir}/core/lib/jmock-cglib-1.0.1.jar"/> <property name="jmock.jar" value="${root.dir}/core/lib/jmock-1.0.1.jar"/> <property name="cglib.jar" value="${root.dir}/core/lib/cglib-2.1.jar"/> - <property name="asm.jar" value="${root.dir}/core/lib/asm.jar"/> - <property name="jcfe.jar" value="${root.dir}/core/lib/jcfe.jar"/> - <property name="jfunc.jar" value="${root.dir}/core/lib/jfunc.jar"/> + <property name="asm.jar" value="${root.dir}/core/lib/asm-1.5.3.jar"/> + <property name="asm-attrs.jar" value="${root.dir}/core/lib/asm-attrs-1.5.3.jar"/> + <property name="jcfe.jar" value="${root.dir}/core/lib/jcfe.jar"/> + <property name="jfunc.jar" value="${root.dir}/core/lib/jfunc.jar"/> <property name="log4j.jar" value="${root.dir}/core/lib/log4j-1.2.8.jar"/> <property name="gnu-crypto.jar" value="${root.dir}/core/lib/gnu-crypto.jar"/> @@ -92,6 +93,7 @@ <pathelement location="${jmock.jar}"/> <pathelement location="${jmock-cglib.jar}"/> <pathelement location="${asm.jar}"/> + <pathelement location="${asm-attrs.jar}"/> <pathelement location="${cglib.jar}"/> <pathelement location="${log4j.jar}"/> <pathelement location="${gnu-crypto.jar}"/> @@ -164,7 +166,7 @@ </target> <!-- Assemble all plugins --> - <target name="assemble-plugins" depends="assemble-projects"> + <target name="assemble-plugins" depends="assemble-projects,openjdk-annotate"> <!-- Now assemble all plugins --> <taskdef name="plugin" classname="org.jnode.build.PluginTask" classpathref="cp-jnode"/> <plugin todir="${plugins.dir}" tmpdir="${build.dir}/tmp/plugins" pluginDir="${descriptors.dir}"> @@ -199,6 +201,7 @@ <libalias name="jmock-1.0.1.jar" alias="${jmock.jar}"/> <libalias name="jmock-cglib-1.0.1.jar" alias="${jmock-cglib.jar}"/> <libalias name="asm.jar" alias="${asm.jar}"/> + <libalias name="asm-attrs.jar" alias="${asm-attrs.jar}"/> <libalias name="cglib.jar" alias="${cglib.jar}"/> <libalias name="mauve.jar" alias="${mauve.jar}"/> <libalias name="jcfe.jar" alias="${jcfe.jar}"/> @@ -571,7 +574,6 @@ <patternset id="cp-sources-pattern"> <exclude name="com/sun/demo/**/*"/> <exclude name="com/sun/tools/hat/**/*"/> - <exclude name="com/sun/tools/hat/**/*"/> <exclude name="com/sun/tools/example/**/*"/> <exclude name="com/sun/tools/javah/**/*"/> <exclude name="com/sun/tools/internal/txw2/**/*"/> @@ -621,6 +623,19 @@ </cp-compare> </target> + <!-- add annotations to compiled openjdk classes --> + <target name="openjdk-annotate" depends="assemble-projects"> + <echo message="openjdk-annotate"/> + <taskdef name="oj-annotate" classname="org.jnode.ant.taskdefs.AnnotateTask" + classpathref="cp-jnode"/> + + <oj-annotate annotationFile="${root.dir}/all/conf/openjdk-annotations.properties"> + <fileset dir="${root.dir}/core/build/classes"> + <patternset includes="**/*.class"/> + </fileset> + </oj-annotate> + </target> + <!-- Run all tests --> <target name="tests" depends="assemble"> <ant target="tests" dir="${root.dir}/fs" inheritall="on" inheritrefs="on"/> Added: trunk/all/conf/openjdk-annotations.properties =================================================================== --- trunk/all/conf/openjdk-annotations.properties (rev 0) +++ trunk/all/conf/openjdk-annotations.properties 2007-08-20 20:44:06 UTC (rev 3399) @@ -0,0 +1 @@ +sun.misc.SharedSecrets=SharedStatics \ No newline at end of file Added: trunk/builder/src/builder/org/jnode/ant/taskdefs/AnnotateTask.java =================================================================== --- trunk/builder/src/builder/org/jnode/ant/taskdefs/AnnotateTask.java (rev 0) +++ trunk/builder/src/builder/org/jnode/ant/taskdefs/AnnotateTask.java 2007-08-20 20:44:06 UTC (rev 3399) @@ -0,0 +1,266 @@ +/* + * $Id: HeaderTask.java 3379 2007-08-04 10:19:57Z lsantha $ + * + * JNode.org + * Copyright (C) 2003-2006 JNode.org + * + * This library 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 library 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 library; If not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.jnode.ant.taskdefs; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.Collections; +import java.util.Properties; + +import org.apache.tools.ant.BuildException; +import org.jnode.vm.annotation.SharedStatics; +import org.objectweb.asm.ClassAdapter; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Type; +import org.objectweb.asm.attrs.Annotation; +import org.objectweb.asm.attrs.RuntimeVisibleAnnotations; +import org.objectweb.asm.util.AbstractVisitor; +import org.objectweb.asm.util.CheckClassAdapter; +import org.objectweb.asm.util.TraceClassVisitor; + +/** + * That ant task will add some annotations to some compiled classes + * mentioned in a property file. + * For now, it's only necessary to add SharedStatics annotations to some + * openjdk classes to avoid modifying the original source code. + * + * @author Fabien DUMINY (fduminy at jnode.org) + * + */ +public class AnnotateTask extends FileSetTask { + + private File annotationFile; + private String[] classesFiles; + + public void execute() throws BuildException { + classesFiles = readProperties(annotationFile); + processFiles(); + } + + public final File getAnnotationFile() { + return annotationFile; + } + + public final void setAnnotationFile(File annotationFile) { + this.annotationFile = annotationFile; + } + + /** + * Read the properties file. For now, it simply contains a list of + * classes that need the SharedStatics annotation. + * + * @return + * @throws BuildException + */ + private static String[] readProperties(File file) throws BuildException + { + if(file == null) + { + throw new BuildException("annotationFile is mandatory"); + } + + Properties props = new Properties(); + FileInputStream fis = null; + try + { + fis = new FileInputStream(file); + props.load(fis); + } catch (IOException e) { + throw new BuildException(e); + } + finally + { + if(fis != null) + { + try { + fis.close(); + } catch (IOException e) { + throw new BuildException(e); + } + } + } + if(props.isEmpty()) + { + System.err.println("WARNING: annotationFile is empty"); + return new String[0]; + } + + String[] classesFiles = new String[props.size()]; + int i = 0; + for(Object name : props.keySet()) + { + String className = String.valueOf(name); + String annotations = props.getProperty(className); + if("SharedStatics".equals(annotations)) + { + className = className.replace('.', File.separatorChar); + className += ".class"; + classesFiles[i++] = className; + } + } + + // we must sort the classes in reverse order so that + // classes with longest package name will be used first + // (that is only necessary for classes whose name is the same + // but package is different ; typical such class name : "Constants") + Arrays.sort(classesFiles, Collections.reverseOrder()); + + return classesFiles; + } + + private static boolean hasFile(String[] files, File file) + { + boolean found = false; + String filePath = file.getAbsolutePath(); + for(String f : files) + { + if(filePath.endsWith(f)) + { + found = true; + break; + } + } + + return found; + } + + @Override + protected void processFile(File file) throws IOException { + if(!hasFile(classesFiles, file)) + { + return; + } + + System.out.println("adding annotation to file "+file.getAbsolutePath()); + File tmpFile = new File(file.getParentFile(), file.getName()+".tmp"); + FileInputStream fis = null; + FileOutputStream fos = null; + + try + { + fis = new FileInputStream(file); + fos = new FileOutputStream(tmpFile); + addAnnotation(file.getName(), fis, fos); + } + finally + { + if(fis != null) + { + fis.close(); + } + if(fos != null) + { + fos.close(); + } + } + + if(!file.delete()) + { + throw new IOException("can delete "+file.getAbsolutePath()); + } + + if(!tmpFile.renameTo(file)) + { + throw new IOException("can rename "+tmpFile.getAbsolutePath()); + } + + //traceClass(file); + } + + /** + * Simple debug method that trace a class file. + * It can be used to visually check that the annotations has been + * properly added + * + * @param file + * @throws IOException + */ + private void traceClass(File file) throws IOException + { + System.out.println("trace for "+file.getAbsolutePath()); + FileInputStream fis = null; + try + { + fis = new FileInputStream(file); + + ClassReader cr = new ClassReader(fis); + TraceClassVisitor tcv = new TraceClassVisitor(new PrintWriter(System.out)); + cr.accept(tcv, + AbstractVisitor.getDefaultAttributes(), false); + } + finally + { + if(fis != null) + { + fis.close(); + } + } + } + + private void addAnnotation(String fileName, InputStream inputClass, OutputStream outputClass) throws BuildException { + ClassWriter cw = new ClassWriter(false); + try { + ClassReader cr = new ClassReader(inputClass); + cr.accept(new MarkerClassVisitor(cw), + AbstractVisitor.getDefaultAttributes(), false); + + byte[] b = cw.toByteArray(); + outputClass.write(b); + } catch (Exception ex) { + throw new BuildException("Unable to load class in file "+fileName); + } + } + + private static class MarkerClassVisitor extends ClassAdapter { + + public MarkerClassVisitor(ClassVisitor cv) { + super(cv); + } + + public void visit(int version, int access, String name, + String superName, String sourceFile, String[] interfaces) { + super.visit(org.objectweb.asm.Constants.V1_5, access, name, superName, + sourceFile, interfaces); + } + + @SuppressWarnings("unchecked") + public void visitEnd() { + String t = Type.getDescriptor(SharedStatics.class); + Annotation ann = new Annotation(t); + + RuntimeVisibleAnnotations attr = new RuntimeVisibleAnnotations(); + attr.annotations.add(ann); + cv.visitAttribute(attr); + + super.visitEnd(); + } + } +} Added: trunk/builder/src/builder/org/jnode/ant/taskdefs/FileSetTask.java =================================================================== --- trunk/builder/src/builder/org/jnode/ant/taskdefs/FileSetTask.java (rev 0) +++ trunk/builder/src/builder/org/jnode/ant/taskdefs/FileSetTask.java 2007-08-20 20:44:06 UTC (rev 3399) @@ -0,0 +1,70 @@ +/* + * $Id: HeaderTask.java 3379 2007-08-04 10:19:57Z lsantha $ + * + * JNode.org + * Copyright (C) 2003-2006 JNode.org + * + * This library 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 library 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 library; If not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.jnode.ant.taskdefs; + +import java.io.*; +import java.util.ArrayList; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.types.FileSet; + +/** + * Abstract class for ant task that process one or more FileSet + * The concrete classes only have to implement the <i>process</i> method + * for doing the concrete work on a file. + * + * @author Fabien DUMINY (fduminy at jnode.org) + * + */ +abstract public class FileSetTask extends Task { + + private final ArrayList<FileSet> fileSets = new ArrayList<FileSet>(); + + public void addFileSet(FileSet fs) { + fileSets.add(fs); + } + + public void execute() throws BuildException { + // default implementation : simply iterate on all files + processFiles(); + } + + final protected void processFiles() throws BuildException + { + final Project project = getProject(); + try { + for (FileSet fs : fileSets) { + final String[] files = fs.getDirectoryScanner(project) + .getIncludedFiles(); + final File projectDir = fs.getDir(project); + for (String fname : files) { + processFile(new File(projectDir, fname)); + } + } + } catch (IOException e) { + throw new BuildException(e); + } + } + + abstract protected void processFile(File file) throws IOException; +} Modified: trunk/builder/src/builder/org/jnode/ant/taskdefs/HeaderTask.java =================================================================== --- trunk/builder/src/builder/org/jnode/ant/taskdefs/HeaderTask.java 2007-08-15 18:21:25 UTC (rev 3398) +++ trunk/builder/src/builder/org/jnode/ant/taskdefs/HeaderTask.java 2007-08-20 20:44:06 UTC (rev 3399) @@ -30,16 +30,12 @@ /** * @author Ewout Prangsma (ep...@us...) */ -public class HeaderTask extends Task { +public class HeaderTask extends FileSetTask { - private final ArrayList<FileSet> fileSets = new ArrayList<FileSet>(); - private File headerFile; + private String[] header; private boolean update = false; - public void addFileSet(FileSet fs) { - fileSets.add(fs); - } private boolean compareHeader(String[] lines, String[] header) { final int linesCnt = lines.length; @@ -77,18 +73,8 @@ throw new BuildException("HeaderFile must be set"); } try { - final String[] header = readFile(headerFile); - - for (FileSet fs : fileSets) { - final String[] files = fs.getDirectoryScanner(getProject()) - .getIncludedFiles(); - final int fileCount = files.length; - for (int j = 0; j < fileCount; j++) { - final String fname = files[j]; - processFile(new File(fs.getDir(getProject()), fname), header); - } - - } + header = readFile(headerFile); + processFiles(); } catch (IOException ex) { throw new BuildException(ex); } @@ -102,7 +88,8 @@ return update; } - private void processFile(File file, String[] header) throws IOException { + @Override + protected void processFile(File file) throws IOException { final String[] inp = readFile(file); if (!compareHeader(inp, header)) { if (update) { Modified: trunk/builder/src/builder/org/jnode/ant/taskdefs/Native2AsciiTask.java =================================================================== --- trunk/builder/src/builder/org/jnode/ant/taskdefs/Native2AsciiTask.java 2007-08-15 18:21:25 UTC (rev 3398) +++ trunk/builder/src/builder/org/jnode/ant/taskdefs/Native2AsciiTask.java 2007-08-20 20:44:06 UTC (rev 3399) @@ -34,38 +34,16 @@ /** * @author Ewout Prangsma (ep...@us...) */ -public class Native2AsciiTask extends Task { +public class Native2AsciiTask extends FileSetTask { - private final ArrayList<FileSet> fileSets = new ArrayList<FileSet>(); - private boolean update = false; - public void addFileSet(FileSet fs) { - fileSets.add(fs); - } - - public void execute() throws BuildException { - try { - for (FileSet fs : fileSets) { - final String[] files = fs.getDirectoryScanner(getProject()) - .getIncludedFiles(); - final int fileCount = files.length; - for (int j = 0; j < fileCount; j++) { - final String fname = files[j]; - processFile(new File(fs.getDir(getProject()), fname)); - } - - } - } catch (IOException ex) { - throw new BuildException(ex); - } - } - public final boolean isUpdate() { return update; } - private void processFile(File file) throws IOException { + @Override + protected void processFile(File file) throws IOException { if (containsNonAscii(file)) { final File tmp = File.createTempFile("jnode", "n2a"); try { Modified: trunk/core/.classpath =================================================================== --- trunk/core/.classpath 2007-08-15 18:21:25 UTC (rev 3398) +++ trunk/core/.classpath 2007-08-20 20:44:06 UTC (rev 3399) @@ -24,6 +24,8 @@ <classpathentry kind="lib" path="lib/junit.jar"/> <classpathentry kind="lib" path="lib/mx4j.jar"/> <classpathentry kind="lib" path="lib/mmtk/mmtk.jar" sourcepath="D:/epr/cvswork/MMTk/src"/> + <classpathentry exported="true" kind="lib" path="lib/asm-1.5.3.jar"/> + <classpathentry exported="true" kind="lib" path="lib/asm-attrs-1.5.3.jar"/> <classpathentry kind="src" path="src/nanoxml"/> <classpathentry kind="lib" path="lib/mauve.jar"/> <classpathentry kind="output" path="build/classes"/> Modified: trunk/core/descriptors/org.objectweb.asm.xml =================================================================== --- trunk/core/descriptors/org.objectweb.asm.xml 2007-08-15 18:21:25 UTC (rev 3398) +++ trunk/core/descriptors/org.objectweb.asm.xml 2007-08-20 20:44:06 UTC (rev 3399) @@ -3,7 +3,7 @@ <plugin id="org.objectweb.asm" name="ASM classes" - version="1" + version="1.5.3" provider-name="Objectweb" provider-url="http://objectweb.org" license-name="bsd"> @@ -12,5 +12,8 @@ <library name="asm.jar"> <export name="org.objectweb.asm.*"/> </library> + <library name="asm-attrs.jar"> + <export name="org.objectweb.asm.*"/> + </library> </runtime> </plugin> \ No newline at end of file Added: trunk/core/lib/asm-1.5.3.jar =================================================================== (Binary files differ) Property changes on: trunk/core/lib/asm-1.5.3.jar ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/core/lib/asm-attrs-1.5.3.jar =================================================================== (Binary files differ) Property changes on: trunk/core/lib/asm-attrs-1.5.3.jar ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Deleted: trunk/core/lib/asm.jar =================================================================== (Binary files differ) Modified: trunk/core/src/openjdk/sun/sun/misc/SharedSecrets.java =================================================================== --- trunk/core/src/openjdk/sun/sun/misc/SharedSecrets.java 2007-08-15 18:21:25 UTC (rev 3398) +++ trunk/core/src/openjdk/sun/sun/misc/SharedSecrets.java 2007-08-20 20:44:06 UTC (rev 3399) @@ -38,7 +38,6 @@ This framework avoids the primary disadvantage of using reflection for this purpose, namely the loss of compile-time checking. */ -...@or...aredStatics //jnode public class SharedSecrets { private static final Unsafe unsafe = Unsafe.getUnsafe(); private static JavaUtilJarAccess javaUtilJarAccess; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |