Add class remapper
authornpzacs <npzacs@gmail.com>
Thu, 14 Sep 2017 11:15:15 +0000 (14:15 +0300)
committernpzacs <npzacs@gmail.com>
Wed, 11 Oct 2017 07:29:56 +0000 (10:29 +0300)
13 files changed:
contrib/asm/src/org/objectweb/asm/commons/LocalVariablesSorter.java [new file with mode: 0644]
contrib/asm/src/org/objectweb/asm/commons/Remapper.java [new file with mode: 0644]
contrib/asm/src/org/objectweb/asm/commons/RemappingAnnotationAdapter.java [new file with mode: 0644]
contrib/asm/src/org/objectweb/asm/commons/RemappingClassAdapter.java [new file with mode: 0644]
contrib/asm/src/org/objectweb/asm/commons/RemappingFieldAdapter.java [new file with mode: 0644]
contrib/asm/src/org/objectweb/asm/commons/RemappingMethodAdapter.java [new file with mode: 0644]
contrib/asm/src/org/objectweb/asm/commons/RemappingSignatureAdapter.java [new file with mode: 0644]
contrib/asm/src/org/objectweb/asm/commons/SimpleRemapper.java [new file with mode: 0644]
contrib/asm/src/org/objectweb/asm/signature/SignatureReader.java [new file with mode: 0644]
contrib/asm/src/org/objectweb/asm/signature/SignatureVisitor.java [new file with mode: 0644]
contrib/asm/src/org/objectweb/asm/signature/SignatureWriter.java [new file with mode: 0644]
src/libbluray/bdj/java/org/videolan/BDJClassFileTransformer.java
src/libbluray/bdj/java/org/videolan/mmbd/Adapter.java [new file with mode: 0644]

