Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  //
  // $Id: InstrumentStreamableTask.java 6776 2012-02-03 21:25:13Z mdb $
  //
  // Narya library - tools for developing networked games
  // Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
  // http://code.google.com/p/narya/
  //
  // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
 package com.threerings.presents.tools;
 
 
 import java.io.File;
 
 
 
 
 
Instruments compiled com.threerings.io.Streamable classes with public methods that can be used to stream protected and private members when running in a sandboxed JVM.
 
 public class InstrumentStreamableTask extends Task
 {
    
Adds a nested <fileset> element which enumerates streamable class files.
 
     public void addFileset (FileSet set)
     {
         .add(set);
     }

    
Adds a <path> element which defines our classpath.
 
     public void addPath (Path path)
     {
         .add(path);
     }

    
Configures the directory into which we write our instrumented class files.
 
     public void setOutdir (File outdir)
     {
          = outdir;
     }
 
     @Override
     public void execute ()
     {
         // configure our ClassPool with our classpath
         for (Path path : ) {
             for (String element : path.list()) {
                 try {
                     .appendClassPath(element);
                 } catch (NotFoundException nfe) {
                     ..println("Invalid classpath entry [path=" + element + "]: " + nfe);
                 }
             }
         }
        // instantiate streamable
        try {
             = .get(Streamable.class.getName());
        } catch (Exception e) {
            throw new BuildException("Unable to load " + Streamable.class.getName() + ": " + e);
        }
        // now process the files
        for (FileSet fs : ) {
            DirectoryScanner ds = fs.getDirectoryScanner(getProject());
            File fromDir = fs.getDir(getProject());
            String[] srcFiles = ds.getIncludedFiles();
            for (String srcFile : srcFiles) {
                processClass(new File(fromDirsrcFile));
            }
        }
    }

    
Processes a class file.
    protected void processClass (File source)
    {
        CtClass clazz;
        InputStream in = null;
        try {
            clazz = .makeClass(in = new BufferedInputStream(new FileInputStream(source)));
        } catch (IOException ioe) {
            ..println("Failed to load " + source + ": " + ioe);
            return;
        } finally {
            StreamUtil.close(in);
        }
        try {
            if (clazz.subtypeOf()) {
                processStreamable(sourceclazz);
            }
        } catch (NotFoundException nfe) {
            ..println("Error processing class [class=" + clazz.getName() +
                               ", error=" + nfe + "].");
        }
    }

    
Instruments the supplied com.threerings.io.Streamable implementing class.
    protected void processStreamable (File sourceCtClass clazz)
        throws NotFoundException
    {
        ArrayList<CtFieldfields = Lists.newArrayList();
        for (CtField field : clazz.getDeclaredFields()) {
            int modifiers = field.getModifiers();
            if (Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers) ||
                !(Modifier.isProtected(modifiers) || Modifier.isPrivate(modifiers))) {
                continue;
            }
            fields.add(field);
        }
        HashSet<Stringmethods = Sets.newHashSet();
        for (CtMethod method : clazz.getMethods()) {
            methods.add(method.getName());
        }
        int added = 0;
        for (CtField field : fields) {
            String rname = FieldMarshaller.getReaderMethodName(field.getName());
            if (!methods.contains(rname)) {
                String reader =
                    "public void " + rname + " (com.threerings.io.ObjectInputStream ins) {\n" +
                    // "    throws java.io.IOException, java.lang.ClassNotFoundException\n" +
                    "    " + getFieldReader(field) + "\n" +
                    "}";
                // System.out.println("Adding reader " + clazz.getName() + ":\n" + reader);
                try {
                    clazz.addMethod(CtNewMethod.make(readerclazz));
                    added++;
                } catch (CannotCompileException cce) {
                    ..println("Unable to compile reader [class=" + clazz.getName() +
                                       ", error=" + cce + "]:");
                    ..println(reader);
                }
            }
            String wname = FieldMarshaller.getWriterMethodName(field.getName());
            if (!methods.contains(wname)) {
                String writer =
                    "public void " + wname + " (com.threerings.io.ObjectOutputStream out) {\n" +
                    // "    throws java.io.IOException\n" +
                    "    " + getFieldWriter(field) + "\n" +
                    "}";
                // System.out.println("Adding writer " + clazz.getName() + ":\n" + writer);
                try {
                    clazz.addMethod(CtNewMethod.make(writerclazz));
                    added++;
                } catch (CannotCompileException cce) {
                    ..println("Unable to compile writer [class=" + clazz.getName() +
                                       ", error=" + cce + "]:");
                    ..println(writer);
                }
            }
        }
        if (added > 0) {
            try {
                ..println("Instrumented '" + clazz.getName() + "'.");
                clazz.writeFile(.getPath());
            } catch (Exception e) {
                ..println("Failed to write instrumented class [class=" + clazz +
                                   ", outdir=" +  + "]: " + e);
            }
        }
    }
    protected String getFieldReader (CtField field)
        throws NotFoundException
    {
        CtClass type = field.getType();
        String name = field.getName();
        if (type.getName().equals("java.lang.String")) {
            return readWrap(fieldname + " = ins.readUTF();");
        } else if (type.equals(.) || type.getName().equals("java.lang.Boolean")) {
            return readWrap(fieldname + " = ins.readBoolean();");
        } else if (type.equals(.) || type.getName().equals("java.lang.Byte")) {
            return readWrap(fieldname + " = ins.readByte();");
        } else if (type.equals(.) || type.getName().equals("java.lang.Short")) {
            return readWrap(fieldname + " = ins.readShort();");
        } else if (type.equals(.) || type.getName().equals("java.lang.Integer")) {
            return readWrap(fieldname + " = ins.readInt();");
        } else if (type.equals(.) || type.getName().equals("java.lang.Long")) {
            return readWrap(fieldname + " = ins.readLong();");
        } else if (type.equals(.) || type.getName().equals("java.lang.Float")) {
            return readWrap(fieldname + " = ins.readFloat();");
        } else if (type.equals(.) || type.getName().equals("java.lang.Double")) {
            return readWrap(fieldname + " = ins.readDouble();");
        }
        if (type.isArray()) {
            CtClass ctype = type.getComponentType();
            if (ctype.equals(.)) {
                return readWrap(fieldname + " = " +  + ".readBooleanArray(ins);");
            } else if (ctype.equals(.)) {
                return readWrap(fieldname + " = " +  + ".readByteArray(ins);");
            } else if (ctype.equals(.)) {
                return readWrap(fieldname + " = " +  + ".readShortArray(ins);");
            } else if (ctype.equals(.)) {
                return readWrap(fieldname + " = " +  + ".readIntArray(ins);");
            } else if (ctype.equals(.)) {
                return readWrap(fieldname + " = " +  + ".readLongArray(ins);");
            } else if (ctype.equals(.)) {
                return readWrap(fieldname + " = " +  + ".readFloat(ins);");
            } else if (ctype.equals(.)) {
                return readWrap(fieldname + " = " +  + ".readDoubleArray(ins);");
            } else if (ctype.getName().equals("java.lang.Object")) {
                return readWrap(fieldname + " = " +  + ".readObjectArray(ins);");
            }
        }
        // no need to wrap streamable instances
        return (name + " = (" + type.getName() + ")ins.readObject();");
    }
    protected String getFieldWriter (CtField field)
        throws NotFoundException
    {
        CtClass type = field.getType();
        String name = field.getName();
        if (type.equals(.) || type.getName().equals("java.lang.Boolean")) {
            return writeWrap(field"out.writeBoolean(" + name + ");");
        } else if (type.equals(.) || type.getName().equals("java.lang.Byte")) {
            return writeWrap(field"out.writeByte(" + name + ");");
        } else if (type.equals(.) || type.getName().equals("java.lang.Short")) {
            return writeWrap(field"out.writeShort(" + name + ");");
        } else if (type.equals(.) || type.getName().equals("java.lang.Integer")) {
            return writeWrap(field"out.writeInt(" + name + ");");
        } else if (type.equals(.) || type.getName().equals("java.lang.Long")) {
            return writeWrap(field"out.writeLong(" + name + ");");
        } else if (type.equals(.) || type.getName().equals("java.lang.Float")) {
            return writeWrap(field"out.writeFloat(" + name + ");");
        } else if (type.equals(.) || type.getName().equals("java.lang.Double")) {
            return writeWrap(field"out.writeDouble(" + name + ");");
        } else if (type.getName().equals("java.lang.String")) {
            return writeWrap(field"out.writeUTF(" + name + ");");
        }
        if (type.isArray()) {
            CtClass ctype = type.getComponentType();
            if (ctype.equals(.)) {
                return writeWrap(field + ".writeBooleanArray(out, " + name + ");");
            } else if (ctype.equals(.)) {
                return writeWrap(field + ".writeByteArray(out, " + name + ");");
            } else if (ctype.equals(.)) {
                return writeWrap(field + ".writeShortArray(out, " + name + ");");
            } else if (ctype.equals(.)) {
                return writeWrap(field + ".writeIntArray(out, " + name + ");");
            } else if (ctype.equals(.)) {
                return writeWrap(field + ".writeLongArray(out, " + name + ");");
            } else if (ctype.equals(.)) {
                return writeWrap(field + ".writeFloat(out, " + name + ");");
            } else if (ctype.equals(.)) {
                return writeWrap(field + ".writeDoubleArray(out, " + name + ");");
            } else if (ctype.getName().equals("java.lang.Object")) {
                return writeWrap(field + ".writeObjectArray(out, " + name + ");");
            }
        }
        // no need to wrap streamable instances
        return "out.writeObject(" + name + ");";
    }
    protected String readWrap (CtField fieldString body)
        throws NotFoundException
    {
        if (field.getType().isPrimitive()) {
            return body;
        } else {
            return "if (ins.readBoolean()) {\n" +
                "        " + body + "\n" +
                "    } else {\n" +
                "        " + field.getName() + " = null;\n" +
                "    }";
        }
    }
    protected String writeWrap (CtField fieldString body)
        throws NotFoundException
    {
        if (field.getType().isPrimitive()) {
            return body;
        } else {
            return "if (" + field.getName() + " == null) {\n" +
                "        out.writeBoolean(false);\n" +
                "    } else {\n" +
                "        out.writeBoolean(true);\n" +
                "        " + body + "\n" +
                "    }";
        }
    }

    
A list of filesets that contain Streamable class files.
    protected ArrayList<FileSet_filesets = Lists.newArrayList();

    
A list of paths that make up our classpath.
    protected ArrayList<Path_paths = Lists.newArrayList();

    
The directory to which we write our instrumented class files.
    protected File _outdir;

    
Used to instrument class files.
    protected ClassPool _pool = ClassPool.getDefault();

    
Used to determine which classes implement com.threerings.io.Streamable.
    protected CtClass _streamable;
    protected static final String BSNAME = BasicStreamers.class.getName();
New to GrepCode? Check out our FAQ X