Package org.apache.harmony.pack200

Source Code of org.apache.harmony.pack200.SegmentConstantPool

/*
*  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 org.apache.harmony.pack200;

import java.util.ArrayList;

import org.apache.harmony.pack200.bytecode.CPClass;
import org.apache.harmony.pack200.bytecode.CPDouble;
import org.apache.harmony.pack200.bytecode.CPFieldRef;
import org.apache.harmony.pack200.bytecode.CPFloat;
import org.apache.harmony.pack200.bytecode.CPInteger;
import org.apache.harmony.pack200.bytecode.CPInterfaceMethodRef;
import org.apache.harmony.pack200.bytecode.CPLong;
import org.apache.harmony.pack200.bytecode.CPMethodRef;
import org.apache.harmony.pack200.bytecode.CPString;
import org.apache.harmony.pack200.bytecode.CPUTF8;
import org.apache.harmony.pack200.bytecode.ConstantPoolEntry;

public class SegmentConstantPool {
    /**
     *
     */
    private CpBands bands;

    /**
     * @param bands
     */
    public SegmentConstantPool(CpBands bands) {
        this.bands = bands;
    }

    // define in archive order

    public static final int ALL = 0;
    public static final int UTF_8 = 1;
    public static final int CP_INT = 2;
    public static final int CP_FLOAT = 3;
    public static final int CP_LONG = 4;
    public static final int CP_DOUBLE = 5;
    public static final int CP_STRING = 6;
    public static final int CP_CLASS = 7;
    public static final int SIGNATURE = 8; // TODO and more to come --
    public static final int CP_DESCR = 9;
    public static final int CP_FIELD = 10;
    public static final int CP_METHOD = 11;
    public static final int CP_IMETHOD = 12;

    public Object getValue(int cp, long value) throws Pack200Exception {
        int index = (int) value;
        if (index == -1) {
            return null;
        } else if (index < 0) {
            throw new Pack200Exception("Cannot have a negative range");
        } else if (cp == UTF_8) {
            return bands.getCpUTF8()[index];
        } else if (cp == CP_INT) {
            return new Integer(bands.getCpInt()[index]);
        } else if (cp == CP_FLOAT) {
            return new Float(bands.getCpFloat()[index]);
        } else if (cp == CP_LONG) {
            return new Long(bands.getCpLong()[index]);
        } else if (cp == CP_DOUBLE) {
            return new Double(bands.getCpDouble()[index]);
        } else if (cp == CP_STRING) {
            return bands.getCpString()[index];
        } else if (cp == CP_CLASS) {
            return bands.getCpClass()[index];
        } else if (cp == SIGNATURE) {
            return bands.getCpSignature()[index];
        } else if (cp == CP_DESCR) {
            return bands.getCpDescriptor()[index];
        } else {
            // etc
            throw new Error("Get value incomplete");
        }
    }
   
    /**
     * Subset the constant pool of the specified type
     * to be just that which has the specified class
     * name. Answer the ConstantPoolEntry at the
     * desiredIndex of the subsetted pool.
     *
     * @param cp type of constant pool array to search
     * @param desiredIndex index of the constant pool
     * @param desiredClassName class to use to generate a
     *     subset of the pool
     * @return ConstantPoolEntry
     * @throws Pack200Exception
     */
    public ConstantPoolEntry getClassSpecificPoolEntry(int cp, long desiredIndex, String desiredClassName) throws Pack200Exception {
      int index = (int)desiredIndex;
      int realIndex = -1;
      String array[] = null;
      if (cp == CP_FIELD) {
        array = bands.getCpFieldClass();
      } else if (cp == CP_METHOD) {
        array = bands.getCpMethodClass();
      } else if (cp == CP_IMETHOD) {
        array = bands.getCpIMethodClass();
      } else {
        throw new Error("Don't know how to handle " + cp);
      }
      realIndex = matchSpecificPoolEntryIndex(array, desiredClassName, index);
      return getConstantPoolEntry(cp, (long)realIndex);
    }
   
    /**
     * Given the name of a class, answer the CPClass associated
     * with that class. Answer null if the class doesn't exist.
     * @param name Class name to look for (form: java/lang/Object)
     * @return CPClass for that class name, or null if not found.
     */
    public ConstantPoolEntry getClassPoolEntry(String name) {
      String classes[] = bands.getCpClass();
      int index = matchSpecificPoolEntryIndex(classes, name, 0);
      if(index == -1) {
        return null;
      }
      try {
        return getConstantPoolEntry(CP_CLASS, (long)index);
      }
      catch (Pack200Exception ex) {
        throw new Error("Error getting class pool entry");
      }
    }
   
    /**
     * Answer the init method for the specified class.
     * @param cp constant pool to search (must be CP_METHOD)
     * @param value index of init method
     * @param desiredClassName String class name of the init method
     * @return CPMethod init method
     * @throws Pack200Exception
     */
    public ConstantPoolEntry getInitMethodPoolEntry(int cp, long value, String desiredClassName) throws Pack200Exception {
      int realIndex = -1;
      String desiredRegex = "^<init>.*";
      if (cp == CP_METHOD) {
        realIndex = matchSpecificPoolEntryIndex(bands.getCpMethodClass(), bands.getCpMethodDescriptor(), desiredClassName, desiredRegex, (int)value);
      } else {
        throw new Error("Nothing but CP_METHOD can be an <init>");
      }
      return getConstantPoolEntry(cp, (long)realIndex);
    }

    /**
     * A number of things make use of subsets of structures.
     * In one particular example, _super bytecodes will use a subset
     * of method or field classes which have just those methods /
     * fields defined in the superclass. Similarly, _this bytecodes
     * use just those methods/fields defined in this class, and _init
     * bytecodes use just those methods that start with <init>.
     *
     * This method takes an array of names, a String to match for,
     * an index and a boolean as parameters, and answers the array
     * position in the array of the indexth element which matches
     * (or equals) the String (depending on the state of the boolean)
     *
     * In other words, if the class array consists of:
     *  Object [position 0, 0th instance of Object]
     *  String [position 1, 0th instance of String]
     *  String [position 2, 1st instance of String]
     *  Object [position 3, 1st instance of Object]
     *  Object [position 4, 2nd instance of Object]
     * then classSpecificPoolEntryIndex(..., "Object", 2, false) will
     * answer 4. classSpecificPoolEntryIndex(..., "String", 0, false)
     * will answer 1.
     *
     * @param nameArray Array of Strings against which the compareString is tested
     * @param compareString String for which to search
     * @param desiredIndex nth element with that match (counting from 0)
     * @return int index into nameArray, or -1 if not found.
     */
    protected int matchSpecificPoolEntryIndex(String[] nameArray, String compareString, int desiredIndex) {
      return matchSpecificPoolEntryIndex(nameArray, nameArray, compareString, ".*", desiredIndex);
    }

    /**
     * This method's function is to look through pairs of arrays.
     * It keeps track of the number of hits it finds using the
     * following basis of comparison for a hit:
     *  - the primaryArray[index] must be .equals() to the primaryCompareString
     *  - the secondaryArray[index] .matches() the secondaryCompareString
     * When the desiredIndex number of hits has been reached, the index
     * into the original two arrays of the element hit is returned.
     *
     * @param primaryArray The first array to search
     * @param secondaryArray The second array (must be same .length as primaryArray)
     * @param primaryCompareString The String to compare against primaryArray using .equals()
     * @param secondaryCompareRegex The String to compare against secondaryArray using .matches()
     * @param desiredIndex The nth hit whose position we're seeking
     * @return int index that represents the position of the nth hit in primaryArray and secondaryArray
     */
    protected int matchSpecificPoolEntryIndex(String[] primaryArray, String[] secondaryArray, String primaryCompareString, String secondaryCompareRegex, int desiredIndex) {
      int instanceCount = -1;
      for(int index=0; index < primaryArray.length; index++) {
        if((primaryArray[index].equals(primaryCompareString)) &&
            secondaryArray[index].matches(secondaryCompareRegex)) {
          instanceCount++;
          if(instanceCount == desiredIndex) {
            return index;
          }
        }
      }
      // We didn't return in the for loop, so the desiredMatch
      // with desiredIndex must not exist in the array.
      return -1;
    }
   
   
    public ConstantPoolEntry getConstantPoolEntry(int cp, long value) throws Pack200Exception {
        int index = (int) value;
        if (index == -1) {
            return null;
        } else if (index < 0) {
            throw new Pack200Exception("Cannot have a negative range");
        } else if (cp == UTF_8) {
            return new CPUTF8(bands.getCpUTF8()[index]);
        } else if (cp == CP_INT) {
            return new CPInteger(new Integer(bands.getCpInt()[index]));
        } else if (cp == CP_FLOAT) {
            return new CPFloat(new Float(bands.getCpFloat()[index]));
        } else if (cp == CP_LONG) {
            return new CPLong(new Long(bands.getCpLong()[index]));
        } else if (cp == CP_DOUBLE) {
            return new CPDouble(new Double(bands.getCpDouble()[index]));
        } else if (cp == CP_STRING) {
            return new CPString(bands.getCpString()[index]);
        } else if (cp == CP_CLASS) {
            return new CPClass(bands.getCpClass()[index]);
        } else if (cp == SIGNATURE) {
          throw new Error("I don't know what to do with signatures yet");
//            return null /* new CPSignature(bands.getCpSignature()[index]) */;
        } else if (cp == CP_DESCR) {
          throw new Error("I don't know what to do with descriptors yet");
//            return null /* new CPDescriptor(bands.getCpDescriptor()[index]) */;
        } else if (cp == CP_FIELD) {
            return new CPFieldRef(bands.getCpFieldClass()[index], bands.getCpFieldDescriptor()[index]);
        } else if (cp == CP_METHOD) {
            return new CPMethodRef(bands.getCpMethodClass()[index], bands.getCpMethodDescriptor()[index]);
        } else if (cp == CP_IMETHOD) {
            return new CPInterfaceMethodRef(bands.getCpIMethodClass()[index], bands.getCpIMethodDescriptor()[index]);
        } else {
            // etc
            throw new Error("Get value incomplete");
        }
    }
   
    public ConstantPoolEntry[] getCpAll() throws Pack200Exception {
          ArrayList cpAll = new ArrayList();
          // TODO: this is 1.5-specific. Try to get rid
          // of it.
          for(int index=0; index < bands.getCpUTF8().length; index++) {
            cpAll.add(getConstantPoolEntry(UTF_8, index));
          }
          for(int index=0; index < bands.getCpInt().length; index++) {
            cpAll.add(getConstantPoolEntry(CP_INT, index));
          }
          for(int index=0; index < bands.getCpFloat().length; index++) {
            cpAll.add(getConstantPoolEntry(CP_FLOAT, index));
          }
          for(int index=0; index < bands.getCpLong().length; index++) {
            cpAll.add(getConstantPoolEntry(CP_LONG, index));
          }
          for(int index=0; index < bands.getCpDouble().length; index++) {
            cpAll.add(getConstantPoolEntry(CP_DOUBLE, index));
          }
          for(int index=0; index < bands.getCpString().length; index++) {
            cpAll.add(getConstantPoolEntry(CP_STRING, index));
          }
          for(int index=0; index < bands.getCpClass().length; index++) {
            cpAll.add(getConstantPoolEntry(CP_CLASS, index));
          }
          for(int index=0; index < bands.getCpFieldClass().length; index++) {
            cpAll.add(getConstantPoolEntry(CP_FIELD, index));
          }
          for(int index=0; index < bands.getCpMethodClass().length; index++) {
            cpAll.add(getConstantPoolEntry(CP_METHOD, index));
          }
          for(int index=0; index < bands.getCpIMethodClass().length; index++) {
            cpAll.add(getConstantPoolEntry(CP_IMETHOD, index));
          }
         
          ConstantPoolEntry[] result = new ConstantPoolEntry[cpAll.size()];
          cpAll.toArray(result);
          return result;
        }

 
    }
TOP

Related Classes of org.apache.harmony.pack200.SegmentConstantPool

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.