Package milk.jpatch.attribs

Source Code of milk.jpatch.attribs.ExceptionsPatch

/*
*   Copyright 2012, Thomas Kerber
*
*   Licensed 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 milk.jpatch.attribs;

import java.util.ArrayList;
import java.util.List;

import milk.jpatch.CPoolMap;
import milk.jpatch.Util;

import org.apache.bcel.Constants;
import org.apache.bcel.classfile.Attribute;
import org.apache.bcel.classfile.ConstantPool;
import org.apache.bcel.classfile.ExceptionTable;

/**
* Patches an "Exceptions" attribute.
*
* Merges with previous.
* @author Thomas Kerber
* @version 1.0.1
*/
public class ExceptionsPatch extends AttributePatch{
   
    private static final long serialVersionUID = -3064317345029686641L;
   
    /**
     * The indexes - in the diffs constant pool - of added exceptions.
     */
    private final int[] addedIndexes;
    /**
     * The names of removed exceptions.
     */
    private final String[] removedNames;
   
    /**
     * Creates the patch.
     * @param addedIndexes The added exceptions indexes.
     * @param removedIndexes The removed exceptions names.
     */
    public ExceptionsPatch(int[] addedIndexes, String[] removedNames){
        this.addedIndexes = addedIndexes;
        this.removedNames = removedNames;
    }
   
    /**
     * Generates.
     * @param old The old attributes.
     * @param new_ The new attributes.
     * @param patches The already generated patches.
     */
    public static void generate(Attribute[] old, Attribute[] new_,
            List<AttributePatch> patches){
       
        ExceptionTable newExceptions = null;
        ExceptionTable oldExceptions = null;
        for(Attribute a : old){
            if(a instanceof ExceptionTable){
                oldExceptions = (ExceptionTable)a;
                break;
            }
        }
        for(Attribute a : new_){
            if(a instanceof ExceptionTable){
                newExceptions = (ExceptionTable)a;
                break;
            }
        }
       
        int[] newIndexes = new int[0];
        String[] newStrings = new String[0];
        if(newExceptions != null){
            newIndexes = newExceptions.getExceptionIndexTable();
            newStrings = newExceptions.getExceptionNames();
        }
        int[] oldIndexes = new int[0];
        String[] oldStrings = new String[0];
        if(oldExceptions != null){
            oldIndexes = oldExceptions.getExceptionIndexTable();
            oldStrings = oldExceptions.getExceptionNames();
        }
       
        List<Integer> removedIndexes = new ArrayList<Integer>();
        List<Integer> addedIndexes = new ArrayList<Integer>();
        // Find added
        outer: for(int i = 0; i < newStrings.length; i++){
            for(int f = 0; f < oldStrings.length; f++){
                if(newStrings[i].equals(oldStrings[f]))
                    continue outer;
            }
            addedIndexes.add(newIndexes[i]);
        }
        // Find removed
        outer: for(int i = 0; i < oldStrings.length; i++){
            for(int f = 0; f < newStrings.length; f++){
                if(newStrings[f].equals(oldStrings[i]))
                    continue outer;
            }
            removedIndexes.add(oldIndexes[i]);
        }
        if(addedIndexes.size() == 0 && removedIndexes.size() == 0)
            return;
        int[] addedInt = new int[addedIndexes.size()];
        String[] removedStr = new String[removedIndexes.size()];
        for(int i = 0; i < addedInt.length; i++)
            addedInt[i] = addedIndexes.get(i);
       
        ConstantPool c = null;
        for(int i = 0; i < removedStr.length; i++){
            if(c == null)
                // Guaranteed to be set as some where apparently "removed"
                // if this point is reached.
                c = old[0].getConstantPool();
            removedStr[i] = c.getConstantString(removedIndexes.get(i),
                    Constants.CONSTANT_Class);
        }
        patches.add(new ExceptionsPatch(addedInt, removedStr));
    }
   
    /**
     *
     * @return The indexes of added exceptions (in the diff constant pool).
     */
    public int[] getAddedIndexes(){
        return addedIndexes;
    }
   
    /**
     *
     * @return The names of exceptions removed by this patch.
     */
    public String[] getRemovedNames(){
        return removedNames;
    }
   
    @Override
    public List<Attribute> patch(List<Attribute> attribs, CPoolMap map){
        int[] newIndexes = new int[addedIndexes.length];
        for(int i = 0; i < addedIndexes.length; i++)
            newIndexes[i] = map.get(addedIndexes[i]);
        int[] remIndexes = new int[removedNames.length];
        for(int i = 0; i < removedNames.length; i++)
            remIndexes[i] = Util.findConstantClassIn(map, removedNames[i],
                    true);
       
       
        int index = findName(attribs, "Exceptions");
        int[] oldIndexes;
        if(index == -1) // None previously
            oldIndexes = new int[0];
        else
            oldIndexes = ((ExceptionTable)attribs.get(index)).
                    getExceptionIndexTable();
       
        List<Integer> indexes = new ArrayList<Integer>();
        // Add old indexes not removed
        outer: for(int i : oldIndexes){
            for(int f : remIndexes){
                if(i == f)
                    continue outer;
            }
            indexes.add(i);
        }
        // Add new indexes
        for(int i : newIndexes)
            //TODO: here and other: prevent duplicate additions.
            indexes.add(i);
       
        if(indexes.size() == 0)
            return attribs;
       
        int[] intIndexes = new int[indexes.size()];
        for(int i = 0; i < intIndexes.length; i++)
            intIndexes[i] = indexes.get(i);
       
        ExceptionTable e = new ExceptionTable(
                Util.findConstantStringIn(map, "Exceptions"),
                2 + 2 * indexes.size(),
                intIndexes,
                map.to);
       
        return replaceTypeWith(attribs, "Exceptions", e);
    }
   
}
TOP

Related Classes of milk.jpatch.attribs.ExceptionsPatch

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.