/*
* @(#)ArrayClassInfo.java 1.30 06/10/22
*
* Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 for more details (a copy is
* included at /legal/license.txt).
*
* You should have received a copy of the GNU General Public License
* version 2 along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.com if you need additional
* information or have any questions.
*
*/
package vm;
import consts.Const;
import components.*;
import util.*;
/*
* An array is a class.
* It is a subclass of java.lang.Object.
* It has all the class-related runtime data structures, or at least
* may of them.
* It is not read in from class files, but is made up on-the-fly
* when the classresolver sees a reference to a classname starting with
* "[".
*
* In order to resolve such references early, we must do likewise here.
*/
public
class ArrayClassInfo extends ClassInfo {
private static int nFake = 0;
public int arrayClassNumber;
public int depth;
public int baseType;
public ClassConstant baseClass;
public int elemClassAccess;
public ClassConstant subarrayClass;
/*
* Given signature s,
* fill in
* depth ( i.e. number of opening [ )
* basetype ( i.e. thing after the last [ )
* and baseClass ( if basetype is a classtype )
*/
private void fillInTypeInfo( String s ) throws DataFormatException {
int index = 0;
char c;
while( ( c = s.charAt( index ) ) == Const.SIGC_ARRAY )
index++;
depth = index;
switch( c ){
case Const.SIGC_INT:
baseType = Const.T_INT;
elemClassAccess = Const.ACC_PUBLIC;
break;
case Const.SIGC_LONG:
baseType = Const.T_LONG;
elemClassAccess = Const.ACC_PUBLIC;
break;
case Const.SIGC_FLOAT:
baseType = Const.T_FLOAT;
elemClassAccess = Const.ACC_PUBLIC;
break;
case Const.SIGC_DOUBLE:
baseType = Const.T_DOUBLE;
elemClassAccess = Const.ACC_PUBLIC;
break;
case Const.SIGC_BOOLEAN:
baseType = Const.T_BOOLEAN;
elemClassAccess = Const.ACC_PUBLIC;
break;
case Const.SIGC_BYTE:
baseType = Const.T_BYTE;
elemClassAccess = Const.ACC_PUBLIC;
break;
case Const.SIGC_CHAR:
baseType = Const.T_CHAR;
elemClassAccess = Const.ACC_PUBLIC;
break;
case Const.SIGC_SHORT:
baseType = Const.T_SHORT;
elemClassAccess = Const.ACC_PUBLIC;
break;
case Const.SIGC_CLASS:
baseType = Const.T_CLASS;
ClassInfo baseClassInfo = baseClass.find();
// The base class' access should propagate to all arrays with
// that base class, so elemClassAccess really is equivalent
// to the the access flags of the base class
elemClassAccess = baseClassInfo.access;
break;
default:
throw new DataFormatException(Localizer.getString("arrayclassinfo.malformed_array_type_string.dataformatexception",s));
}
// For CVM, we want to know the sub-class, which is different from
// the base class.
if ( depth > 1 ){
// sub-classes have already been entered
ClassInfo ci = ClassTable.lookupClass(s.substring(1));
subarrayClass = new ClassConstant(ci);
} else if ( depth == 1 ) {
subarrayClass = baseClass;
}
}
public ArrayClassInfo( boolean v, String s, ClassConstant base )
throws DataFormatException
{
super(v);
arrayClassNumber = nFake++;
baseClass = base;
className = s;
thisClass = new ClassConstant( new UnicodeConstant( s ) );
superClassInfo = ClassTable.lookupClass("java/lang/Object");
superClass = superClassInfo.thisClass;
access = Const.ACC_FINAL|Const.ACC_ABSTRACT;
methods = new MethodInfo[0];
fields = new FieldInfo[0];
fillInTypeInfo( s );
access |= (elemClassAccess & Const.ACC_PUBLIC);
}
protected String createGenericNativeName() {
return /*NOI18N*/"fakeArray" + arrayClassNumber;
}
public void buildFieldtable() {}
public void buildMethodtable() {}
public String getNativeName() {
switch ( baseType ) {
case Const.T_INT:
return "Int";
case Const.T_LONG:
return "Long";
case Const.T_FLOAT:
return "Float";
case Const.T_DOUBLE:
return "Double";
case Const.T_BOOLEAN:
return "Boolean";
case Const.T_BYTE:
return "Byte";
case Const.T_CHAR:
return "Char";
case Const.T_SHORT:
return "Short";
default:
return "ERROR";
}
}
public static boolean
collectArrayClass(String cname, components.ClassLoader classloader, boolean verbose)
{
// cname is the name of an array class
// make sure it doesn't exist ( it won't if it came from a
// class constant ), and instantiate it. For CVM, do the same with
// any sub-array types.
//
// make sure the base type (if a class) already exists:
// under CVM, it cannot correctly represent an array
// of an unresolved base class.
boolean good = true;
int lastBracket = cname.lastIndexOf('[');
ClassInfo baseClassInfo = null;
if ( lastBracket < cname.length()-2 ){
// it is a [[[[[Lsomething;
// isolate the something and see if its defined.
String baseClass = cname.substring(lastBracket+2, cname.length()-1);
baseClassInfo = ClassTable.lookupClass(baseClass, classloader);
if (baseClassInfo == null) {
// base class not defined. punt this.
if (verbose) {
System.out.println(Localizer.getString(
"javacodecompact.array_class_not_instantiated",
cname, baseClass));
}
return good;
}
} else {
String baseClass = cname.substring(lastBracket+1, cname.length());
baseClassInfo =
ClassTable.lookupPrimitiveClass(baseClass.charAt(0));
if (baseClassInfo == null) {
// base class not defined. punt this.
System.out.println(Localizer.getString(
"javacodecompact.array_class_not_instantiated",
cname, baseClass));
if (verbose) {
System.out.println(Localizer.getString(
"javacodecompact.array_class_not_instantiated",
cname, baseClass));
}
// return false;
}
}
components.ClassLoader loader = baseClassInfo.loader;
ClassConstant baseClassConstant = new ClassConstant(baseClassInfo);
// enter sub-classes first
for (int i = lastBracket; i >= 0; --i) {
String aname = cname.substring(i);
ClassInfo cinfo = ClassTable.lookupClass(aname, loader);
if (cinfo != null) {
// this one exists. But subclasses may not, so keep going.
continue;
}
try {
ClassInfo newArray =
new ArrayClassInfo(verbose, aname, baseClassConstant);
ClassTable.enterClass(newArray, loader);
} catch ( DataFormatException e ){
e.printStackTrace();
good = false;
break; // out of do...while
}
}
return good;
}
}