blob: ab4b2faea3f8c6f8a60ec6fe439539a465db25dd [file] [log] [blame]
/**********************************************************************
* Copyright (c) 2002, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
 *
* Contributors:
* IBM - Initial API and implementation
**********************************************************************/
package org.eclipse.wtp.releng.tools.component.internalreference;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Vector;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.util.ClassFormatException;
import org.eclipse.jdt.core.util.IClassFileReader;
import org.eclipse.jdt.core.util.IConstantPool;
import org.eclipse.jdt.core.util.IConstantPoolConstant;
import org.eclipse.jdt.core.util.IConstantPoolEntry;
import org.eclipse.jdt.core.util.IFieldInfo;
import org.eclipse.jdt.core.util.IMethodInfo;
import org.eclipse.jdt.core.util.IModifierConstants;
import org.eclipse.jdt.internal.core.util.ClassFileReader;
import org.eclipse.wtp.releng.tools.component.location.ILocation;
/**
* A <code>Type</code> is a model object. Types contain references to other types.
*/
public class Type
{
private ILocation location;
private String name;
private IClassFileReader reader;
/**
* Creates a new type on the given location.
*
* @param location
*/
public Type(ILocation location)
{
this.location = location;
reader = null;
}
private void init()
{
if (reader == null)
{
try
{
reader = new ClassFileReader(getInputBytes(location), IClassFileReader.CONSTANT_POOL | IClassFileReader.METHOD_INFOS | IClassFileReader.FIELD_INFOS);
//reader = new ClassFileReader(getInputBytes(location), IClassFileReader.ALL);
}
catch (ClassFormatException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
/*
* Answers the references contained in the class that the reader is reading.
* @param reader a class file reader @return Set a set of references.
*/
private Set getReferencedTypes(IClassFileReader reader)
{
init();
Set types = new HashSet();
IConstantPool constantPool = reader.getConstantPool();
int poolSize = constantPool.getConstantPoolCount();
for (int i = 0; i < poolSize; i++)
{
// Extract the constant's referenced class (if that is even relevant)
if (constantPool.getEntryKind(i) == IConstantPoolConstant.CONSTANT_Class)
{
IConstantPoolEntry classEntry = constantPool.decodeEntry(i);
String signature = new String(classEntry.getClassInfoName());
int index = signature.lastIndexOf('[');
if (index > -1)
{
// could be an array of a primitive type
if (signature.length() - (index + 1) == 1)
continue;
signature = Signature.toString(signature);
signature = signature.substring(0, signature.length() - 2 * (index + 1));
signature = signature.replace('.', '$');
}
String typeName = signature.replace('/', '.');
types.add(typeName);
}
}
return types;
}
/**
* @return Set a set of <code>InternalTypeReference</code> objects
*/
public Set getReferencedTypes()
{
return getReferencedTypes(reader);
}
/**
* @return String the fully qualified name of the type
*/
public String getName()
{
if (name == null)
{
init();
name = toClassName(reader.getClassName());
}
return name;
}
public String getSuperClass()
{
init();
char[] superClass = reader.getSuperclassName();
if (superClass != null)
return toClassName(superClass);
else
return null;
}
public String[] getInterfaces()
{
init();
char[][] interfaceNames = reader.getInterfaceNames();
String[] interfaces = new String[interfaceNames.length];
for (int i = 0; i < interfaces.length; i++)
interfaces[i] = toClassName(interfaceNames[i]);
return interfaces;
}
public IFieldInfo[] getFieldInfo()
{
init();
return reader.getFieldInfos();
}
public IMethodInfo[] getMethodInfo()
{
init();
return reader.getMethodInfos();
}
public IConstantPoolEntry[] getConstantPoolEntries(int kind)
{
init();
List entries = new Vector();
IConstantPool pool = reader.getConstantPool();
int poolSize = pool.getConstantPoolCount();
for (int i = 0; i < poolSize; i++)
if (pool.getEntryKind(i) == kind)
entries.add(pool.decodeEntry(i));
return (IConstantPoolEntry[])entries.toArray(new IConstantPoolEntry[0]);
}
public boolean isInterface()
{
init();
return ((reader.getAccessFlags() & IModifierConstants.ACC_INTERFACE) == IModifierConstants.ACC_INTERFACE);
}
public int getAccessFlags()
{
init();
return reader.getAccessFlags();
}
private String toClassName(char[] name)
{
return new String(name).replace('/', '.');
}
/*
* Reads the content bytes found at the given location @param location a
* location, not <code> null </code> . @return byte[] the content at the
* location @throws IOException if a read error occured.
*/
protected byte[] getInputBytes(ILocation location) throws IOException
{
InputStream in = null;
byte[] fBuffer = new byte[8192];
ByteArrayOutputStream fBytesOut = new ByteArrayOutputStream(8192);
try
{
fBytesOut.reset();
in = location.getInputStream();
for (int read = in.read(fBuffer); read != -1; read = in.read(fBuffer))
{
fBytesOut.write(fBuffer, 0, read);
}
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
finally
{
in.close();
}
return fBytesOut.toByteArray();
}
public void reset()
{
reader = null;
}
}