Return-Path: Delivered-To: apmail-harmony-commits-archive@www.apache.org Received: (qmail 35053 invoked from network); 29 Jan 2008 14:36:44 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 29 Jan 2008 14:36:44 -0000 Received: (qmail 51482 invoked by uid 500); 29 Jan 2008 14:36:35 -0000 Delivered-To: apmail-harmony-commits-archive@harmony.apache.org Received: (qmail 51385 invoked by uid 500); 29 Jan 2008 14:36:35 -0000 Mailing-List: contact commits-help@harmony.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@harmony.apache.org Delivered-To: mailing list commits@harmony.apache.org Received: (qmail 51376 invoked by uid 99); 29 Jan 2008 14:36:35 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 29 Jan 2008 06:36:35 -0800 X-ASF-Spam-Status: No, hits=-100.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 29 Jan 2008 14:36:26 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id B0F821A9832; Tue, 29 Jan 2008 06:36:16 -0800 (PST) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r616345 - in /harmony/enhanced/classlib/trunk/modules/pack200/src: main/java/org/apache/harmony/pack200/ main/java/org/apache/harmony/pack200/bytecode/ main/java/org/apache/harmony/pack200/bytecode/forms/ test/java/org/apache/harmony/pack20... Date: Tue, 29 Jan 2008 14:36:03 -0000 To: commits@harmony.apache.org From: sjanuary@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20080129143616.B0F821A9832@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: sjanuary Date: Tue Jan 29 06:35:57 2008 New Revision: 616345 URL: http://svn.apache.org/viewvc?rev=616345&view=rev Log: Applying patch from HARMONY-5438 - [pack200][classlib] Added some inner class support Added: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/IcTuple.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/InnerClassesAttribute.java harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/ICTupleTest.java Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/IcBands.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Segment.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/SegmentConstantPool.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/SegmentUtils.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPClass.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPFieldRef.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPUTF8.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/ClassConstantPool.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/ClassPoolSet.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/ByteCodeForm.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/NewInitMethodRefForm.java harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/SegmentTest.java Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.java?rev=616345&r1=616344&r2=616345&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.java Tue Jan 29 06:35:57 2008 @@ -22,7 +22,6 @@ import java.util.Iterator; import java.util.List; -import org.apache.harmony.pack200.IcBands.ICTuple; import org.apache.harmony.pack200.bytecode.Attribute; import org.apache.harmony.pack200.bytecode.CPClass; import org.apache.harmony.pack200.bytecode.CPNameAndType; @@ -60,7 +59,7 @@ private int[] classVersionMinor; - private IcBands.ICTuple[][] icLocal; + private IcTuple[][] icLocal; private ArrayList[] codeAttributes; @@ -532,7 +531,7 @@ int innerClassIndex = 0; int innerClassC2NIndex = 0; int versionIndex = 0; - icLocal = new IcBands.ICTuple[classCount][]; + icLocal = new IcTuple[classCount][]; for (int i = 0; i < classCount; i++) { long flag = classFlags[i]; @@ -581,9 +580,9 @@ if (innerClassLayout.matches(flag)) { // Just create the tuples for now because the attributes are // decided at the end when creating class constant pools - icLocal[i] = new IcBands.ICTuple[classInnerClassesN[innerClassIndex]]; + icLocal[i] = new IcTuple[classInnerClassesN[innerClassIndex]]; for (int j = 0; j < icLocal[i].length; j++) { - IcBands.ICTuple icTuple = new IcBands.ICTuple(); + IcTuple icTuple = new IcTuple(); icTuple.C = cpClass[classInnerClassesRC[innerClassIndex][j]]; icTuple.F = classInnerClassesF[innerClassIndex][j]; if (icTuple.F != 0) { @@ -593,7 +592,7 @@ } else { // Get from icBands IcBands icBands = segment.getIcBands(); - ICTuple[] icAll = icBands.getIcTuples(); + IcTuple[] icAll = icBands.getIcTuples(); for (int k = 0; k < icAll.length; k++) { if (icAll[k].C.equals(icTuple.C)) { icTuple.C2 = icAll[k].C2; Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/IcBands.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/IcBands.java?rev=616345&r1=616344&r2=616345&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/IcBands.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/IcBands.java Tue Jan 29 06:35:57 2008 @@ -18,22 +18,20 @@ import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.harmony.pack200.bytecode.CPClass; +import org.apache.harmony.pack200.bytecode.ClassConstantPool; /** * Pack200 Inner Class Bands */ public class IcBands extends BandSet { - public static class ICTuple { - - public String C; // this class - public int F; // flags - public String C2; // outer class - public String N; // name - - } - private ICTuple[] icAll; + private IcTuple[] icAll; private String[] cpUTF8; @@ -65,10 +63,10 @@ cpUTF8); // Construct IC tuples - icAll = new ICTuple[icThisClass.length]; + icAll = new IcTuple[icThisClass.length]; int index = 0; for (int i = 0; i < icThisClass.length; i++) { - icAll[i] = new ICTuple(); + icAll[i] = new IcTuple(); icAll[i].C = icThisClass[i]; icAll[i].F = icFlags[i]; if((icFlags[i] & 1<<16) != 0) { @@ -79,9 +77,72 @@ } } - public ICTuple[] getIcTuples() { + public IcTuple[] getIcTuples() { return icAll; } + /** + * Answer the relevant IcTuples for the specified className + * and class constant pool. + * @param className String name of the class X for ic_relevant(X) + * @param cp ClassConstantPool used to generate ic_relevant(X) + * @return array of IcTuple + */ + public IcTuple[] getRelevantIcTuples(String className, ClassConstantPool cp) { + List relevantTuples = new ArrayList(); + IcTuple[] allTuples = getIcTuples(); + int allTuplesSize = allTuples.length; + SegmentUtils.debug("-------\nRelevant() " + className); + for(int index=0; index < allTuplesSize; index++) { + if(allTuples[index].outerClassString().equals(className)) { + relevantTuples.add(allTuples[index]); + } + } + + SegmentUtils.debug("self halt"); + List classPoolClasses = cp.allClasses(); + boolean changed = true; + // For every class in both ic_this_class and cp, + // add it to ic_relevant. Repeat until no more + // changes to ic_relevant. + while(changed) { + changed = false; + for(int allTupleIndex=0; allTupleIndex < allTuplesSize; allTupleIndex++) { + Iterator it = classPoolClasses.iterator(); + SegmentUtils.debug("\n\n----\nLooking through class pool for: " + allTuples[allTupleIndex].thisClassString()); + while(it.hasNext()) { + CPClass classInPool = (CPClass)it.next(); + String poolClassName = classInPool.name; + SegmentUtils.debug(" " + poolClassName); + if(poolClassName.equals(allTuples[allTupleIndex].thisClassString())) { + // If the tuple isn't already in there, then add it + SegmentUtils.debug(" -> match"); + if(relevantTuples.indexOf(allTuples[allTupleIndex]) == -1) { + SegmentUtils.debug(" -> added"); + relevantTuples.add(allTuples[allTupleIndex]); + changed = true; + } + } + // TODO: is this right? + if(poolClassName.equals(allTuples[allTupleIndex].outerClassString())) { + // If the tuple isn't already in there, then add it + SegmentUtils.debug(" -> omatch"); + if(relevantTuples.indexOf(allTuples[allTupleIndex]) == -1) { + SegmentUtils.debug(" -> oadded"); + relevantTuples.add(allTuples[allTupleIndex]); + changed = true; + } + } + } + } + } + + IcTuple[] result = new IcTuple[relevantTuples.size()]; + for(int index=0; index < result.length; index++) { + result[index] = (IcTuple)relevantTuples.get(index); + SegmentUtils.debug("Returning relevantTuple: " + result[index].thisClassString()); + } + return result; + } } Added: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/IcTuple.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/IcTuple.java?rev=616345&view=auto ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/IcTuple.java (added) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/IcTuple.java Tue Jan 29 06:35:57 2008 @@ -0,0 +1,195 @@ +/* + * 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; + +public class IcTuple { + + public static int NESTED_CLASS_FLAG = 0x00010000; + public String C; // this class + public int F; // flags + public String C2; // outer class + public String N; // name + + private String cachedOuterClassString = null; + private String cachedSimpleClassName = null; + private boolean initialized = false; + private boolean anonymous = false; + private boolean member = true; + + /** + * Answer true if the receiver is predicted; + * answer false if the receiver is specified + * explicitly in the outer and name fields. + * @return + */ + public boolean predicted() { + return ((F & NESTED_CLASS_FLAG) == 0); + } + + /** + * Break the receiver into components at $ boundaries. + * + * @return + */ + public String[] innerBreakAtDollar(String className) { + ArrayList resultList = new ArrayList(); + int start = 0; + int index = 0; + while(index < className.length()) { + if(className.charAt(index) <= '$') { + resultList.add(className.substring(start, index)); + start = index + 1; + } + index++; + if(index >= className.length()) { + // Add the last element + resultList.add(className.substring(start, className.length())); + } + } + String[] result = new String[resultList.size()]; + for(int i=0; i < resultList.size(); i++) { + result[i] = (String)resultList.get(i); + } + return result; + } + + /** + * Answer the outer class name for the receiver. + * This may either be specified or inferred from + * inner class name. + * @return String name of outer class + */ + public String outerClassString() { + if(!initialized) { + initializeClassStrings(); + } + return cachedOuterClassString; + } + + /** + * Answer the inner class name for the receiver. + * @return String name of inner class + */ + public String simpleClassName() { + if(!initialized) { + initializeClassStrings(); + } + return cachedSimpleClassName; + } + + /** + * Answer the full name of the inner class represented + * by this tuple (including its outer component) + * @return String full name of inner class + */ + public String thisClassString() { + if(predicted()) { + return C; + } else { + // TODO: this may not be right. + return C2 + "$" + N; + } + } + + public boolean isMember() { + initializeClassStrings(); + return member; + } + + public boolean isAnonymous() { + initializeClassStrings(); + return anonymous; + } + + private void initializeClassStrings() { + if(initialized) { + return; + } + initialized = true; + if(!predicted()) { + cachedOuterClassString = C2; + cachedSimpleClassName = N; + return; + } + // Class names must be calculated from + // this class name. + String nameComponents[] = innerBreakAtDollar(C); + if(nameComponents.length == 0) { + throw new Error("Unable to predict outer class name: " + C); + } + if(nameComponents.length == 1) { + throw new Error("Unable to predict inner class name: " + C); + } + // If we get to this point, nameComponents.length must be >=2 + int lastPosition = nameComponents.length - 1; + cachedSimpleClassName = nameComponents[lastPosition]; + cachedOuterClassString = new String(); + for(int index=0; index < lastPosition; index++) { + cachedOuterClassString += nameComponents[index]; + if(isAllDigits(nameComponents[index])) { + member = false; + } + if(index + 1 != lastPosition) { + cachedOuterClassString += '$'; + } + } + // Now special-case: if the last part of the outer + // class name is all digits, then the cachedOuterClassString + // is null (an anonymous outer class). If the cachedInnerClassString + // is all digits, then the cachedInnerClassString is null (an + // anonymous inner class). + // TODO: Don't know about this - we might need to + // do this later on (after we've determined what's + // anonymous and what isn't) so we point to the right + // class file entries. +// if(isAllDigits(nameComponents[lastPosition - 1])) { +// cachedOuterClassString = null; +// anonymous = false; +// } + if(isAllDigits(cachedSimpleClassName)) { + anonymous = true; + member = false; +// cachedSimpleClassName = C; + } + } + + private boolean isAllDigits(String nameString) { + // Answer true if the receiver is all digits; otherwise answer false. + if(null == nameString) { + return false; + } + for(int index = 0; index < nameString.length(); index++) { + if(!Character.isDigit(nameString.charAt(index))) { + return false; + } + } + return true; + } + + public String toString() { + StringBuffer result = new StringBuffer(); + result.append(this.getClass().getName()); + result.append('('); + result.append(simpleClassName()); + result.append(" in "); + result.append(outerClassString()); + result.append(')'); + return result.toString(); + } +} Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Segment.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Segment.java?rev=616345&r1=616344&r2=616345&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Segment.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Segment.java Tue Jan 29 06:35:57 2008 @@ -28,9 +28,11 @@ import org.apache.harmony.pack200.bytecode.CPClass; import org.apache.harmony.pack200.bytecode.CPField; import org.apache.harmony.pack200.bytecode.CPMethod; +import org.apache.harmony.pack200.bytecode.CPUTF8; import org.apache.harmony.pack200.bytecode.ClassConstantPool; import org.apache.harmony.pack200.bytecode.ClassFile; import org.apache.harmony.pack200.bytecode.ClassFileEntry; +import org.apache.harmony.pack200.bytecode.InnerClassesAttribute; import org.apache.harmony.pack200.bytecode.SourceFileAttribute; /** @@ -162,6 +164,51 @@ for (i = 0; i < cfMethods.length; i++) { cfMethods[i] = cp.add(new CPMethod(classBands.getMethodDescr()[classNum][i], classBands.getMethodFlags()[classNum][i], classBands.getMethodAttributes()[classNum][i])); + } + // TODO: maybe this is a better place to add ic_relevant? + // This seems like the right thing to do. + boolean addedClasses = false; + InnerClassesAttribute innerClassesAttribute = new InnerClassesAttribute("InnerClasses"); + IcTuple[] ic_relevant = getIcBands().getRelevantIcTuples(fullName, cp); + + for(int index = 0; index < ic_relevant.length; index++) { + String innerClassString = ic_relevant[index].thisClassString(); + String outerClassString = ic_relevant[index].outerClassString(); + String simpleClassName = ic_relevant[index].simpleClassName(); + + CPClass innerClass = null; + CPUTF8 innerName = null; + CPClass outerClass = null; + + if(ic_relevant[index].isAnonymous()) { + innerClass = new CPClass(innerClassString); + } else { + innerClass = new CPClass(innerClassString); + innerName = new CPUTF8(simpleClassName, ClassConstantPool.DOMAIN_ATTRIBUTEASCIIZ); + } + + // TODO: I think we need to worry about if the + // OUTER class is a member or not - not the + // ic_relevant itself. +// if(ic_relevant[index].isMember()) { + outerClass = new CPClass(outerClassString); +// } + + int flags = ic_relevant[index].F; + innerClassesAttribute.addInnerClassesEntry(innerClass, outerClass, innerName, flags); + addedClasses = true; + } + if(addedClasses) { + // Need to add the InnerClasses attribute to the + // existing classFile attributes. + Attribute[] originalAttrs = classFile.attributes; + Attribute[] newAttrs = new Attribute[originalAttrs.length + 1]; + for(int index=0; index < originalAttrs.length; index++) { + newAttrs[index] = originalAttrs[index]; + } + newAttrs[newAttrs.length - 1] = innerClassesAttribute; + classFile.attributes = newAttrs; + cp.add(innerClassesAttribute); } // sort CP according to cp_All cp.resolve(this); Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/SegmentConstantPool.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/SegmentConstantPool.java?rev=616345&r1=616344&r2=616345&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/SegmentConstantPool.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/SegmentConstantPool.java Tue Jan 29 06:35:57 2008 @@ -220,6 +220,9 @@ } // We didn't return in the for loop, so the desiredMatch // with desiredIndex must not exist in the array. + if(secondaryCompareRegex.equals("^.*")) { + SegmentUtils.debug("self halt"); + } return -1; } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/SegmentUtils.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/SegmentUtils.java?rev=616345&r1=616344&r2=616345&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/SegmentUtils.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/SegmentUtils.java Tue Jan 29 06:35:57 2008 @@ -21,27 +21,6 @@ public static int countArgs(String descriptor) { return countArgs(descriptor, 1); -// int bra = descriptor.indexOf("("); -// int ket = descriptor.indexOf(")"); -// if (bra == -1 || ket == -1 || ket < bra) -// throw new IllegalArgumentException("No arguments"); -// -// boolean inType = false; -// int count = 0; -// for (int i = bra + 1; i < ket; i++) { -// char charAt = descriptor.charAt(i); -// if (inType && charAt == ';') { -// inType = false; -// } else if (!inType && charAt == 'L') { -// inType = true; -// count++; -// } else if (charAt == '[' || inType) { -// // NOP -// } else { -// count++; -// } -// } -// return count; } public static int countInvokeInterfaceArgs(String descriptor) { @@ -141,6 +120,39 @@ return count; } + /** + * Given a String classX (the name of a class) and the + * collection of inner class tuples ic_all, answer + * ic_relevant(classX) + * @param classX String class name + * @param ic_all ICTuple[] all the inner class tuples + * @return ICTuple[] all the relevant tuples sorted as in + */ + public static IcTuple[] icRelevant(String classX, IcTuple[] ic_all) { + return null; + } + + public static boolean isRelevant(String outerClass, IcTuple tuple) { + if(tuple.C.equals(outerClass)) { + // If the outer class name is explicitly + // specified and it's the correct one, the + // tuple is relevant. + return true; + } + + if(tuple.C != null) { + // If the outer class name is explicitly specified + // (non-null) and it's not the correct one, the + // tuple is not relevant. + return false; + } + + // Now we know that tuple.C is null, so it might be + // relevant. Find out. + return false; + } + + private SegmentUtils() { // Intended to be a helper class } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPClass.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPClass.java?rev=616345&r1=616344&r2=616345&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPClass.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPClass.java Tue Jan 29 06:35:57 2008 @@ -19,6 +19,8 @@ import java.io.DataOutputStream; import java.io.IOException; +import org.apache.harmony.pack200.IcBands; + public class CPClass extends ConstantPoolEntry { private int index; @@ -87,6 +89,8 @@ } public String comparisonString() { + // TODO: what to do about inner classes? + if(name==null) {return "null:name (probably an inner class?)";}; return getName(); } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPFieldRef.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPFieldRef.java?rev=616345&r1=616344&r2=616345&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPFieldRef.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPFieldRef.java Tue Jan 29 06:35:57 2008 @@ -59,7 +59,9 @@ return "FieldRef: " + className + "#" + nameAndType; } - + public String comparisonString() { + return (className.getName() + Character.MAX_VALUE) + nameAndType.descriptor + Character.MAX_VALUE + nameAndType.name; + } public int hashCode() { final int PRIME = 31; Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPUTF8.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPUTF8.java?rev=616345&r1=616344&r2=616345&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPUTF8.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/CPUTF8.java Tue Jan 29 06:35:57 2008 @@ -84,10 +84,14 @@ } public String normalComparisonString() { + // TODO: what to do about inner classes? + if(utf8==null) {return "null:utf8 (probably an inner class?)";}; return utf8; } public String signatureComparisonString() { + // TODO: what to do about inner classes? + if(utf8==null) {return "null:utf8 (probably an inner class?)";}; StringBuffer alphaChars = new StringBuffer(); StringBuffer extraChars = new StringBuffer(); if(utf8.length() > 0){ Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/ClassConstantPool.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/ClassConstantPool.java?rev=616345&r1=616344&r2=616345&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/ClassConstantPool.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/ClassConstantPool.java Tue Jan 29 06:35:57 2008 @@ -17,7 +17,6 @@ package org.apache.harmony.pack200.bytecode; import java.util.ArrayList; -import java.util.Comparator; import java.util.Iterator; import java.util.List; @@ -27,40 +26,6 @@ public class ClassConstantPool { - class PoolComparator implements Comparator { - /* (non-Javadoc) - * Note: this comparator imposes orderings that are inconsistent with equals. - * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) - */ - public int compare(Object o1, Object o2) { - // If we compare anything other than ConstantPoolEntries - // with this comparator, it is an error. - ConstantPoolEntry cpe1 = (ConstantPoolEntry)o1; - ConstantPoolEntry cpe2 = (ConstantPoolEntry)o2; - - int domain1 = cpe1.getDomain(); - int domain2 = cpe2.getDomain(); - - if(domain1 < domain2) { - return -1; - } - if(domain1 > domain2) { - return 1; - } - - // Domains must be the same, need to compare - // based on name. - // TODO: what means name? - String compare1 = cpe1.comparisonString(); - String compare2 = cpe2.comparisonString(); - return compare1.compareTo(compare2); -// if(cpe1.creationOrder < cpe2.creationOrder) { -// return -1; -// } else { -// return 1; -// } - } - } // These are the domains in sorted order. public static int DOMAIN_UNDEFINED = 0; public static int DOMAIN_INTEGER = 1; @@ -93,10 +58,10 @@ // Only add in constant pools, but resolve all types since they may // introduce new constant pool entries // This is a handy way to see what's adding a ClassFileEntry - set a breakpoint on the print -// if(entry instanceof CPUTF8) { -// System.out.println("AAH:" + ((CPUTF8)entry).comparisonString()); +// if(entry instanceof CPFieldRef) { +// SegmentUtils.debug("AAH:" + ((CPFieldRef)entry).comparisonString()); // if (((CPUTF8)entry).underlyingString().matches("Code")) { -// System.out.println("Adding"); +// SegmentUtils.debug("Adding"); // } // } if (entry instanceof ConstantPoolEntry) { @@ -189,4 +154,22 @@ } } + /** + * Answer the collection of CPClasses currently held + * by the ClassPoolSet. This is used to calculate relevant + * classes when generating the set of relevant inner + * classes (ic_relevant()) + * @return ArrayList collection of all classes. + * + * NOTE: when this list is answered, the classes may not + * yet be resolved. + */ + public List allClasses() { + List classesList = new ArrayList(); + Iterator it = classPoolSet.partialIterator(DOMAIN_CLASSREF, DOMAIN_CLASSREF); + while(it.hasNext()) { + classesList.add(it.next()); + } + return classesList; + } } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/ClassPoolSet.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/ClassPoolSet.java?rev=616345&r1=616344&r2=616345&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/ClassPoolSet.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/ClassPoolSet.java Tue Jan 29 06:35:57 2008 @@ -25,6 +25,8 @@ /** * This class implements the special set (which is aware of * domains) used when generating ClassConstantPools. + * It's called a Set, but isn't quite a Collection - it + * doesn't implement all the API required. */ public class ClassPoolSet { Added: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/InnerClassesAttribute.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/InnerClassesAttribute.java?rev=616345&view=auto ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/InnerClassesAttribute.java (added) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/InnerClassesAttribute.java Tue Jan 29 06:35:57 2008 @@ -0,0 +1,184 @@ +/* + * 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.bytecode; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.harmony.pack200.IcTuple; +import org.apache.harmony.pack200.SegmentUtils; + + +public class InnerClassesAttribute extends Attribute { + + class InnerClassesEntry { + CPClass inner_class_info; + CPClass outer_class_info; + CPUTF8 inner_class_name; + + int inner_class_info_index = -1; + int outer_class_info_index = -1; + int inner_name_index = -1; + int inner_class_access_flags = -1; + + public InnerClassesEntry(IcTuple icTuple) { + this(icTuple.C, icTuple.C2, icTuple.N, icTuple.F); + } + + public InnerClassesEntry(String innerString, String outerString, String nameString, int flags) { + + } + public InnerClassesEntry(CPClass innerClass, CPClass outerClass, CPUTF8 innerName, int flags) { + this.inner_class_info = innerClass; + this.outer_class_info = outerClass; + this.inner_class_name = innerName; + this.inner_class_access_flags = flags; + } + + /** + * Determine the indices of the things in the receiver + * which point to elements of the ClassConstantPool + * @param pool ClassConstantPool which holds the + * CPClass and CPUTF8 objects. + */ + public void resolve(ClassConstantPool pool) { + SegmentUtils.debug("----"); + SegmentUtils.debug("inner_class_info: " + inner_class_info); + SegmentUtils.debug("inner_class_name: " + inner_class_name); + SegmentUtils.debug("outer_class_info: " + outer_class_info); + + if(inner_class_info != null) { + inner_class_info.resolve(pool); + inner_class_info_index = pool.indexOf(inner_class_info); + } else { + inner_class_info_index = 0; + } + + if(inner_class_name != null) { + inner_class_name.resolve(pool); + inner_name_index = pool.indexOf(inner_class_name); + } else { + inner_name_index = 0; + } + + if(outer_class_info != null) { + outer_class_info.resolve(pool); + outer_class_info_index = pool.indexOf(outer_class_info); + } else { + outer_class_info_index = 0; + } + } + + public void write(DataOutputStream dos) throws IOException { + dos.writeShort(inner_class_info_index); + dos.writeShort(outer_class_info_index); + dos.writeShort(inner_name_index); + dos.writeShort(inner_class_access_flags); + } + + } + + private List innerClasses = new ArrayList(); + private List nestedClassFileEntries = new ArrayList(); + + public InnerClassesAttribute(String name) { + super("InnerClasses"); //$NON-NLS-1$ + nestedClassFileEntries.add(getAttributeName()); + } + + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (this.getClass() != obj.getClass()) + return false; + final InnerClassesAttribute other = (InnerClassesAttribute) obj; + if (getAttributeName() == null) { + if (other.getAttributeName() != null) + return false; + } else if (!getAttributeName().equals(other.getAttributeName())) + return false; + return true; + } + + protected int getLength() { + return 2 + ((2 + 2 + 2 + 2) * innerClasses.size()); + } + + protected ClassFileEntry[] getNestedClassFileEntries() { + ClassFileEntry[] result = new ClassFileEntry[nestedClassFileEntries.size()]; + for(int index=0; index < result.length; index++) { + result[index] = (ClassFileEntry)nestedClassFileEntries.get(index); + } + return result; + } + + public int hashCode() { + final int PRIME = 31; + int result = super.hashCode(); + result = PRIME * result + ((getAttributeName() == null) ? 0 : getAttributeName().hashCode()); + return result; + } + + protected void resolve(ClassConstantPool pool) { + super.resolve(pool); + Iterator it = innerClasses.iterator(); + while(it.hasNext()) { + InnerClassesEntry entry = (InnerClassesEntry)it.next(); + entry.resolve(pool); + } + } + + public String toString() { + return "InnerClasses: " + getAttributeName(); + } + + protected void doWrite(DataOutputStream dos) throws IOException { + // Hack so I can see what's being written. + super.doWrite(dos); + } + + protected void writeBody(DataOutputStream dos) throws IOException { + dos.writeShort(innerClasses.size()); + Iterator it = innerClasses.iterator(); + while(it.hasNext()) { + InnerClassesEntry entry = (InnerClassesEntry)it.next(); + entry.write(dos); + } + } + + public void addInnerClassesEntry(CPClass innerClass, CPClass outerClass, CPUTF8 innerName, int flags) { + if(innerClass != null) { + nestedClassFileEntries.add(innerClass); + } + if(outerClass != null) { + nestedClassFileEntries.add(outerClass); + } + if(innerName != null) { + nestedClassFileEntries.add(innerName); + } + addInnerClassesEntry(new InnerClassesEntry(innerClass, outerClass, innerName, flags)); + } + + private void addInnerClassesEntry(InnerClassesEntry innerClassesEntry) { + innerClasses.add(innerClassesEntry); + } +} Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/ByteCodeForm.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/ByteCodeForm.java?rev=616345&r1=616344&r2=616345&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/ByteCodeForm.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/ByteCodeForm.java Tue Jan 29 06:35:57 2008 @@ -285,7 +285,7 @@ byteCodeArray[218] = new SuperFieldRefForm(218, "getfield_super", new int[] {180, -1, -1}); byteCodeArray[219] = new SuperFieldRefForm(219, "putfield_super", new int[] {181, -1, -1}); byteCodeArray[220] = new SuperMethodRefForm(220, "invokevirtual_super", new int[] {182, -1, -1}); - byteCodeArray[221] = new SuperFieldRefForm(221, "invokespecial_super", new int[] {183, -1, -1}); + byteCodeArray[221] = new SuperMethodRefForm(221, "invokespecial_super", new int[] {183, -1, -1}); byteCodeArray[222] = new SuperMethodRefForm(222, "invokestatic_super", new int[] {184, -1, -1}); byteCodeArray[223] = new SuperFieldRefForm(223, "aload_0_getstatic_super", new int[] {42, 178, -1, -1}); byteCodeArray[224] = new SuperFieldRefForm(224, "aload_0_putstatic_super", new int[] {42, 179, -1, -1}); Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/NewInitMethodRefForm.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/NewInitMethodRefForm.java?rev=616345&r1=616344&r2=616345&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/NewInitMethodRefForm.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/forms/NewInitMethodRefForm.java Tue Jan 29 06:35:57 2008 @@ -16,6 +16,10 @@ */ package org.apache.harmony.pack200.bytecode.forms; +import org.apache.harmony.pack200.Pack200Exception; +import org.apache.harmony.pack200.SegmentConstantPool; +import org.apache.harmony.pack200.bytecode.ByteCode; +import org.apache.harmony.pack200.bytecode.ClassFileEntry; import org.apache.harmony.pack200.bytecode.OperandManager; /** @@ -40,6 +44,26 @@ } protected String context(OperandManager operandManager) { - return operandManager.getNewClass(); + String result = operandManager.getNewClass(); + return result; + } + + protected void setNestedEntries(ByteCode byteCode, OperandManager operandManager, int offset) throws Pack200Exception { + SegmentConstantPool globalPool = operandManager.globalConstantPool(); + ClassFileEntry[] nested = null; + nested = new ClassFileEntry[] { + globalPool.getInitMethodPoolEntry(SegmentConstantPool.CP_METHOD, offset, context(operandManager)) + }; + if(nested[0] == null) { + // One class in JNDI isn't finding its + // method. Not sure why. + // TODO: find out why. + // org/apache/harmony/security/asn1/ASN1Type + byteCode.setNested(new ClassFileEntry[]{}); + byteCode.setNestedPositions(new int[][] {{}}); + return; + } + byteCode.setNested(nested); + byteCode.setNestedPositions(new int[][] {{0, 2}}); } } Added: harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/ICTupleTest.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/ICTupleTest.java?rev=616345&view=auto ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/ICTupleTest.java (added) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/ICTupleTest.java Tue Jan 29 06:35:57 2008 @@ -0,0 +1,83 @@ +/* + * 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.tests; + +import junit.framework.TestCase; +import org.apache.harmony.pack200.IcTuple; + +public class ICTupleTest extends TestCase { + + public void testPredictedClassTupleParsing() { + IcTuple tuple = new IcTuple(); + tuple.C = "orw/SimpleHelloWorld$SimpleHelloWorldInner"; + tuple.C2 = null; + tuple.F = 0; + tuple.N = null; + assertEquals("SimpleHelloWorldInner", tuple.simpleClassName()); + assertEquals("orw/SimpleHelloWorld", tuple.outerClassString()); + + tuple = new IcTuple(); + tuple.C = "java/util/AbstractList$2$Local"; + tuple.C2 = null; + tuple.F = 0; + tuple.N = null; + assertEquals("Local", tuple.simpleClassName()); + assertEquals("java/util/AbstractList$2", tuple.outerClassString()); + + tuple = new IcTuple(); + tuple.C = "java/util/AbstractList#2#Local"; + tuple.C2 = null; + tuple.F = 0; + tuple.N = null; + assertEquals("Local", tuple.simpleClassName()); + assertEquals("java/util/AbstractList$2", tuple.outerClassString()); + + tuple = new IcTuple(); + tuple.C = "java/util/AbstractList$1"; + tuple.C2 = null; + tuple.F = 0; + tuple.N = null; + assertEquals("1", tuple.simpleClassName()); + assertEquals("java/util/AbstractList", tuple.outerClassString()); + } + + public void testExplicitClassTupleParsing() { + IcTuple tuple = new IcTuple(); + tuple.C = "Foo$$2$Local"; + tuple.C2 = null; + tuple.F = IcTuple.NESTED_CLASS_FLAG; + tuple.N = "$2$Local"; + assertEquals("$2$Local", tuple.simpleClassName()); + assertEquals(null, tuple.outerClassString()); + + tuple = new IcTuple(); + tuple.C = "Red$Herring"; + tuple.C2 = "Red$Herring"; + tuple.F = IcTuple.NESTED_CLASS_FLAG; + tuple.N = null; + assertEquals(null, tuple.simpleClassName()); + assertEquals("Red$Herring", tuple.outerClassString()); + + tuple = new IcTuple(); + tuple.C = "X$1$Q"; + tuple.C2 = "X$1"; + tuple.F = IcTuple.NESTED_CLASS_FLAG; + tuple.N = "Q"; + assertEquals("Q", tuple.simpleClassName()); + assertEquals("X$1", tuple.outerClassString()); + } +} Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/SegmentTest.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/SegmentTest.java?rev=616345&r1=616344&r2=616345&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/SegmentTest.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/SegmentTest.java Tue Jan 29 06:35:57 2008 @@ -33,8 +33,6 @@ InputStream in; JarOutputStream out; - boolean handlingInnerClasses = false; - public void testHelloWorld() throws Exception { in = Segment.class .getResourceAsStream("/org/apache/harmony/pack200/tests/HelloWorld.pack"); @@ -74,7 +72,6 @@ // Test with an archive containing Harmony's SQL module public void testWithSql() throws Exception { - if(!handlingInnerClasses) return; in = Segment.class .getResourceAsStream("/org/apache/harmony/pack200/tests/sql.pack.gz"); Segment segment = Segment.parse(in); @@ -105,7 +102,6 @@ // Test with an archive containing Harmony's JNDI module public void testWithJNDIE1() throws Exception { - if(!handlingInnerClasses) return; in = Segment.class .getResourceAsStream("/org/apache/harmony/pack200/tests/jndi-e1.pack.gz"); Segment segment = Segment.parse(in);