diff --git a/contrib/asm/src/org/objectweb/asm/commons/LocalVariablesSorter.java b/contrib/asm/src/org/objectweb/asm/commons/LocalVariablesSorter.java
new file mode 100644 (file)
index 0000000..295c319
--- /dev/null
@@ -0,0 +1,381 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.commons;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.TypePath;
+
+/**
+ * A {@link MethodVisitor} that renumbers local variables in their order of
+ * appearance. This adapter allows one to easily add new local variables to a
+ * method. It may be used by inheriting from this class, but the preferred way
+ * of using it is via delegation: the next visitor in the chain can indeed add
+ * new locals when needed by calling {@link #newLocal} on this adapter (this
+ * requires a reference back to this {@link LocalVariablesSorter}).
+ * 
+ * @author Chris Nokleberg
+ * @author Eugene Kuleshov
+ * @author Eric Bruneton
+ */
+public class LocalVariablesSorter extends MethodVisitor {
+
+    private static final Type OBJECT_TYPE = Type
+            .getObjectType("java/lang/Object");
+
+    /**
+     * Mapping from old to new local variable indexes. A local variable at index
+     * i of size 1 is remapped to 'mapping[2*i]', while a local variable at
+     * index i of size 2 is remapped to 'mapping[2*i+1]'.
+     */
+    private int[] mapping = new int[40];
+
+    /**
+     * Array used to store stack map local variable types after remapping.
+     */
+    private Object[] newLocals = new Object[20];
+
+    /**
+     * Index of the first local variable, after formal parameters.
+     */
+    protected final int firstLocal;
+
+    /**
+     * Index of the next local variable to be created by {@link #newLocal}.
+     */
+    protected int nextLocal;
+
+    /**
+     * Indicates if at least one local variable has moved due to remapping.
+     */
+    private boolean changed;
+
+    /**
+     * Creates a new {@link LocalVariablesSorter}. <i>Subclasses must not use
+     * this constructor</i>. Instead, they must use the
+     * {@link #LocalVariablesSorter(int, int, String, MethodVisitor)} version.
+     * 
+     * @param access
+     *            access flags of the adapted method.
+     * @param desc
+     *            the method's descriptor (see {@link Type Type}).
+     * @param mv
+     *            the method visitor to which this adapter delegates calls.
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
+     */
+    public LocalVariablesSorter(final int access, final String desc,
+            final MethodVisitor mv) {
+        this(Opcodes.ASM5, access, desc, mv);
+        if (getClass() != LocalVariablesSorter.class) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Creates a new {@link LocalVariablesSorter}.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param access
+     *            access flags of the adapted method.
+     * @param desc
+     *            the method's descriptor (see {@link Type Type}).
+     * @param mv
+     *            the method visitor to which this adapter delegates calls.
+     */
+    protected LocalVariablesSorter(final int api, final int access,
+            final String desc, final MethodVisitor mv) {
+        super(api, mv);
+        Type[] args = Type.getArgumentTypes(desc);
+        nextLocal = (Opcodes.ACC_STATIC & access) == 0 ? 1 : 0;
+        for (int i = 0; i < args.length; i++) {
+            nextLocal += args[i].getSize();
+        }
+        firstLocal = nextLocal;
+    }
+
+    @Override
+    public void visitVarInsn(final int opcode, final int var) {
+        Type type;
+        switch (opcode) {
+        case Opcodes.LLOAD:
+        case Opcodes.LSTORE:
+            type = Type.LONG_TYPE;
+            break;
+
+        case Opcodes.DLOAD:
+        case Opcodes.DSTORE:
+            type = Type.DOUBLE_TYPE;
+            break;
+
+        case Opcodes.FLOAD:
+        case Opcodes.FSTORE:
+            type = Type.FLOAT_TYPE;
+            break;
+
+        case Opcodes.ILOAD:
+        case Opcodes.ISTORE:
+            type = Type.INT_TYPE;
+            break;
+
+        default:
+            // case Opcodes.ALOAD:
+            // case Opcodes.ASTORE:
+            // case RET:
+            type = OBJECT_TYPE;
+            break;
+        }
+        mv.visitVarInsn(opcode, remap(var, type));
+    }
+
+    @Override
+    public void visitIincInsn(final int var, final int increment) {
+        mv.visitIincInsn(remap(var, Type.INT_TYPE), increment);
+    }
+
+    @Override
+    public void visitMaxs(final int maxStack, final int maxLocals) {
+        mv.visitMaxs(maxStack, nextLocal);
+    }
+
+    @Override
+    public void visitLocalVariable(final String name, final String desc,
+            final String signature, final Label start, final Label end,
+            final int index) {
+        int newIndex = remap(index, Type.getType(desc));
+        mv.visitLocalVariable(name, desc, signature, start, end, newIndex);
+    }
+
+    @Override
+    public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+            TypePath typePath, Label[] start, Label[] end, int[] index,
+            String desc, boolean visible) {
+        Type t = Type.getType(desc);
+        int[] newIndex = new int[index.length];
+        for (int i = 0; i < newIndex.length; ++i) {
+            newIndex[i] = remap(index[i], t);
+        }
+        return mv.visitLocalVariableAnnotation(typeRef, typePath, start, end,
+                newIndex, desc, visible);
+    }
+
+    @Override
+    public void visitFrame(final int type, final int nLocal,
+            final Object[] local, final int nStack, final Object[] stack) {
+        if (type != Opcodes.F_NEW) { // uncompressed frame
+            throw new IllegalStateException(
+                    "ClassReader.accept() should be called with EXPAND_FRAMES flag");
+        }
+
+        if (!changed) { // optimization for the case where mapping = identity
+            mv.visitFrame(type, nLocal, local, nStack, stack);
+            return;
+        }
+
+        // creates a copy of newLocals
+        Object[] oldLocals = new Object[newLocals.length];
+        System.arraycopy(newLocals, 0, oldLocals, 0, oldLocals.length);
+
+        updateNewLocals(newLocals);
+
+        // copies types from 'local' to 'newLocals'
+        // 'newLocals' already contains the variables added with 'newLocal'
+
+        int index = 0; // old local variable index
+        int number = 0; // old local variable number
+        for (; number < nLocal; ++number) {
+            Object t = local[number];
+            int size = t == Opcodes.LONG || t == Opcodes.DOUBLE ? 2 : 1;
+            if (t != Opcodes.TOP) {
+                Type typ = OBJECT_TYPE;
+                if (t == Opcodes.INTEGER) {
+                    typ = Type.INT_TYPE;
+                } else if (t == Opcodes.FLOAT) {
+                    typ = Type.FLOAT_TYPE;
+                } else if (t == Opcodes.LONG) {
+                    typ = Type.LONG_TYPE;
+                } else if (t == Opcodes.DOUBLE) {
+                    typ = Type.DOUBLE_TYPE;
+                } else if (t instanceof String) {
+                    typ = Type.getObjectType((String) t);
+                }
+                setFrameLocal(remap(index, typ), t);
+            }
+            index += size;
+        }
+
+        // removes TOP after long and double types as well as trailing TOPs
+
+        index = 0;
+        number = 0;
+        for (int i = 0; index < newLocals.length; ++i) {
+            Object t = newLocals[index++];
+            if (t != null && t != Opcodes.TOP) {
+                newLocals[i] = t;
+                number = i + 1;
+                if (t == Opcodes.LONG || t == Opcodes.DOUBLE) {
+                    index += 1;
+                }
+            } else {
+                newLocals[i] = Opcodes.TOP;
+            }
+        }
+
+        // visits remapped frame
+        mv.visitFrame(type, number, newLocals, nStack, stack);
+
+        // restores original value of 'newLocals'
+        newLocals = oldLocals;
+    }
+
+    // -------------
+
+    /**
+     * Creates a new local variable of the given type.
+     * 
+     * @param type
+     *            the type of the local variable to be created.
+     * @return the identifier of the newly created local variable.
+     */
+    public int newLocal(final Type type) {
+        Object t;
+        switch (type.getSort()) {
+        case Type.BOOLEAN:
+        case Type.CHAR:
+        case Type.BYTE:
+        case Type.SHORT:
+        case Type.INT:
+            t = Opcodes.INTEGER;
+            break;
+        case Type.FLOAT:
+            t = Opcodes.FLOAT;
+            break;
+        case Type.LONG:
+            t = Opcodes.LONG;
+            break;
+        case Type.DOUBLE:
+            t = Opcodes.DOUBLE;
+            break;
+        case Type.ARRAY:
+            t = type.getDescriptor();
+            break;
+        // case Type.OBJECT:
+        default:
+            t = type.getInternalName();
+            break;
+        }
+        int local = newLocalMapping(type);
+        setLocalType(local, type);
+        setFrameLocal(local, t);
+        changed = true;
+        return local;
+    }
+
+    /**
+     * Notifies subclasses that a new stack map frame is being visited. The
+     * array argument contains the stack map frame types corresponding to the
+     * local variables added with {@link #newLocal}. This method can update
+     * these types in place for the stack map frame being visited. The default
+     * implementation of this method does nothing, i.e. a local variable added
+     * with {@link #newLocal} will have the same type in all stack map frames.
+     * But this behavior is not always the desired one, for instance if a local
+     * variable is added in the middle of a try/catch block: the frame for the
+     * exception handler should have a TOP type for this new local.
+     * 
+     * @param newLocals
+     *            the stack map frame types corresponding to the local variables
+     *            added with {@link #newLocal} (and null for the others). The
+     *            format of this array is the same as in
+     *            {@link MethodVisitor#visitFrame}, except that long and double
+     *            types use two slots. The types for the current stack map frame
+     *            must be updated in place in this array.
+     */
+    protected void updateNewLocals(Object[] newLocals) {
+    }
+
+    /**
+     * Notifies subclasses that a local variable has been added or remapped. The
+     * default implementation of this method does nothing.
+     * 
+     * @param local
+     *            a local variable identifier, as returned by {@link #newLocal
+     *            newLocal()}.
+     * @param type
+     *            the type of the value being stored in the local variable.
+     */
+    protected void setLocalType(final int local, final Type type) {
+    }
+
+    private void setFrameLocal(final int local, final Object type) {
+        int l = newLocals.length;
+        if (local >= l) {
+            Object[] a = new Object[Math.max(2 * l, local + 1)];
+            System.arraycopy(newLocals, 0, a, 0, l);
+            newLocals = a;
+        }
+        newLocals[local] = type;
+    }
+
+    private int remap(final int var, final Type type) {
+        if (var + type.getSize() <= firstLocal) {
+            return var;
+        }
+        int key = 2 * var + type.getSize() - 1;
+        int size = mapping.length;
+        if (key >= size) {
+            int[] newMapping = new int[Math.max(2 * size, key + 1)];
+            System.arraycopy(mapping, 0, newMapping, 0, size);
+            mapping = newMapping;
+        }
+        int value = mapping[key];
+        if (value == 0) {
+            value = newLocalMapping(type);
+            setLocalType(value, type);
+            mapping[key] = value + 1;
+        } else {
+            value--;
+        }
+        if (value != var) {
+            changed = true;
+        }
+        return value;
+    }
+
+    protected int newLocalMapping(final Type type) {
+        int local = nextLocal;
+        nextLocal += type.getSize();
+        return local;
+    }
+}
diff --git a/contrib/asm/src/org/objectweb/asm/commons/Remapper.java b/contrib/asm/src/org/objectweb/asm/commons/Remapper.java
new file mode 100644 (file)
index 0000000..121cf88
--- /dev/null
@@ -0,0 +1,223 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.objectweb.asm.commons;
+
+import org.objectweb.asm.Handle;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.signature.SignatureReader;
+import org.objectweb.asm.signature.SignatureVisitor;
+import org.objectweb.asm.signature.SignatureWriter;
+
+/**
+ * A class responsible for remapping types and names. Subclasses can override
+ * the following methods:
+ * 
+ * <ul>
+ * <li>{@link #map(String)} - map type</li>
+ * <li>{@link #mapFieldName(String, String, String)} - map field name</li>
+ * <li>{@link #mapMethodName(String, String, String)} - map method name</li>
+ * </ul>
+ * 
+ * @author Eugene Kuleshov
+ */
+public abstract class Remapper {
+
+    public String mapDesc(String desc) {
+        Type t = Type.getType(desc);
+        switch (t.getSort()) {
+        case Type.ARRAY:
+            String s = mapDesc(t.getElementType().getDescriptor());
+            for (int i = 0; i < t.getDimensions(); ++i) {
+                s = '[' + s;
+            }
+            return s;
+        case Type.OBJECT:
+            String newType = map(t.getInternalName());
+            if (newType != null) {
+                return 'L' + newType + ';';
+            }
+        }
+        return desc;
+    }
+
+    private Type mapType(Type t) {
+        switch (t.getSort()) {
+        case Type.ARRAY:
+            String s = mapDesc(t.getElementType().getDescriptor());
+            for (int i = 0; i < t.getDimensions(); ++i) {
+                s = '[' + s;
+            }
+            return Type.getType(s);
+        case Type.OBJECT:
+            s = map(t.getInternalName());
+            return s != null ? Type.getObjectType(s) : t;
+        case Type.METHOD:
+            return Type.getMethodType(mapMethodDesc(t.getDescriptor()));
+        }
+        return t;
+    }
+
+    public String mapType(String type) {
+        if (type == null) {
+            return null;
+        }
+        return mapType(Type.getObjectType(type)).getInternalName();
+    }
+
+    public String[] mapTypes(String[] types) {
+        String[] newTypes = null;
+        boolean needMapping = false;
+        for (int i = 0; i < types.length; i++) {
+            String type = types[i];
+            String newType = map(type);
+            if (newType != null && newTypes == null) {
+                newTypes = new String[types.length];
+                if (i > 0) {
+                    System.arraycopy(types, 0, newTypes, 0, i);
+                }
+                needMapping = true;
+            }
+            if (needMapping) {
+                newTypes[i] = newType == null ? type : newType;
+            }
+        }
+        return needMapping ? newTypes : types;
+    }
+
+    public String mapMethodDesc(String desc) {
+        if ("()V".equals(desc)) {
+            return desc;
+        }
+
+        Type[] args = Type.getArgumentTypes(desc);
+        StringBuilder sb = new StringBuilder("(");
+        for (int i = 0; i < args.length; i++) {
+            sb.append(mapDesc(args[i].getDescriptor()));
+        }
+        Type returnType = Type.getReturnType(desc);
+        if (returnType == Type.VOID_TYPE) {
+            sb.append(")V");
+            return sb.toString();
+        }
+        sb.append(')').append(mapDesc(returnType.getDescriptor()));
+        return sb.toString();
+    }
+
+    public Object mapValue(Object value) {
+        if (value instanceof Type) {
+            return mapType((Type) value);
+        }
+        if (value instanceof Handle) {
+            Handle h = (Handle) value;
+            return new Handle(h.getTag(), mapType(h.getOwner()), mapMethodName(
+                    h.getOwner(), h.getName(), h.getDesc()),
+                    mapMethodDesc(h.getDesc()));
+        }
+        return value;
+    }
+
+    /**
+     * 
+     * @param typeSignature
+     *            true if signature is a FieldTypeSignature, such as the
+     *            signature parameter of the ClassVisitor.visitField or
+     *            MethodVisitor.visitLocalVariable methods
+     */
+    public String mapSignature(String signature, boolean typeSignature) {
+        if (signature == null) {
+            return null;
+        }
+        SignatureReader r = new SignatureReader(signature);
+        SignatureWriter w = new SignatureWriter();
+        SignatureVisitor a = createRemappingSignatureAdapter(w);
+        if (typeSignature) {
+            r.acceptType(a);
+        } else {
+            r.accept(a);
+        }
+        return w.toString();
+    }
+
+    protected SignatureVisitor createRemappingSignatureAdapter(
+            SignatureVisitor v) {
+        return new RemappingSignatureAdapter(v, this);
+    }
+
+    /**
+     * Map method name to the new name. Subclasses can override.
+     * 
+     * @param owner
+     *            owner of the method.
+     * @param name
+     *            name of the method.
+     * @param desc
+     *            descriptor of the method.
+     * @return new name of the method
+     */
+    public String mapMethodName(String owner, String name, String desc) {
+        return name;
+    }
+
+    /**
+     * Map invokedynamic method name to the new name. Subclasses can override.
+     * 
+     * @param name
+     *            name of the invokedynamic.
+     * @param desc
+     *            descriptor of the invokedynamic.
+     * @return new invokdynamic name.
+     */
+    public String mapInvokeDynamicMethodName(String name, String desc) {
+        return name;
+    }
+
+    /**
+     * Map field name to the new name. Subclasses can override.
+     * 
+     * @param owner
+     *            owner of the field.
+     * @param name
+     *            name of the field
+     * @param desc
+     *            descriptor of the field
+     * @return new name of the field.
+     */
+    public String mapFieldName(String owner, String name, String desc) {
+        return name;
+    }
+
+    /**
+     * Map type name to the new name. Subclasses can override.
+     */
+    public String map(String typeName) {
+        return typeName;
+    }
+}
diff --git a/contrib/asm/src/org/objectweb/asm/commons/RemappingAnnotationAdapter.java b/contrib/asm/src/org/objectweb/asm/commons/RemappingAnnotationAdapter.java
new file mode 100644 (file)
index 0000000..b9749fc
--- /dev/null
@@ -0,0 +1,79 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.objectweb.asm.commons;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Opcodes;
+
+/**
+ * An {@link AnnotationVisitor} adapter for type remapping.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class RemappingAnnotationAdapter extends AnnotationVisitor {
+
+    protected final Remapper remapper;
+
+    public RemappingAnnotationAdapter(final AnnotationVisitor av,
+            final Remapper remapper) {
+        this(Opcodes.ASM5, av, remapper);
+    }
+
+    protected RemappingAnnotationAdapter(final int api,
+            final AnnotationVisitor av, final Remapper remapper) {
+        super(api, av);
+        this.remapper = remapper;
+    }
+
+    @Override
+    public void visit(String name, Object value) {
+        av.visit(name, remapper.mapValue(value));
+    }
+
+    @Override
+    public void visitEnum(String name, String desc, String value) {
+        av.visitEnum(name, remapper.mapDesc(desc), value);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(String name, String desc) {
+        AnnotationVisitor v = av.visitAnnotation(name, remapper.mapDesc(desc));
+        return v == null ? null : (v == av ? this
+                : new RemappingAnnotationAdapter(v, remapper));
+    }
+
+    @Override
+    public AnnotationVisitor visitArray(String name) {
+        AnnotationVisitor v = av.visitArray(name);
+        return v == null ? null : (v == av ? this
+                : new RemappingAnnotationAdapter(v, remapper));
+    }
+}
diff --git a/contrib/asm/src/org/objectweb/asm/commons/RemappingClassAdapter.java b/contrib/asm/src/org/objectweb/asm/commons/RemappingClassAdapter.java
new file mode 100644 (file)
index 0000000..c0b52ca
--- /dev/null
@@ -0,0 +1,135 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.objectweb.asm.commons;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.TypePath;
+
+/**
+ * A {@link ClassVisitor} for type remapping.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class RemappingClassAdapter extends ClassVisitor {
+
+    protected final Remapper remapper;
+
+    protected String className;
+
+    public RemappingClassAdapter(final ClassVisitor cv, final Remapper remapper) {
+        this(Opcodes.ASM5, cv, remapper);
+    }
+
+    protected RemappingClassAdapter(final int api, final ClassVisitor cv,
+            final Remapper remapper) {
+        super(api, cv);
+        this.remapper = remapper;
+    }
+
+    @Override
+    public void visit(int version, int access, String name, String signature,
+            String superName, String[] interfaces) {
+        this.className = name;
+        super.visit(version, access, remapper.mapType(name), remapper
+                .mapSignature(signature, false), remapper.mapType(superName),
+                interfaces == null ? null : remapper.mapTypes(interfaces));
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+        AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
+                visible);
+        return av == null ? null : createRemappingAnnotationAdapter(av);
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
+                remapper.mapDesc(desc), visible);
+        return av == null ? null : createRemappingAnnotationAdapter(av);
+    }
+
+    @Override
+    public FieldVisitor visitField(int access, String name, String desc,
+            String signature, Object value) {
+        FieldVisitor fv = super.visitField(access,
+                remapper.mapFieldName(className, name, desc),
+                remapper.mapDesc(desc), remapper.mapSignature(signature, true),
+                remapper.mapValue(value));
+        return fv == null ? null : createRemappingFieldAdapter(fv);
+    }
+
+    @Override
+    public MethodVisitor visitMethod(int access, String name, String desc,
+            String signature, String[] exceptions) {
+        String newDesc = remapper.mapMethodDesc(desc);
+        MethodVisitor mv = super.visitMethod(access, remapper.mapMethodName(
+                className, name, desc), newDesc, remapper.mapSignature(
+                signature, false),
+                exceptions == null ? null : remapper.mapTypes(exceptions));
+        return mv == null ? null : createRemappingMethodAdapter(access,
+                newDesc, mv);
+    }
+
+    @Override
+    public void visitInnerClass(String name, String outerName,
+            String innerName, int access) {
+        // TODO should innerName be changed?
+        super.visitInnerClass(remapper.mapType(name), outerName == null ? null
+                : remapper.mapType(outerName), innerName, access);
+    }
+
+    @Override
+    public void visitOuterClass(String owner, String name, String desc) {
+        super.visitOuterClass(remapper.mapType(owner), name == null ? null
+                : remapper.mapMethodName(owner, name, desc),
+                desc == null ? null : remapper.mapMethodDesc(desc));
+    }
+
+    protected FieldVisitor createRemappingFieldAdapter(FieldVisitor fv) {
+        return new RemappingFieldAdapter(fv, remapper);
+    }
+
+    protected MethodVisitor createRemappingMethodAdapter(int access,
+            String newDesc, MethodVisitor mv) {
+        return new RemappingMethodAdapter(access, newDesc, mv, remapper);
+    }
+
+    protected AnnotationVisitor createRemappingAnnotationAdapter(
+            AnnotationVisitor av) {
+        return new RemappingAnnotationAdapter(av, remapper);
+    }
+}
diff --git a/contrib/asm/src/org/objectweb/asm/commons/RemappingFieldAdapter.java b/contrib/asm/src/org/objectweb/asm/commons/RemappingFieldAdapter.java
new file mode 100644 (file)
index 0000000..3179aba
--- /dev/null
@@ -0,0 +1,71 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.objectweb.asm.commons;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.TypePath;
+
+/**
+ * A {@link FieldVisitor} adapter for type remapping.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class RemappingFieldAdapter extends FieldVisitor {
+
+    private final Remapper remapper;
+
+    public RemappingFieldAdapter(final FieldVisitor fv, final Remapper remapper) {
+        this(Opcodes.ASM5, fv, remapper);
+    }
+
+    protected RemappingFieldAdapter(final int api, final FieldVisitor fv,
+            final Remapper remapper) {
+        super(api, fv);
+        this.remapper = remapper;
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+        AnnotationVisitor av = fv.visitAnnotation(remapper.mapDesc(desc),
+                visible);
+        return av == null ? null : new RemappingAnnotationAdapter(av, remapper);
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
+                remapper.mapDesc(desc), visible);
+        return av == null ? null : new RemappingAnnotationAdapter(av, remapper);
+    }
+}
diff --git a/contrib/asm/src/org/objectweb/asm/commons/RemappingMethodAdapter.java b/contrib/asm/src/org/objectweb/asm/commons/RemappingMethodAdapter.java
new file mode 100644 (file)
index 0000000..c9badc2
--- /dev/null
@@ -0,0 +1,224 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.objectweb.asm.commons;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Handle;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.TypePath;
+
+/**
+ * A {@link LocalVariablesSorter} for type mapping.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class RemappingMethodAdapter extends LocalVariablesSorter {
+
+    protected final Remapper remapper;
+
+    public RemappingMethodAdapter(final int access, final String desc,
+            final MethodVisitor mv, final Remapper remapper) {
+        this(Opcodes.ASM5, access, desc, mv, remapper);
+    }
+
+    protected RemappingMethodAdapter(final int api, final int access,
+            final String desc, final MethodVisitor mv, final Remapper remapper) {
+        super(api, access, desc, mv);
+        this.remapper = remapper;
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotationDefault() {
+        AnnotationVisitor av = super.visitAnnotationDefault();
+        return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+        AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
+                visible);
+        return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
+                remapper.mapDesc(desc), visible);
+        return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+    }
+
+    @Override
+    public AnnotationVisitor visitParameterAnnotation(int parameter,
+            String desc, boolean visible) {
+        AnnotationVisitor av = super.visitParameterAnnotation(parameter,
+                remapper.mapDesc(desc), visible);
+        return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+    }
+
+    @Override
+    public void visitFrame(int type, int nLocal, Object[] local, int nStack,
+            Object[] stack) {
+        super.visitFrame(type, nLocal, remapEntries(nLocal, local), nStack,
+                remapEntries(nStack, stack));
+    }
+
+    private Object[] remapEntries(int n, Object[] entries) {
+        for (int i = 0; i < n; i++) {
+            if (entries[i] instanceof String) {
+                Object[] newEntries = new Object[n];
+                if (i > 0) {
+                    System.arraycopy(entries, 0, newEntries, 0, i);
+                }
+                do {
+                    Object t = entries[i];
+                    newEntries[i++] = t instanceof String ? remapper
+                            .mapType((String) t) : t;
+                } while (i < n);
+                return newEntries;
+            }
+        }
+        return entries;
+    }
+
+    @Override
+    public void visitFieldInsn(int opcode, String owner, String name,
+            String desc) {
+        super.visitFieldInsn(opcode, remapper.mapType(owner),
+                remapper.mapFieldName(owner, name, desc),
+                remapper.mapDesc(desc));
+    }
+
+    @Deprecated
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        if (api >= Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc,
+                opcode == Opcodes.INVOKEINTERFACE);
+    }
+
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        if (api < Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc, itf);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc, itf);
+    }
+
+    private void doVisitMethodInsn(int opcode, String owner, String name,
+            String desc, boolean itf) {
+        // Calling super.visitMethodInsn requires to call the correct version
+        // depending on this.api (otherwise infinite loops can occur). To
+        // simplify and to make it easier to automatically remove the backward
+        // compatibility code, we inline the code of the overridden method here.
+        // IMPORTANT: THIS ASSUMES THAT visitMethodInsn IS NOT OVERRIDDEN IN
+        // LocalVariableSorter.
+        if (mv != null) {
+            mv.visitMethodInsn(opcode, remapper.mapType(owner),
+                    remapper.mapMethodName(owner, name, desc),
+                    remapper.mapMethodDesc(desc), itf);
+        }
+    }
+
+    @Override
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
+        for (int i = 0; i < bsmArgs.length; i++) {
+            bsmArgs[i] = remapper.mapValue(bsmArgs[i]);
+        }
+        super.visitInvokeDynamicInsn(
+                remapper.mapInvokeDynamicMethodName(name, desc),
+                remapper.mapMethodDesc(desc), (Handle) remapper.mapValue(bsm),
+                bsmArgs);
+    }
+
+    @Override
+    public void visitTypeInsn(int opcode, String type) {
+        super.visitTypeInsn(opcode, remapper.mapType(type));
+    }
+
+    @Override
+    public void visitLdcInsn(Object cst) {
+        super.visitLdcInsn(remapper.mapValue(cst));
+    }
+
+    @Override
+    public void visitMultiANewArrayInsn(String desc, int dims) {
+        super.visitMultiANewArrayInsn(remapper.mapDesc(desc), dims);
+    }
+
+    @Override
+    public AnnotationVisitor visitInsnAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        AnnotationVisitor av = super.visitInsnAnnotation(typeRef, typePath,
+                remapper.mapDesc(desc), visible);
+        return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+    }
+
+    @Override
+    public void visitTryCatchBlock(Label start, Label end, Label handler,
+            String type) {
+        super.visitTryCatchBlock(start, end, handler, type == null ? null
+                : remapper.mapType(type));
+    }
+
+    @Override
+    public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        AnnotationVisitor av = super.visitTryCatchAnnotation(typeRef, typePath,
+                remapper.mapDesc(desc), visible);
+        return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+    }
+
+    @Override
+    public void visitLocalVariable(String name, String desc, String signature,
+            Label start, Label end, int index) {
+        super.visitLocalVariable(name, remapper.mapDesc(desc),
+                remapper.mapSignature(signature, true), start, end, index);
+    }
+
+    @Override
+    public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+            TypePath typePath, Label[] start, Label[] end, int[] index,
+            String desc, boolean visible) {
+        AnnotationVisitor av = super.visitLocalVariableAnnotation(typeRef,
+                typePath, start, end, index, remapper.mapDesc(desc), visible);
+        return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+    }
+}
diff --git a/contrib/asm/src/org/objectweb/asm/commons/RemappingSignatureAdapter.java b/contrib/asm/src/org/objectweb/asm/commons/RemappingSignatureAdapter.java
new file mode 100644 (file)
index 0000000..5728034
--- /dev/null
@@ -0,0 +1,155 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.objectweb.asm.commons;
+
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.signature.SignatureVisitor;
+
+/**
+ * A {@link SignatureVisitor} adapter for type mapping.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class RemappingSignatureAdapter extends SignatureVisitor {
+
+    private final SignatureVisitor v;
+
+    private final Remapper remapper;
+
+    private String className;
+
+    public RemappingSignatureAdapter(final SignatureVisitor v,
+            final Remapper remapper) {
+        this(Opcodes.ASM5, v, remapper);
+    }
+
+    protected RemappingSignatureAdapter(final int api,
+            final SignatureVisitor v, final Remapper remapper) {
+        super(api);
+        this.v = v;
+        this.remapper = remapper;
+    }
+
+    @Override
+    public void visitClassType(String name) {
+        className = name;
+        v.visitClassType(remapper.mapType(name));
+    }
+
+    @Override
+    public void visitInnerClassType(String name) {
+        String remappedOuter = remapper.mapType(className) + '$';
+        className = className + '$' + name;
+        String remappedName = remapper.mapType(className);
+        int index = remappedName.startsWith(remappedOuter) ? remappedOuter
+                .length() : remappedName.lastIndexOf('$') + 1;
+        v.visitInnerClassType(remappedName.substring(index));
+    }
+
+    @Override
+    public void visitFormalTypeParameter(String name) {
+        v.visitFormalTypeParameter(name);
+    }
+
+    @Override
+    public void visitTypeVariable(String name) {
+        v.visitTypeVariable(name);
+    }
+
+    @Override
+    public SignatureVisitor visitArrayType() {
+        v.visitArrayType();
+        return this;
+    }
+
+    @Override
+    public void visitBaseType(char descriptor) {
+        v.visitBaseType(descriptor);
+    }
+
+    @Override
+    public SignatureVisitor visitClassBound() {
+        v.visitClassBound();
+        return this;
+    }
+
+    @Override
+    public SignatureVisitor visitExceptionType() {
+        v.visitExceptionType();
+        return this;
+    }
+
+    @Override
+    public SignatureVisitor visitInterface() {
+        v.visitInterface();
+        return this;
+    }
+
+    @Override
+    public SignatureVisitor visitInterfaceBound() {
+        v.visitInterfaceBound();
+        return this;
+    }
+
+    @Override
+    public SignatureVisitor visitParameterType() {
+        v.visitParameterType();
+        return this;
+    }
+
+    @Override
+    public SignatureVisitor visitReturnType() {
+        v.visitReturnType();
+        return this;
+    }
+
+    @Override
+    public SignatureVisitor visitSuperclass() {
+        v.visitSuperclass();
+        return this;
+    }
+
+    @Override
+    public void visitTypeArgument() {
+        v.visitTypeArgument();
+    }
+
+    @Override
+    public SignatureVisitor visitTypeArgument(char wildcard) {
+        v.visitTypeArgument(wildcard);
+        return this;
+    }
+
+    @Override
+    public void visitEnd() {
+        v.visitEnd();
+    }
+}
diff --git a/contrib/asm/src/org/objectweb/asm/commons/SimpleRemapper.java b/contrib/asm/src/org/objectweb/asm/commons/SimpleRemapper.java
new file mode 100644 (file)
index 0000000..7b42b9b
--- /dev/null
@@ -0,0 +1,75 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.objectweb.asm.commons;
+
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * A {@link Remapper} using a {@link Map} to define its mapping.
+ *
+ * @author Eugene Kuleshov
+ */
+public class SimpleRemapper extends Remapper {
+
+    private final Map<String, String> mapping;
+
+    public SimpleRemapper(Map<String, String> mapping) {
+        this.mapping = mapping;
+    }
+
+    public SimpleRemapper(String oldName, String newName) {
+        this.mapping = Collections.singletonMap(oldName, newName);
+    }
+
+    @Override
+    public String mapMethodName(String owner, String name, String desc) {
+        String s = map(owner + '.' + name + desc);
+        return s == null ? name : s;
+    }
+
+    @Override
+    public String mapInvokeDynamicMethodName(String name, String desc) {
+        String s = map('.' + name + desc);
+        return s == null ? name : s;
+    }
+
+    @Override
+    public String mapFieldName(String owner, String name, String desc) {
+        String s = map(owner + '.' + name);
+        return s == null ? name : s;
+    }
+
+    @Override
+    public String map(String key) {
+        return mapping.get(key);
+    }
+}
diff --git a/contrib/asm/src/org/objectweb/asm/signature/SignatureReader.java b/contrib/asm/src/org/objectweb/asm/signature/SignatureReader.java
new file mode 100644 (file)
index 0000000..1083b3d
--- /dev/null
@@ -0,0 +1,228 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.signature;
+
+/**
+ * A type signature parser to make a signature visitor visit an existing
+ * signature.
+ * 
+ * @author Thomas Hallgren
+ * @author Eric Bruneton
+ */
+public class SignatureReader {
+
+    /**
+     * The signature to be read.
+     */
+    private final String signature;
+
+    /**
+     * Constructs a {@link SignatureReader} for the given signature.
+     * 
+     * @param signature
+     *            A <i>ClassSignature</i>, <i>MethodTypeSignature</i>, or
+     *            <i>FieldTypeSignature</i>.
+     */
+    public SignatureReader(final String signature) {
+        this.signature = signature;
+    }
+
+    /**
+     * Makes the given visitor visit the signature of this
+     * {@link SignatureReader}. This signature is the one specified in the
+     * constructor (see {@link #SignatureReader(String) SignatureReader}). This
+     * method is intended to be called on a {@link SignatureReader} that was
+     * created using a <i>ClassSignature</i> (such as the <code>signature</code>
+     * parameter of the {@link org.objectweb.asm.ClassVisitor#visit
+     * ClassVisitor.visit} method) or a <i>MethodTypeSignature</i> (such as the
+     * <code>signature</code> parameter of the
+     * {@link org.objectweb.asm.ClassVisitor#visitMethod
+     * ClassVisitor.visitMethod} method).
+     * 
+     * @param v
+     *            the visitor that must visit this signature.
+     */
+    public void accept(final SignatureVisitor v) {
+        String signature = this.signature;
+        int len = signature.length();
+        int pos;
+        char c;
+
+        if (signature.charAt(0) == '<') {
+            pos = 2;
+            do {
+                int end = signature.indexOf(':', pos);
+                v.visitFormalTypeParameter(signature.substring(pos - 1, end));
+                pos = end + 1;
+
+                c = signature.charAt(pos);
+                if (c == 'L' || c == '[' || c == 'T') {
+                    pos = parseType(signature, pos, v.visitClassBound());
+                }
+
+                while ((c = signature.charAt(pos++)) == ':') {
+                    pos = parseType(signature, pos, v.visitInterfaceBound());
+                }
+            } while (c != '>');
+        } else {
+            pos = 0;
+        }
+
+        if (signature.charAt(pos) == '(') {
+            pos++;
+            while (signature.charAt(pos) != ')') {
+                pos = parseType(signature, pos, v.visitParameterType());
+            }
+            pos = parseType(signature, pos + 1, v.visitReturnType());
+            while (pos < len) {
+                pos = parseType(signature, pos + 1, v.visitExceptionType());
+            }
+        } else {
+            pos = parseType(signature, pos, v.visitSuperclass());
+            while (pos < len) {
+                pos = parseType(signature, pos, v.visitInterface());
+            }
+        }
+    }
+
+    /**
+     * Makes the given visitor visit the signature of this
+     * {@link SignatureReader}. This signature is the one specified in the
+     * constructor (see {@link #SignatureReader(String) SignatureReader}). This
+     * method is intended to be called on a {@link SignatureReader} that was
+     * created using a <i>FieldTypeSignature</i>, such as the
+     * <code>signature</code> parameter of the
+     * {@link org.objectweb.asm.ClassVisitor#visitField ClassVisitor.visitField}
+     * or {@link org.objectweb.asm.MethodVisitor#visitLocalVariable
+     * MethodVisitor.visitLocalVariable} methods.
+     * 
+     * @param v
+     *            the visitor that must visit this signature.
+     */
+    public void acceptType(final SignatureVisitor v) {
+        parseType(this.signature, 0, v);
+    }
+
+    /**
+     * Parses a field type signature and makes the given visitor visit it.
+     * 
+     * @param signature
+     *            a string containing the signature that must be parsed.
+     * @param pos
+     *            index of the first character of the signature to parsed.
+     * @param v
+     *            the visitor that must visit this signature.
+     * @return the index of the first character after the parsed signature.
+     */
+    private static int parseType(final String signature, int pos,
+            final SignatureVisitor v) {
+        char c;
+        int start, end;
+        boolean visited, inner;
+        String name;
+
+        switch (c = signature.charAt(pos++)) {
+        case 'Z':
+        case 'C':
+        case 'B':
+        case 'S':
+        case 'I':
+        case 'F':
+        case 'J':
+        case 'D':
+        case 'V':
+            v.visitBaseType(c);
+            return pos;
+
+        case '[':
+            return parseType(signature, pos, v.visitArrayType());
+
+        case 'T':
+            end = signature.indexOf(';', pos);
+            v.visitTypeVariable(signature.substring(pos, end));
+            return end + 1;
+
+        default: // case 'L':
+            start = pos;
+            visited = false;
+            inner = false;
+            for (;;) {
+                switch (c = signature.charAt(pos++)) {
+                case '.':
+                case ';':
+                    if (!visited) {
+                        name = signature.substring(start, pos - 1);
+                        if (inner) {
+                            v.visitInnerClassType(name);
+                        } else {
+                            v.visitClassType(name);
+                        }
+                    }
+                    if (c == ';') {
+                        v.visitEnd();
+                        return pos;
+                    }
+                    start = pos;
+                    visited = false;
+                    inner = true;
+                    break;
+
+                case '<':
+                    name = signature.substring(start, pos - 1);
+                    if (inner) {
+                        v.visitInnerClassType(name);
+                    } else {
+                        v.visitClassType(name);
+                    }
+                    visited = true;
+                    top: for (;;) {
+                        switch (c = signature.charAt(pos)) {
+                        case '>':
+                            break top;
+                        case '*':
+                            ++pos;
+                            v.visitTypeArgument();
+                            break;
+                        case '+':
+                        case '-':
+                            pos = parseType(signature, pos + 1,
+                                    v.visitTypeArgument(c));
+                            break;
+                        default:
+                            pos = parseType(signature, pos,
+                                    v.visitTypeArgument('='));
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/contrib/asm/src/org/objectweb/asm/signature/SignatureVisitor.java b/contrib/asm/src/org/objectweb/asm/signature/SignatureVisitor.java
new file mode 100644 (file)
index 0000000..1dba32d
--- /dev/null
@@ -0,0 +1,238 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.signature;
+
+import org.objectweb.asm.Opcodes;
+
+/**
+ * A visitor to visit a generic signature. The methods of this interface must be
+ * called in one of the three following orders (the last one is the only valid
+ * order for a {@link SignatureVisitor} that is returned by a method of this
+ * interface):
+ * <ul>
+ * <li><i>ClassSignature</i> = ( <tt>visitFormalTypeParameter</tt>
+ * <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* (
+ * <tt>visitSuperclass</tt> <tt>visitInterface</tt>* )</li>
+ * <li><i>MethodSignature</i> = ( <tt>visitFormalTypeParameter</tt>
+ * <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* (
+ * <tt>visitParameterType</tt>* <tt>visitReturnType</tt>
+ * <tt>visitExceptionType</tt>* )</li>
+ * <li><i>TypeSignature</i> = <tt>visitBaseType</tt> |
+ * <tt>visitTypeVariable</tt> | <tt>visitArrayType</tt> | (
+ * <tt>visitClassType</tt> <tt>visitTypeArgument</tt>* (
+ * <tt>visitInnerClassType</tt> <tt>visitTypeArgument</tt>* )* <tt>visitEnd</tt>
+ * ) )</li>
+ * </ul>
+ * 
+ * @author Thomas Hallgren
+ * @author Eric Bruneton
+ */
+public abstract class SignatureVisitor {
+
+    /**
+     * Wildcard for an "extends" type argument.
+     */
+    public final static char EXTENDS = '+';
+
+    /**
+     * Wildcard for a "super" type argument.
+     */
+    public final static char SUPER = '-';
+
+    /**
+     * Wildcard for a normal type argument.
+     */
+    public final static char INSTANCEOF = '=';
+
+    /**
+     * The ASM API version implemented by this visitor. The value of this field
+     * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     */
+    protected final int api;
+
+    /**
+     * Constructs a new {@link SignatureVisitor}.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     */
+    public SignatureVisitor(final int api) {
+        if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
+            throw new IllegalArgumentException();
+        }
+        this.api = api;
+    }
+
+    /**
+     * Visits a formal type parameter.
+     * 
+     * @param name
+     *            the name of the formal parameter.
+     */
+    public void visitFormalTypeParameter(String name) {
+    }
+
+    /**
+     * Visits the class bound of the last visited formal type parameter.
+     * 
+     * @return a non null visitor to visit the signature of the class bound.
+     */
+    public SignatureVisitor visitClassBound() {
+        return this;
+    }
+
+    /**
+     * Visits an interface bound of the last visited formal type parameter.
+     * 
+     * @return a non null visitor to visit the signature of the interface bound.
+     */
+    public SignatureVisitor visitInterfaceBound() {
+        return this;
+    }
+
+    /**
+     * Visits the type of the super class.
+     * 
+     * @return a non null visitor to visit the signature of the super class
+     *         type.
+     */
+    public SignatureVisitor visitSuperclass() {
+        return this;
+    }
+
+    /**
+     * Visits the type of an interface implemented by the class.
+     * 
+     * @return a non null visitor to visit the signature of the interface type.
+     */
+    public SignatureVisitor visitInterface() {
+        return this;
+    }
+
+    /**
+     * Visits the type of a method parameter.
+     * 
+     * @return a non null visitor to visit the signature of the parameter type.
+     */
+    public SignatureVisitor visitParameterType() {
+        return this;
+    }
+
+    /**
+     * Visits the return type of the method.
+     * 
+     * @return a non null visitor to visit the signature of the return type.
+     */
+    public SignatureVisitor visitReturnType() {
+        return this;
+    }
+
+    /**
+     * Visits the type of a method exception.
+     * 
+     * @return a non null visitor to visit the signature of the exception type.
+     */
+    public SignatureVisitor visitExceptionType() {
+        return this;
+    }
+
+    /**
+     * Visits a signature corresponding to a primitive type.
+     * 
+     * @param descriptor
+     *            the descriptor of the primitive type, or 'V' for <tt>void</tt>
+     *            .
+     */
+    public void visitBaseType(char descriptor) {
+    }
+
+    /**
+     * Visits a signature corresponding to a type variable.
+     * 
+     * @param name
+     *            the name of the type variable.
+     */
+    public void visitTypeVariable(String name) {
+    }
+
+    /**
+     * Visits a signature corresponding to an array type.
+     * 
+     * @return a non null visitor to visit the signature of the array element
+     *         type.
+     */
+    public SignatureVisitor visitArrayType() {
+        return this;
+    }
+
+    /**
+     * Starts the visit of a signature corresponding to a class or interface
+     * type.
+     * 
+     * @param name
+     *            the internal name of the class or interface.
+     */
+    public void visitClassType(String name) {
+    }
+
+    /**
+     * Visits an inner class.
+     * 
+     * @param name
+     *            the local name of the inner class in its enclosing class.
+     */
+    public void visitInnerClassType(String name) {
+    }
+
+    /**
+     * Visits an unbounded type argument of the last visited class or inner
+     * class type.
+     */
+    public void visitTypeArgument() {
+    }
+
+    /**
+     * Visits a type argument of the last visited class or inner class type.
+     * 
+     * @param wildcard
+     *            '+', '-' or '='.
+     * @return a non null visitor to visit the signature of the type argument.
+     */
+    public SignatureVisitor visitTypeArgument(char wildcard) {
+        return this;
+    }
+
+    /**
+     * Ends the visit of a signature corresponding to a class or interface type.
+     */
+    public void visitEnd() {
+    }
+}
diff --git a/contrib/asm/src/org/objectweb/asm/signature/SignatureWriter.java b/contrib/asm/src/org/objectweb/asm/signature/SignatureWriter.java
new file mode 100644 (file)
index 0000000..ec475db
--- /dev/null
@@ -0,0 +1,227 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.signature;
+
+import org.objectweb.asm.Opcodes;
+
+/**
+ * A signature visitor that generates signatures in string format.
+ * 
+ * @author Thomas Hallgren
+ * @author Eric Bruneton
+ */
+public class SignatureWriter extends SignatureVisitor {
+
+    /**
+     * Buffer used to construct the signature.
+     */
+    private final StringBuffer buf = new StringBuffer();
+
+    /**
+     * Indicates if the signature contains formal type parameters.
+     */
+    private boolean hasFormals;
+
+    /**
+     * Indicates if the signature contains method parameter types.
+     */
+    private boolean hasParameters;
+
+    /**
+     * Stack used to keep track of class types that have arguments. Each element
+     * of this stack is a boolean encoded in one bit. The top of the stack is
+     * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping =
+     * /2.
+     */
+    private int argumentStack;
+
+    /**
+     * Constructs a new {@link SignatureWriter} object.
+     */
+    public SignatureWriter() {
+        super(Opcodes.ASM5);
+    }
+
+    // ------------------------------------------------------------------------
+    // Implementation of the SignatureVisitor interface
+    // ------------------------------------------------------------------------
+
+    @Override
+    public void visitFormalTypeParameter(final String name) {
+        if (!hasFormals) {
+            hasFormals = true;
+            buf.append('<');
+        }
+        buf.append(name);
+        buf.append(':');
+    }
+
+    @Override
+    public SignatureVisitor visitClassBound() {
+        return this;
+    }
+
+    @Override
+    public SignatureVisitor visitInterfaceBound() {
+        buf.append(':');
+        return this;
+    }
+
+    @Override
+    public SignatureVisitor visitSuperclass() {
+        endFormals();
+        return this;
+    }
+
+    @Override
+    public SignatureVisitor visitInterface() {
+        return this;
+    }
+
+    @Override
+    public SignatureVisitor visitParameterType() {
+        endFormals();
+        if (!hasParameters) {
+            hasParameters = true;
+            buf.append('(');
+        }
+        return this;
+    }
+
+    @Override
+    public SignatureVisitor visitReturnType() {
+        endFormals();
+        if (!hasParameters) {
+            buf.append('(');
+        }
+        buf.append(')');
+        return this;
+    }
+
+    @Override
+    public SignatureVisitor visitExceptionType() {
+        buf.append('^');
+        return this;
+    }
+
+    @Override
+    public void visitBaseType(final char descriptor) {
+        buf.append(descriptor);
+    }
+
+    @Override
+    public void visitTypeVariable(final String name) {
+        buf.append('T');
+        buf.append(name);
+        buf.append(';');
+    }
+
+    @Override
+    public SignatureVisitor visitArrayType() {
+        buf.append('[');
+        return this;
+    }
+
+    @Override
+    public void visitClassType(final String name) {
+        buf.append('L');
+        buf.append(name);
+        argumentStack *= 2;
+    }
+
+    @Override
+    public void visitInnerClassType(final String name) {
+        endArguments();
+        buf.append('.');
+        buf.append(name);
+        argumentStack *= 2;
+    }
+
+    @Override
+    public void visitTypeArgument() {
+        if (argumentStack % 2 == 0) {
+            ++argumentStack;
+            buf.append('<');
+        }
+        buf.append('*');
+    }
+
+    @Override
+    public SignatureVisitor visitTypeArgument(final char wildcard) {
+        if (argumentStack % 2 == 0) {
+            ++argumentStack;
+            buf.append('<');
+        }
+        if (wildcard != '=') {
+            buf.append(wildcard);
+        }
+        return this;
+    }
+
+    @Override
+    public void visitEnd() {
+        endArguments();
+        buf.append(';');
+    }
+
+    /**
+     * Returns the signature that was built by this signature writer.
+     * 
+     * @return the signature that was built by this signature writer.
+     */
+    @Override
+    public String toString() {
+        return buf.toString();
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Ends the formal type parameters section of the signature.
+     */
+    private void endFormals() {
+        if (hasFormals) {
+            hasFormals = false;
+            buf.append('>');
+        }
+    }
+
+    /**
+     * Ends the type arguments of a class or inner class type.
+     */
+    private void endArguments() {
+        if (argumentStack % 2 != 0) {
+            buf.append('>');
+        }
+        argumentStack /= 2;
+    }
+}
\ No newline at end of file
index 71faae0..10ddecc 100644 (file)
@@ -32,15 +32,48 @@ package org.videolan;
  *       in class file com/tcs/blr/bluray/pal/fox/controller/d
  */
 
+import java.util.Map;
+
 import org.objectweb.asm.ClassReader;
 import org.objectweb.asm.ClassWriter;
 import org.objectweb.asm.ClassVisitor;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.Attribute;
+import org.objectweb.asm.commons.SimpleRemapper;
+import org.objectweb.asm.commons.RemappingClassAdapter;
 
-class BDJClassFileTransformer
+public class BDJClassFileTransformer
 {
+    public byte[] rename(byte[] b, int off, int len, Map mappings)
+        throws ClassFormatError
+    {
+        byte[] r = new byte[len];
+        for (int i = 0; i < len; i++)
+            r[i] = b[i+off];
+
+        return rename(r, mappings);
+    }
+
+    public byte[] rename(byte[] b, Map mappings)
+        throws ClassFormatError
+    {
+        logger.info("Trying to rename class (" + b.length + " bytes)");
+
+        try {
+            SimpleRemapper m = new SimpleRemapper(mappings);
+            ClassReader cr = new ClassReader(b);
+            ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES/* | ClassWriter.COMPUTE_MAXS*/);
+            ClassVisitor cv = new RemappingClassAdapter(cw, m);
+            cr.accept(cv, ClassReader.SKIP_DEBUG);
+            return cw.toByteArray();
+        } catch (Exception e) {
+            logger.error("Failed renaming class: " + e);
+        }
+
+        return null;
+    }
+
     public byte[] strip(byte[] b, int off, int len)
         throws ClassFormatError
     {
diff --git a/src/libbluray/bdj/java/org/videolan/mmbd/Adapter.java b/src/libbluray/bdj/java/org/videolan/mmbd/Adapter.java
new file mode 100644 (file)
index 0000000..da862b4
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * This file is part of libbluray
+ * Copyright (C) 2017  VideoLAN
+ *
+ * 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, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * BD-J support classes for libmmbd
+ */
+
+package org.videolan.mmbd;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import org.videolan.BDJClassFileTransformer;
+import org.videolan.BDJClassLoaderAdapter;
+import org.videolan.Logger;
+
+import javax.media.ClockStartedError;
+import javax.media.Manager;
+import javax.media.NoPlayerException;
+import javax.media.Player;
+import javax.tv.xlet.Xlet;
+import javax.tv.xlet.XletContext;
+import javax.tv.xlet.XletStateChangeException;
+import org.bluray.bdplus.StatusListener;
+
+public class Adapter implements BDJClassLoaderAdapter {
+
+    public Map getHideClasses() {
+        return null;
+    }
+
+    public Map getBootClasses() {
+        return bootClasses;
+    }
+
+    public Map getXletClasses() {
+        return xletClasses;
+    }
+
+    public Adapter() throws ClassNotFoundException {
+        /* relocate classes to avoid runtime package collisions */
+
+        final String s1 = "org/videolan/mmbd/Adapter$Xlet";
+        final String s2 = "org/videolan/mmbd/Adapter$If";
+        Map m = new HashMap();
+        String d1, d2;
+        m.put(s1, d1 = (new String(b0) + new String(b1)));
+        m.put(s2, d2 = (new String(b0) + new String(b2)));
+
+        BDJClassFileTransformer t = new BDJClassFileTransformer();
+        byte[] c1 = t.rename(loadBootClassCode(s1), m);
+        byte[] c2 = t.rename(loadBootClassCode(s2), m);
+
+        if (c1 != null) {
+            bootClasses = new HashMap();
+            bootClasses.put(d1.replace('/', '.'), c1);
+        }
+        if (c2 != null) {
+            xletClasses = new HashMap();
+            xletClasses.put(d2.replace('/', '.'), c2);
+        }
+    }
+
+    public static abstract class If {
+        protected If() {}
+    }
+
+    public static class Xlet implements StatusListener {
+        private static Xlet instance = new Xlet();
+        private javax.tv.xlet.Xlet xlet = null;
+        private XletContext ctx = null;
+
+        static private void log(String s) {
+            System.out.println(s);
+        }
+        static private void error(String s) {
+            System.err.println(s);
+        }
+
+        public static Xlet initXlet(javax.tv.xlet.Xlet xlet, XletContext ctx) throws XletStateChangeException {
+            if ((xlet == null) || (ctx == null)) {
+                error("initXlet: null argument");
+                throw new XletStateChangeException();
+            }
+            if ((instance.xlet == xlet) && (instance.ctx == ctx)) {
+                error("initXlet: invalid arguments");
+                throw new XletStateChangeException();
+            }
+            log("initXlet");
+            instance.xlet = xlet;
+            instance.ctx = ctx;
+            return instance;
+        }
+
+        public static Xlet lookup(XletContext ctx) {
+            return instance;
+        }
+
+        public void startXlet() throws XletStateChangeException {
+        }
+
+        public void pauseXlet() {
+        }
+
+        public void destroyXlet(boolean a) {
+            this.instance.xlet = null;
+            this.instance.ctx = null;
+        }
+
+        public boolean isAuthRequired() {
+            log("isAuthRequired");
+            return false;
+        }
+
+        public void doAuth() throws InterruptedException {
+            doAuth(null);
+        }
+
+        public synchronized void doAuth(If a) throws InterruptedException, RuntimeException {
+            error("doAuth");
+        }
+
+        public void destroy() {
+        }
+
+        public void receive(int i) {
+        }
+
+        public byte[] getMMV() {
+            byte[] b = new byte[8];
+            new java.util.Random().nextBytes(b);
+            log("getMMV");
+            return b;
+        }
+
+        public Player createPlayer(javax.media.protocol.DataSource s) throws IOException, NoPlayerException {
+            return Manager.createPlayer(s);
+        }
+
+        public Player createPlayer(javax.media.MediaLocator l) throws IOException, NoPlayerException {
+            return Manager.createPlayer(l);
+        }
+
+        public Player createPlayer(java.net.URL u) throws IOException, NoPlayerException {
+            return Manager.createPlayer(u);
+        }
+
+        public void destroyPlayer(Player p) {
+            if (p == null)
+                return;
+            p.stop();
+            try {
+                p.deallocate();
+            } catch (ClockStartedError localClockStartedError) {
+            }
+            p.close();
+        }
+    }
+
+    /*
+     * class loader
+     */
+
+    private final byte[] b0 = {99,111,109,47,109,97,99,114,111,118,105,115,105,111,110,47,98,100,112,108,117,115,47};
+    private final byte[] b1 = {77,86,67,111,109,109};
+    private final byte[] b2 = {83,116,114,101,101,116,76,111,99,107,71,101,116,116,101,114};
+
+    private byte[] loadBootClassCode(String name) throws ClassNotFoundException {
+        final String path = name.replace('.', '/').concat(".class");
+        InputStream is = null;
+        ByteArrayOutputStream os = new ByteArrayOutputStream();
+        byte[] buffer = new byte[0xffff];
+        try {
+            is = (InputStream)
+            AccessController.doPrivileged(
+                new PrivilegedAction() {
+                    public Object run() {
+                        return ClassLoader.getSystemResourceAsStream(path);
+                    }
+                });
+
+            if (is == null) {
+                logger.error("loadBootClassCode(" + name + "): not found");
+                throw new ClassNotFoundException(name);
+            }
+
+            while (true) {
+                int r = is.read(buffer);
+                if (r == -1) {
+                    break;
+                }
+                os.write(buffer, 0, r);
+            }
+
+            return os.toByteArray();
+
+        } catch (Exception e) {
+            logger.error("loadBootClassCode(" + name + ") failed: " + e);
+            throw new ClassNotFoundException(name);
+
+        } finally {
+            try {
+                if (is != null)
+                    is.close();
+            } catch (IOException ioe) {
+            }
+            try {
+                if (os != null)
+                    os.close();
+            } catch (IOException ioe) {
+            }
+        }
+    }
+
+    private Map bootClasses = new HashMap();
+    private Map xletClasses = new HashMap();
+
+    private static final Logger logger = Logger.getLogger(Adapter.class.getName());
+}