All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ibm.wala.classLoader.ArrayClass Maven / Gradle / Ivy

/*
 * Copyright (c) 2002 - 2006 IBM Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 */
package com.ibm.wala.classLoader;

import static com.ibm.wala.types.TypeName.ArrayMask;
import static com.ibm.wala.types.TypeName.ElementBits;
import static com.ibm.wala.types.TypeName.PrimitiveMask;

import com.ibm.wala.core.util.strings.Atom;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.shrike.shrikeBT.Constants;
import com.ibm.wala.types.Selector;
import com.ibm.wala.types.TypeName;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.types.annotations.Annotation;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.debug.UnimplementedError;
import java.io.Reader;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;

/**
 * Implementation of {@link IClass} for array classes. Such classes would be best called 'broken
 * covariant array types', since that is the semantics that they implement.
 */
public class ArrayClass implements IClass, Constants {

  private final IClassHierarchy cha;

  /**
   * Package-visible constructor; only for use by ArrayClassLoader class. 'loader' must be the
   * Primordial IClassLoader.
   *
   * 

[WHY? -- array classes are loaded by the element classloader??] */ ArrayClass(TypeReference type, IClassLoader loader, IClassHierarchy cha) { this.type = type; this.loader = loader; this.cha = cha; TypeReference elementType = type.getInnermostElementType(); if (!elementType.isPrimitiveType()) { IClass klass = loader.lookupClass(elementType.getName()); if (klass == null) { Assertions.UNREACHABLE("caller should not attempt to create an array with type " + type); } } else { // assert loader.getReference().equals(ClassLoaderReference.Primordial); } } private final TypeReference type; private final IClassLoader loader; @Override public IClassLoader getClassLoader() { return loader; } @Override public TypeName getName() { return getReference().getName(); } /** Does this class represent an array of primitives? */ public boolean isOfPrimitives() { return this.type.getInnermostElementType().isPrimitiveType(); } @Override public boolean isInterface() { return false; } @Override public boolean isAbstract() { return false; } @Override public int getModifiers() { return ACC_PUBLIC | ACC_FINAL; } public String getQualifiedNameForReflection() { return type.getName().toString(); // XXX is this the right string? } @Override public IClass getSuperclass() { IClass elt = getElementClass(); assert getReference().getArrayElementType().isPrimitiveType() || elt != null; // super is Ljava/lang/Object in two cases: // 1) [Ljava/lang/Object // 2) [? for primitive arrays (null from getElementClass) if (elt == null || elt.getReference() == getClassLoader().getLanguage().getRootType()) { return loader.lookupClass(getClassLoader().getLanguage().getRootType().getName()); } // else it is array of super of element type (yuck) else { TypeReference eltSuperRef = elt.getSuperclass().getReference(); TypeReference superRef = TypeReference.findOrCreateArrayOf(eltSuperRef); return elt.getSuperclass().getClassLoader().lookupClass(superRef.getName()); } } @Override public IMethod getMethod(Selector sig) { return cha.lookupClass(getClassLoader().getLanguage().getRootType()).getMethod(sig); } @Override public IField getField(Atom name) { return getSuperclass().getField(name); } @Override public IField getField(Atom name, TypeName typeName) { return getSuperclass().getField(name, typeName); } @Override public Collection getDeclaredMethods() { return Collections.emptySet(); } public int getNumberOfDeclaredMethods() { return 0; } @Override public TypeReference getReference() { return type; } @Override public String getSourceFileName() { return null; } @Override public IMethod getClassInitializer() { return null; } @Override public boolean isArrayClass() { return true; } @Override public String toString() { return getReference().toString(); } /** * @return the IClass that represents the array element type, or null if the element type is a * primitive */ public IClass getElementClass() { TypeReference elementType = getReference().getArrayElementType(); if (elementType.isPrimitiveType()) { return null; } return loader.lookupClass(elementType.getName()); } @Override public int hashCode() { return type.hashCode(); } @Override public Collection getDeclaredInstanceFields() throws UnsupportedOperationException { throw new UnsupportedOperationException(); } @Override public Collection getDeclaredStaticFields() throws UnimplementedError { Assertions.UNREACHABLE(); return null; } @Override public Collection getAllImplementedInterfaces() { HashSet result = HashSetFactory.make(2); for (TypeReference ref : getClassLoader().getLanguage().getArrayInterfaces()) { IClass klass = loader.lookupClass(ref.getName()); if (klass != null) { result.add(klass); } } return result; } /** * @see IClass#getAllImplementedInterfaces() */ public Collection getAllAncestorInterfaces() throws UnsupportedOperationException { throw new UnsupportedOperationException(); } @Override public boolean isReferenceType() { return true; } public int getDimensionality() { return getArrayTypeDimensionality(getReference()); } /** * @param reference a type reference for an array type * @return the dimensionality of the array */ public static int getArrayTypeDimensionality(TypeReference reference) { int mask = reference.getDerivedMask(); if ((mask & PrimitiveMask) == PrimitiveMask) { mask >>= ElementBits; } int dims = 0; while ((mask & ArrayMask) == ArrayMask) { mask >>= ElementBits; dims++; } assert dims > 0; return dims; } /** * @return the IClass that represents the innermost array element type, or null if the element * type is a primitive */ public IClass getInnermostElementClass() { TypeReference elementType = getReference().getInnermostElementType(); if (elementType.isPrimitiveType()) { return null; } return loader.lookupClass(elementType.getName()); } @Override public Collection getDirectInterfaces() throws UnimplementedError { // TODO Auto-generated method stub Assertions.UNREACHABLE(); return null; } @Override public boolean equals(Object obj) { if (obj instanceof ArrayClass) { ArrayClass other = (ArrayClass) obj; return loader.equals(other.loader) && type.equals(other.type); } else { return false; } } @Override public Collection getAllInstanceFields() { Assertions.UNREACHABLE(); return null; } @Override public Collection getAllStaticFields() { Assertions.UNREACHABLE(); return null; } @Override public Collection getAllMethods() { return loader .lookupClass(getClassLoader().getLanguage().getRootType().getName()) .getAllMethods(); } @Override public Collection getAllFields() { Assertions.UNREACHABLE(); return null; } @Override public IClassHierarchy getClassHierarchy() { return cha; } @Override public boolean isPublic() { return true; } @Override public boolean isPrivate() { return false; } @Override public boolean isSynthetic() { return false; } @Override public Reader getSource() { return null; } @Override public Collection getAnnotations() { return Collections.emptySet(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy