| 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
/*  | 
 | 
 * Licensed to the Apache Software Foundation (ASF) under one or more  | 
 | 
 * contributor license agreements.  See the NOTICE file distributed with  | 
 | 
 * this work for additional information regarding copyright ownership.  | 
 | 
 * The ASF licenses this file to You under the Apache License, Version 2.0  | 
 | 
 * (the "License"); you may not use this file except in compliance with  | 
 | 
 * the License.  You may obtain a copy of the License at  | 
 | 
 *  | 
 | 
 *      http://www.apache.org/licenses/LICENSE-2.0  | 
 | 
 *  | 
 | 
 * Unless required by applicable law or agreed to in writing, software  | 
 | 
 * distributed under the License is distributed on an "AS IS" BASIS,  | 
 | 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  | 
 | 
 * See the License for the specific language governing permissions and  | 
 | 
 * limitations under the License.  | 
 | 
 */  | 
 | 
 | 
 | 
package com.sun.org.apache.bcel.internal.generic;  | 
 | 
 | 
 | 
import java.io.ByteArrayInputStream;  | 
 | 
import java.io.ByteArrayOutputStream;  | 
 | 
import java.io.DataInput;  | 
 | 
import java.io.DataInputStream;  | 
 | 
import java.io.DataOutputStream;  | 
 | 
import java.io.IOException;  | 
 | 
import java.util.ArrayList;  | 
 | 
import java.util.List;  | 
 | 
 | 
 | 
import com.sun.org.apache.bcel.internal.classfile.AnnotationEntry;  | 
 | 
import com.sun.org.apache.bcel.internal.classfile.Attribute;  | 
 | 
import com.sun.org.apache.bcel.internal.classfile.ConstantUtf8;  | 
 | 
import com.sun.org.apache.bcel.internal.classfile.ElementValuePair;  | 
 | 
import com.sun.org.apache.bcel.internal.classfile.RuntimeInvisibleAnnotations;  | 
 | 
import com.sun.org.apache.bcel.internal.classfile.RuntimeInvisibleParameterAnnotations;  | 
 | 
import com.sun.org.apache.bcel.internal.classfile.RuntimeVisibleAnnotations;  | 
 | 
