001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.harmony.pack200;
018:
019: import java.io.IOException;
020: import java.io.InputStream;
021: import java.util.ArrayList;
022: import java.util.Iterator;
023: import java.util.List;
024:
025: import org.apache.harmony.pack200.bytecode.CPClass;
026: import org.apache.harmony.pack200.bytecode.ClassConstantPool;
027:
028: /**
029: * Pack200 Inner Class Bands
030: */
031: public class IcBands extends BandSet {
032: private IcTuple[] icAll;
033:
034: private String[] cpUTF8;
035:
036: private String[] cpClass;
037:
038: /**
039: * @param header
040: */
041: public IcBands(Segment segment) {
042: super (segment);
043: this .cpClass = segment.getCpBands().getCpClass();
044: this .cpUTF8 = segment.getCpBands().getCpUTF8();
045: }
046:
047: /* (non-Javadoc)
048: * @see org.apache.harmony.pack200.BandSet#unpack(java.io.InputStream)
049: */
050: public void unpack(InputStream in) throws IOException,
051: Pack200Exception {
052: // Read IC bands
053: int innerClassCount = header.getInnerClassCount();
054: String[] icThisClass = parseReferences("ic_this_class", in,
055: Codec.UDELTA5, innerClassCount, cpClass);
056: int[] icFlags = decodeBandInt("ic_flags", in, Codec.UNSIGNED5,
057: innerClassCount);
058: int outerClasses = SegmentUtils.countBit16(icFlags);
059: String[] icOuterClass = parseReferences("ic_outer_class", in,
060: Codec.DELTA5, outerClasses, cpClass);
061: String[] icName = parseReferences("ic_name", in, Codec.DELTA5,
062: outerClasses, cpUTF8);
063:
064: // Construct IC tuples
065: icAll = new IcTuple[icThisClass.length];
066: int index = 0;
067: for (int i = 0; i < icThisClass.length; i++) {
068: icAll[i] = new IcTuple();
069: icAll[i].C = icThisClass[i];
070: icAll[i].F = icFlags[i];
071: if ((icFlags[i] & 1 << 16) != 0) {
072: icAll[i].C2 = icOuterClass[index];
073: icAll[i].N = icName[index];
074: index++;
075: }
076: }
077: }
078:
079: public IcTuple[] getIcTuples() {
080: return icAll;
081: }
082:
083: /**
084: * Answer the relevant IcTuples for the specified className
085: * and class constant pool.
086: * @param className String name of the class X for ic_relevant(X)
087: * @param cp ClassConstantPool used to generate ic_relevant(X)
088: * @return array of IcTuple
089: */
090: public IcTuple[] getRelevantIcTuples(String className,
091: ClassConstantPool cp) {
092: List relevantTuples = new ArrayList();
093: IcTuple[] allTuples = getIcTuples();
094: int allTuplesSize = allTuples.length;
095: for (int index = 0; index < allTuplesSize; index++) {
096: if (allTuples[index].outerClassString().equals(className)) {
097: relevantTuples.add(allTuples[index]);
098: }
099: }
100:
101: List classPoolClasses = cp.allClasses();
102: boolean changed = true;
103: // For every class in both ic_this_class and cp,
104: // add it to ic_relevant. Repeat until no more
105: // changes to ic_relevant.
106: while (changed) {
107: changed = false;
108: for (int allTupleIndex = 0; allTupleIndex < allTuplesSize; allTupleIndex++) {
109: Iterator it = classPoolClasses.iterator();
110: while (it.hasNext()) {
111: CPClass classInPool = (CPClass) it.next();
112: String poolClassName = classInPool.name;
113: if (poolClassName.equals(allTuples[allTupleIndex]
114: .this ClassString())) {
115: // If the tuple isn't already in there, then add it
116: if (relevantTuples
117: .indexOf(allTuples[allTupleIndex]) == -1) {
118: relevantTuples
119: .add(allTuples[allTupleIndex]);
120: changed = true;
121: }
122: }
123: }
124: }
125: }
126:
127: // Now order the result as a subsequence of ic_all
128: IcTuple[] orderedRelevantTuples = new IcTuple[relevantTuples
129: .size()];
130: int orderedRelevantIndex = 0;
131: for (int index = 0; index < allTuplesSize; index++) {
132: if (relevantTuples.contains(allTuples[index])) {
133: orderedRelevantTuples[orderedRelevantIndex] = allTuples[index];
134: orderedRelevantIndex++;
135: }
136: }
137: if (orderedRelevantIndex != orderedRelevantTuples.length) {
138: // This should never happen. If it does, we have a
139: // logic error in the ordering code.
140: throw new Error("Missing a tuple when ordering them");
141: }
142: return orderedRelevantTuples;
143: }
144:
145: }
|