import com.sun.org.apache.bcel.internal.classfile.RuntimeVisibleParameterAnnotations;  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
public class AnnotationEntryGen { | 
 | 
    private int typeIndex;  | 
 | 
 | 
 | 
    private List<ElementValuePairGen> evs;  | 
 | 
 | 
 | 
    private final ConstantPoolGen cpool;  | 
 | 
 | 
 | 
    private boolean isRuntimeVisible = false;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public AnnotationEntryGen(final AnnotationEntry a, final ConstantPoolGen cpool,  | 
 | 
                              final boolean copyPoolEntries) { | 
 | 
        this.cpool = cpool;  | 
 | 
        if (copyPoolEntries) { | 
 | 
            typeIndex = cpool.addUtf8(a.getAnnotationType());  | 
 | 
        } else { | 
 | 
            typeIndex = a.getAnnotationTypeIndex();  | 
 | 
        }  | 
 | 
        isRuntimeVisible = a.isRuntimeVisible();  | 
 | 
        evs = copyValues(a.getElementValuePairs(), cpool, copyPoolEntries);  | 
 | 
    }  | 
 | 
 | 
 | 
    private List<ElementValuePairGen> copyValues(final ElementValuePair[] in, final ConstantPoolGen cpool,  | 
 | 
                                                 final boolean copyPoolEntries) { | 
 | 
        final List<ElementValuePairGen> out = new ArrayList<>();  | 
 | 
        for (final ElementValuePair nvp : in) { | 
 | 
            out.add(new ElementValuePairGen(nvp, cpool, copyPoolEntries));  | 
 | 
        }  | 
 | 
        return out;  | 
 | 
    }  | 
 | 
 | 
 | 
    private AnnotationEntryGen(final ConstantPoolGen cpool) { | 
 | 
        this.cpool = cpool;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public AnnotationEntry getAnnotation() { | 
 | 
        final AnnotationEntry a = new AnnotationEntry(typeIndex, cpool.getConstantPool(),  | 
 | 
                isRuntimeVisible);  | 
 | 
        for (final ElementValuePairGen element : evs) { | 
 | 
            a.addElementNameValuePair(element.getElementNameValuePair());  | 
 | 
        }  | 
 | 
        return a;  | 
 | 
    }  | 
 | 
 | 
 | 
    public AnnotationEntryGen(final ObjectType type,  | 
 | 
                              final List<ElementValuePairGen> elements, final boolean vis,  | 
 | 
                              final ConstantPoolGen cpool) { | 
 | 
        this.cpool = cpool;  | 
 | 
        this.typeIndex = cpool.addUtf8(type.getSignature());  | 
 | 
        evs = elements;  | 
 | 
        isRuntimeVisible = vis;  | 
 | 
    }  | 
 | 
 | 
 | 
    public static AnnotationEntryGen read(final DataInput dis,  | 
 | 
                                          final ConstantPoolGen cpool, final boolean b) throws IOException { | 
 | 
        final AnnotationEntryGen a = new AnnotationEntryGen(cpool);  | 
 | 
        a.typeIndex = dis.readUnsignedShort();  | 
 | 
        final int elemValuePairCount = dis.readUnsignedShort();  | 
 | 
        for (int i = 0; i < elemValuePairCount; i++) { | 
 | 
            final int nidx = dis.readUnsignedShort();  | 
 | 
            a.addElementNameValuePair(new ElementValuePairGen(nidx,  | 
 | 
                    ElementValueGen.readElementValue(dis, cpool), cpool));  | 
 | 
        }  | 
 | 
        a.isRuntimeVisible(b);  | 
 | 
        return a;  | 
 | 
    }  | 
 | 
 | 
 | 
    public void dump(final DataOutputStream dos) throws IOException { | 
 | 
        dos.writeShort(typeIndex);   | 
 | 
        dos.writeShort(evs.size());   | 
 | 
        for (final ElementValuePairGen envp : evs) { | 
 | 
            envp.dump(dos);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    public void addElementNameValuePair(final ElementValuePairGen evp) { | 
 | 
        if (evs == null) { | 
 | 
            evs = new ArrayList<>();  | 
 | 
        }  | 
 | 
        evs.add(evp);  | 
 | 
    }  | 
 | 
 | 
 | 
    public int getTypeIndex() { | 
 | 
        return typeIndex;  | 
 | 
    }  | 
 | 
 | 
 | 
    public final String getTypeSignature() { | 
 | 
          | 
 | 
        final ConstantUtf8 utf8 = (ConstantUtf8) cpool  | 
 | 
                .getConstant(typeIndex/* c.getNameIndex() */);  | 
 | 
        return utf8.getBytes();  | 
 | 
    }  | 
 | 
 | 
 | 
    public final String getTypeName() { | 
 | 
        return getTypeSignature();  | 
 | 
        // Utility.signatureToString(getTypeSignature());  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public List<ElementValuePairGen> getValues() { | 
 | 
        return evs;  | 
 | 
    }  | 
 | 
 | 
 | 
    @Override  | 
 | 
    public String toString() { | 
 | 
        final StringBuilder s = new StringBuilder(32);   | 
 | 
        s.append("AnnotationGen:[").append(getTypeName()).append(" #").append(evs.size()).append(" {"); | 
 | 
        for (int i = 0; i < evs.size(); i++) { | 
 | 
            s.append(evs.get(i));  | 
 | 
            if (i + 1 < evs.size()) { | 
 | 
                s.append(","); | 
 | 
            }  | 
 | 
        }  | 
 | 
        s.append("}]"); | 
 | 
        return s.toString();  | 
 | 
    }  | 
 | 
 | 
 | 
    public String toShortString() { | 
 | 
        final StringBuilder s = new StringBuilder();  | 
 | 
        s.append("@").append(getTypeName()).append("("); | 
 | 
        for (int i = 0; i < evs.size(); i++) { | 
 | 
            s.append(evs.get(i));  | 
 | 
            if (i + 1 < evs.size()) { | 
 | 
                s.append(","); | 
 | 
            }  | 
 | 
        }  | 
 | 
        s.append(")"); | 
 | 
        return s.toString();  | 
 | 
    }  | 
 | 
 | 
 | 
    private void isRuntimeVisible(final boolean b) { | 
 | 
        isRuntimeVisible = b;  | 
 | 
    }  | 
 | 
 | 
 | 
    public boolean isRuntimeVisible() { | 
 | 
        return isRuntimeVisible;  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    static Attribute[] getAnnotationAttributes(final ConstantPoolGen cp, final AnnotationEntryGen[] annotationEntryGens) { | 
 | 
        if (annotationEntryGens.length == 0) { | 
 | 
            return new Attribute[0];  | 
 | 
        }  | 
 | 
 | 
 | 
        try { | 
 | 
            int countVisible = 0;  | 
 | 
            int countInvisible = 0;  | 
 | 
 | 
 | 
              | 
 | 
            for (final AnnotationEntryGen a : annotationEntryGens) { | 
 | 
                if (a.isRuntimeVisible()) { | 
 | 
                    countVisible++;  | 
 | 
                } else { | 
 | 
                    countInvisible++;  | 
 | 
                }  | 
 | 
            }  | 
 | 
 | 
 | 
            final ByteArrayOutputStream rvaBytes = new ByteArrayOutputStream();  | 
 | 
            final ByteArrayOutputStream riaBytes = new ByteArrayOutputStream();  | 
 | 
            try (DataOutputStream rvaDos = new DataOutputStream(rvaBytes);  | 
 | 
                    DataOutputStream riaDos = new DataOutputStream(riaBytes)) { | 
 | 
 | 
 | 
                rvaDos.writeShort(countVisible);  | 
 | 
                riaDos.writeShort(countInvisible);  | 
 | 
 | 
 | 
                  | 
 | 
                for (final AnnotationEntryGen a : annotationEntryGens) { | 
 | 
                    if (a.isRuntimeVisible()) { | 
 | 
                        a.dump(rvaDos);  | 
 | 
                    } else { | 
 | 
                        a.dump(riaDos);  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            }  | 
 | 
 | 
 | 
            final byte[] rvaData = rvaBytes.toByteArray();  | 
 | 
            final byte[] riaData = riaBytes.toByteArray();  | 
 | 
 | 
 | 
            int rvaIndex = -1;  | 
 | 
            int riaIndex = -1;  | 
 | 
 | 
 | 
            if (rvaData.length > 2) { | 
 | 
                rvaIndex = cp.addUtf8("RuntimeVisibleAnnotations"); | 
 | 
            }  | 
 | 
            if (riaData.length > 2) { | 
 | 
                riaIndex = cp.addUtf8("RuntimeInvisibleAnnotations"); | 
 | 
            }  | 
 | 
 | 
 | 
            final List<Attribute> newAttributes = new ArrayList<>();  | 
 | 
            if (rvaData.length > 2) { | 
 | 
                newAttributes.add(  | 
 | 
                        new RuntimeVisibleAnnotations(rvaIndex, rvaData.length,  | 
 | 
                            new DataInputStream(new ByteArrayInputStream(rvaData)), cp.getConstantPool()));  | 
 | 
            }  | 
 | 
            if (riaData.length > 2) { | 
 | 
                newAttributes.add(  | 
 | 
                        new RuntimeInvisibleAnnotations(riaIndex, riaData.length,  | 
 | 
                            new DataInputStream(new ByteArrayInputStream(riaData)), cp.getConstantPool()));  | 
 | 
            }  | 
 | 
 | 
 | 
            return newAttributes.toArray(new Attribute[newAttributes.size()]);  | 
 | 
        } catch (final IOException e) { | 
 | 
            System.err.println("IOException whilst processing annotations. " + | 
 | 
                    e.getMessage());  | 
 | 
        }  | 
 | 
        return null;  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    static Attribute[] getParameterAnnotationAttributes(  | 
 | 
            final ConstantPoolGen cp,  | 
 | 
            final List<AnnotationEntryGen>[] vec) { | 
 | 
        final int[] visCount = new int[vec.length];  | 
 | 
        int totalVisCount = 0;  | 
 | 
        final int[] invisCount = new int[vec.length];  | 
 | 
        int totalInvisCount = 0;  | 
 | 
        try { | 
 | 
            for (int i = 0; i < vec.length; i++) { | 
 | 
                if (vec[i] != null) { | 
 | 
                    for (final AnnotationEntryGen element : vec[i]) { | 
 | 
                        if (element.isRuntimeVisible()) { | 
 | 
                            visCount[i]++;  | 
 | 
                            totalVisCount++;  | 
 | 
                        } else { | 
 | 
                            invisCount[i]++;  | 
 | 
                            totalInvisCount++;  | 
 | 
                        }  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            }  | 
 | 
              | 
 | 
            final ByteArrayOutputStream rvaBytes = new ByteArrayOutputStream();  | 
 | 
            try (DataOutputStream rvaDos = new DataOutputStream(rvaBytes)) { | 
 | 
                rvaDos.writeByte(vec.length);   | 
 | 
                for (int i = 0; i < vec.length; i++) { | 
 | 
                    rvaDos.writeShort(visCount[i]);  | 
 | 
                    if (visCount[i] > 0) { | 
 | 
                        for (final AnnotationEntryGen element : vec[i]) { | 
 | 
                            if (element.isRuntimeVisible()) { | 
 | 
                                element.dump(rvaDos);  | 
 | 
                            }  | 
 | 
                        }  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            }  | 
 | 
              | 
 | 
            final ByteArrayOutputStream riaBytes = new ByteArrayOutputStream();  | 
 | 
            try (DataOutputStream riaDos = new DataOutputStream(riaBytes)) { | 
 | 
                riaDos.writeByte(vec.length);   | 
 | 
                for (int i = 0; i < vec.length; i++) { | 
 | 
                    riaDos.writeShort(invisCount[i]);  | 
 | 
                    if (invisCount[i] > 0) { | 
 | 
                        for (final AnnotationEntryGen element : vec[i]) { | 
 | 
                            if (!element.isRuntimeVisible()) { | 
 | 
                                element.dump(riaDos);  | 
 | 
                            }  | 
 | 
                        }  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            }  | 
 | 
            final byte[] rvaData = rvaBytes.toByteArray();  | 
 | 
            final byte[] riaData = riaBytes.toByteArray();  | 
 | 
            int rvaIndex = -1;  | 
 | 
            int riaIndex = -1;  | 
 | 
            if (totalVisCount > 0) { | 
 | 
                rvaIndex = cp.addUtf8("RuntimeVisibleParameterAnnotations"); | 
 | 
            }  | 
 | 
            if (totalInvisCount > 0) { | 
 | 
                riaIndex = cp.addUtf8("RuntimeInvisibleParameterAnnotations"); | 
 | 
            }  | 
 | 
            final List<Attribute> newAttributes = new ArrayList<>();  | 
 | 
            if (totalVisCount > 0) { | 
 | 
                newAttributes  | 
 | 
                        .add(new RuntimeVisibleParameterAnnotations(rvaIndex,  | 
 | 
                                rvaData.length,  | 
 | 
                                new DataInputStream(new ByteArrayInputStream(rvaData)),  | 
 | 
                                    cp.getConstantPool()));  | 
 | 
            }  | 
 | 
            if (totalInvisCount > 0) { | 
 | 
                newAttributes  | 
 | 
                        .add(new RuntimeInvisibleParameterAnnotations(riaIndex,  | 
 | 
                                riaData.length,  | 
 | 
                                new DataInputStream(new ByteArrayInputStream(riaData)),  | 
 | 
                                    cp.getConstantPool()));  | 
 | 
            }  | 
 | 
            return newAttributes.toArray(new Attribute[newAttributes.size()]);  | 
 | 
        } catch (final IOException e) { | 
 | 
            System.err.println("IOException whilst processing parameter annotations." + | 
 | 
                    e.getMessage());  | 
 | 
        }  | 
 | 
        return null;  | 
 | 
    }  | 
 | 
 | 
 | 
}  |