blob: be16daabc3958095119c3776e1699c1471b3b35d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2008 IBM Corporation and others.
* 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 org.eclipse.pde.api.tools.internal.util;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.filebuffers.ITextFileBufferManager;
import org.eclipse.core.filebuffers.LocationKind;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ArrayType;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.ParameterizedType;
import org.eclipse.jdt.core.dom.PrimitiveType;
import org.eclipse.jdt.core.dom.QualifiedType;
import org.eclipse.jdt.core.dom.SimpleType;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.internal.launching.EEVMType;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jdt.launching.LibraryLocation;
import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
import org.eclipse.jdt.launching.environments.IExecutionEnvironmentsManager;
import org.eclipse.jface.text.IDocument;
import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.api.tools.internal.ApiSettingsXmlVisitor;
import org.eclipse.pde.api.tools.internal.IApiCoreConstants;
import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin;
import org.eclipse.pde.api.tools.internal.provisional.Factory;
import org.eclipse.pde.api.tools.internal.provisional.IApiComponent;
import org.eclipse.pde.api.tools.internal.provisional.IClassFile;
import org.eclipse.pde.api.tools.internal.provisional.RestrictionModifiers;
import org.eclipse.pde.api.tools.internal.provisional.VisibilityModifiers;
import org.eclipse.pde.api.tools.internal.provisional.comparator.DeltaVisitor;
import org.eclipse.pde.api.tools.internal.provisional.comparator.IDelta;
import org.eclipse.pde.api.tools.internal.provisional.descriptors.IElementDescriptor;
import org.eclipse.pde.api.tools.internal.provisional.descriptors.IReferenceTypeDescriptor;
import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblem;
import org.eclipse.pde.api.tools.internal.provisional.search.ReferenceModifiers;
import org.objectweb.asm.Opcodes;
import org.osgi.framework.Version;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* A Utility class to use for API tools
*
* @since 1.0.0
*/
public final class Util {
/**
* Class that runs a build in the workspace or the given project
*/
private static final class BuildJob extends Job {
private final IProject[] fProjects;
/**
* Constructor
* @param name
* @param project
*/
private BuildJob(String name, IProject[] projects) {
super(name);
fProjects = projects;
}
public boolean belongsTo(Object family) {
return ResourcesPlugin.FAMILY_MANUAL_BUILD == family;
}
/**
* Returns if this build job is covered by another build job
* @param other
* @return true if covered by another build job, false otherwise
*/
public boolean isCoveredBy(BuildJob other) {
if (other.fProjects == null) {
return true;
}
if (this.fProjects != null) {
for (int i = 0, max = this.fProjects.length; i < max; i++) {
if (!other.contains(this.fProjects[i])) {
return false;
}
}
return true;
}
return false;
}
public boolean contains(IProject project) {
if (project == null) return false;
for (int i = 0, max = this.fProjects.length; i < max; i++) {
if (project.equals(this.fProjects[i])) {
return true;
}
}
return false;
}
/* (non-Javadoc)
* @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
*/
protected IStatus run(IProgressMonitor monitor) {
synchronized (getClass()) {
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
Job[] buildJobs = Job.getJobManager().find(ResourcesPlugin.FAMILY_MANUAL_BUILD);
for (int i= 0; i < buildJobs.length; i++) {
Job curr= buildJobs[i];
if (curr != this && curr instanceof BuildJob) {
BuildJob job= (BuildJob) curr;
if (job.isCoveredBy(this)) {
curr.cancel(); // cancel all other build jobs of our kind
}
}
}
}
try {
if (fProjects != null) {
int length = fProjects.length;
monitor.beginTask(UtilMessages.Util_0, length);
for (int i = 0; i < length; i++) {
IProject project = fProjects[i];
monitor.subTask(NLS.bind(UtilMessages.Util_5, project.getName()));
project.build(IncrementalProjectBuilder.FULL_BUILD, ApiPlugin.BUILDER_ID, null, new SubProgressMonitor(monitor,1));
monitor.worked(1);
}
}
} catch (CoreException e) {
return e.getStatus();
} catch (OperationCanceledException e) {
return Status.CANCEL_STATUS;
}
finally {
monitor.done();
}
return Status.OK_STATUS;
}
}
public static boolean DEBUG;
public static final String EMPTY_STRING = "";//$NON-NLS-1$
public static final String DEFAULT_PACKAGE_NAME = EMPTY_STRING;
public static final String DOT_CLASS_SUFFIX = ".class"; //$NON-NLS-1$
/**
* Constant representing the default size to read from an input stream
*/
private static final int DEFAULT_READING_SIZE = 8192;
private static final String JAVA_LANG_OBJECT = "java.lang.Object"; //$NON-NLS-1$
private static final String JAVA_LANG_RUNTIMEEXCEPTION = "java.lang.RuntimeException"; //$NON-NLS-1$
public static final String LINE_DELIMITER = System.getProperty("line.separator"); //$NON-NLS-1$
public static final String UNKNOWN_ELEMENT_TYPE = "UNKOWN_ELEMENT_KIND"; //$NON-NLS-1$
public static final String UNKNOWN_FLAGS = "UNKNOWN_FLAGS"; //$NON-NLS-1$
public static final String UNKNOWN_KIND = "UNKOWN_KIND"; //$NON-NLS-1$
public static final IClassFile[] NO_CLASS_FILES = new IClassFile[0];
// Trace for delete operation
/*
* Maximum time wasted repeating delete operations while running JDT/Core tests.
*/
private static int DELETE_MAX_TIME = 0;
/**
* Trace deletion operations while running JDT/Core tests.
*/
private static boolean DELETE_DEBUG = false;
/**
* Maximum of time in ms to wait in deletion operation while running JDT/Core tests.
* Default is 10 seconds. This number cannot exceed 1 minute (ie. 60000).
* <br>
* To avoid too many loops while waiting, the ten first ones are done waiting
* 10ms before repeating, the ten loops after are done waiting 100ms and
* the other loops are done waiting 1s...
*/
private static int DELETE_MAX_WAIT = 10000;
static {
String property = System.getProperty("DEBUG"); //$NON-NLS-1$
DEBUG = property != null && property.equalsIgnoreCase("TRUE"); //$NON-NLS-1$
}
/**
* Throws an exception with the given message and underlying exception.
*
* @param message error message
* @param exception underlying exception, or <code>null</code>
* @throws CoreException
*/
private static void abort(String message, Throwable exception) throws CoreException {
IStatus status = new Status(IStatus.ERROR, ApiPlugin.PLUGIN_ID, message, exception);
throw new CoreException(status);
}
/**
* Appends a property to the given string buffer with the given key and value
* in the format "key=value\n".
*
* @param buffer buffer to append to
* @param key key
* @param value value
*/
private static void appendProperty(StringBuffer buffer, String key, String value) {
buffer.append(key);
buffer.append('=');
buffer.append(value);
buffer.append('\n');
}
/**
* Collects all of the deltas from the given parent delta
* @param delta
* @return
*/
public static List collectAllDeltas(IDelta delta) {
final List list = new ArrayList();
delta.accept(new DeltaVisitor() {
public void endVisit(IDelta localDelta) {
if (localDelta.getChildren().length == 0) {
list.add(localDelta);
}
super.endVisit(localDelta);
}
});
return list;
}
/**
* Collects files into the collector array list
*
* @param root
* the root to collect the files from
* @param collector
* the collector to place matches into
* @param fileFilter
* the filter for files or <code>null</code> to accept all
* files
*/
private static void collectAllFiles(File root, ArrayList collector, FileFilter fileFilter) {
File[] files = root.listFiles(fileFilter);
for (int i = 0; i < files.length; i++) {
final File currentFile = files[i];
if (currentFile.isDirectory()) {
collectAllFiles(currentFile, collector, fileFilter);
} else {
collector.add(currentFile);
}
}
}
/**
* Convert fully qualified signature to unqualified one.
* The descriptor can be dot or slashed based.
*
* @param descriptor the given descriptor to convert
* @return the converted signature
*/
public static String dequalifySignature(String signature) {
StringBuffer buffer = new StringBuffer();
char[] chars = signature.toCharArray();
for (int i = 0, max = chars.length; i < max; i++) {
char currentChar = chars[i];
switch(currentChar) {
case 'L' : {
buffer.append('Q');
// read reference type
int lastDotPosition = i;
i++;
while(i < chars.length && (currentChar = chars[i]) != ';') {
switch(currentChar) {
case '/' :
case '.' :
lastDotPosition = i;
break;
}
i++;
}
buffer.append(chars, lastDotPosition + 1, i - lastDotPosition - 1);
buffer.append(';');
break;
}
case 'Q': {
while(i < chars.length && currentChar != ';') {
buffer.append(currentChar);
currentChar = chars[++i];
}
}
default: {
buffer.append(currentChar);
}
}
}
return String.valueOf(buffer);
}
/**
* Returns all of the API projects in the workspace
* @return all of the API projects in the workspace or <code>null</code> if there are none.
*/
public static IProject[] getApiProjects() {
IProject[] allProjects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
ArrayList temp = new ArrayList();
IProject project = null;
for (int i = 0, max = allProjects.length; i < max; i++) {
project = allProjects[i];
if (project.isAccessible()) {
try {
if (project.hasNature(org.eclipse.pde.api.tools.internal.provisional.ApiPlugin.NATURE_ID)) {
temp.add(project);
}
}
catch (CoreException e) {}
}
}
IProject[] projects = null;
if (temp.size() != 0) {
projects = new IProject[temp.size()];
temp.toArray(projects);
}
return projects;
}
/**
* Returns if the specified signature is qualified or not.
* Qualification is determined if there is a token in the signature the begins with an 'L'.
* @param signature
* @return true if the signature is qualified, false otherwise
*/
public static boolean isQualifiedSignature(String signature) {
StringTokenizer tokenizer = new StringTokenizer(signature, "();IJCSBDFTZ!["); //$NON-NLS-1$
if(tokenizer.hasMoreTokens()) {
return tokenizer.nextToken().charAt(0) == 'L';
}
return false;
}
/**
* Copies the given file to the new file
* @param file
* @param newFile
* @return if the copy succeeded
*/
public static boolean copy(File file, File newFile) {
byte[] bytes = null;
BufferedInputStream inputStream = null;
try {
inputStream = new BufferedInputStream(new FileInputStream(file));
bytes = Util.getInputStreamAsByteArray(inputStream, -1);
} catch (FileNotFoundException e) {
ApiPlugin.log(e);
} catch (IOException e) {
ApiPlugin.log(e);
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
ApiPlugin.log(e);
}
}
}
if (bytes != null) {
BufferedOutputStream outputStream = null;
try {
outputStream = new BufferedOutputStream(new FileOutputStream(newFile));
outputStream.write(bytes);
outputStream.flush();
} catch (FileNotFoundException e) {
ApiPlugin.log(e);
} catch (IOException e) {
ApiPlugin.log(e);
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch(IOException e) {
// ignore
}
}
}
return true;
}
return false;
}
/**
* Creates an ee file using the default ee id set in the workspace, or 'JavaSE 1.6' if there
* is no default ee id set or the framework is not running
*
* @return a new ee file
* @throws IOException
* @throws CoreException
*/
public static File createDefaultEEFile() throws IOException, CoreException {
return createEEFile(getDefaultEEId());
}
/**
* Resolves an EE file given the id of the environment
* @param eeid
* @return
* @throws IOException
*/
public static File createEEFile(String eeid) throws IOException, CoreException {
if (ApiPlugin.isRunningInFramework()) {
IExecutionEnvironmentsManager manager = JavaRuntime.getExecutionEnvironmentsManager();
IExecutionEnvironment environment = manager.getEnvironment(eeid);
IVMInstall[] compatibleVMs = environment.getCompatibleVMs();
IVMInstall jre = null;
for (int i = 0; i < compatibleVMs.length; i++) {
IVMInstall install = compatibleVMs[i];
if (environment.isStrictlyCompatible(install)) {
jre = install;
break;
}
}
if (jre == null && compatibleVMs.length > 0) {
jre = compatibleVMs[0];
}
if (jre == null) {
jre = JavaRuntime.getDefaultVMInstall();
}
return createEEFile(jre, eeid);
} else {
String fileName = System.getProperty("ee.file"); //$NON-NLS-1$
if (fileName == null) {
abort("Could not retrieve the ee.file property", null); //$NON-NLS-1$
}
return new File(fileName);
}
}
/**
* Creates an EE file for the given JRE and specified EE id
* @param eeid
* @return
* @throws IOException
*/
public static File createEEFile(IVMInstall jre, String eeid) throws IOException {
String string = Util.generateEEContents(jre, eeid);
File eeFile = File.createTempFile("eed", ".ee"); //$NON-NLS-1$ //$NON-NLS-2$
eeFile.deleteOnExit();
FileOutputStream outputStream = new FileOutputStream(eeFile);
outputStream.write(string.getBytes(IApiCoreConstants.UTF_8));
outputStream.close();
return eeFile;
}
/**
* Returns whether the objects are equal, accounting for either one being <code>null</code>.
*
* @param o1
* @param o2
* @return whether the objects are equal, or both are <code>null</code>
*/
public static boolean equalsOrNull(Object o1, Object o2) {
if (o1 == null) {
return o2 == null;
}
return o1.equals(o2);
}
/**
* Returns an execution environment description for the given VM.
*
* @param vm JRE to create an definition for
* @return an execution environment description for the given VM
* @throws IOException if unable to generate description
*/
public static String generateEEContents(IVMInstall vm, String eeId) throws IOException {
StringBuffer buffer = new StringBuffer();
appendProperty(buffer, EEVMType.PROP_JAVA_HOME, vm.getInstallLocation().getCanonicalPath());
StringBuffer paths = new StringBuffer();
LibraryLocation[] libraryLocations = JavaRuntime.getLibraryLocations(vm);
for (int i = 0; i < libraryLocations.length; i++) {
LibraryLocation lib = libraryLocations[i];
paths.append(lib.getSystemLibraryPath().toOSString());
if (i < (libraryLocations.length - 1)) {
paths.append(File.pathSeparatorChar);
}
}
appendProperty(buffer, EEVMType.PROP_BOOT_CLASS_PATH, paths.toString());
appendProperty(buffer, EEVMType.PROP_CLASS_LIB_LEVEL, eeId);
return buffer.toString();
}
/**
* Returns an array of all of the files from the given root that are
* accepted by the given file filter. If the file filter is null all files
* within the given root are returned.
*
* @param root
* @param fileFilter
* @return the list of files from within the given root
*/
public static File[] getAllFiles(File root, FileFilter fileFilter) {
ArrayList files = new ArrayList();
if (root.isDirectory()) {
collectAllFiles(root, files, fileFilter);
File[] result = new File[files.size()];
files.toArray(result);
return result;
}
return null;
}
/**
* Returns XML for the component's current API description.
*
* @param apiComponent API component
* @return XML for the API description
* @throws CoreException if something goes terribly wrong
*/
public static String getApiDescriptionXML(IApiComponent apiComponent) throws CoreException {
ApiSettingsXmlVisitor xmlVisitor = new ApiSettingsXmlVisitor(apiComponent);
apiComponent.getApiDescription().accept(xmlVisitor);
return xmlVisitor.getXML();
}
/**
* Returns a build job
* @param projects The projects to build or <code>null</code> to build the workspace.
* @return the build job
*/
public static Job getBuildJob(final IProject[] projects) {
Assert.isNotNull(projects);
Job buildJob = new BuildJob(UtilMessages.Util_4, projects);
buildJob.setRule(ResourcesPlugin.getWorkspace().getRuleFactory().buildRule());
buildJob.setUser(true);
return buildJob;
}
/**
* Returns the {@link IClassFile} with the given name from the first {@link IApiComponent}
* it is found in, or <code>null</code> if not found
* @param components
* @param typeName
* @return the {@link IClassFile} with the given name or <code>null</code>
*/
public static IClassFile getClassFile(IApiComponent[] components, String typeName) {
if (components == null) return null;
for (int i = 0, max = components.length; i < max; i++) {
IApiComponent apiComponent = components[i];
if (apiComponent != null) {
try {
IClassFile classFile = apiComponent.findClassFile(typeName);
if (classFile != null) {
return classFile;
}
} catch (CoreException e) {
// ignore
}
}
}
return null;
}
/**
* Returns the component with the given type name or <code>null</code>
* @param components
* @param typeName
* @return the component with the given type name or <code>null</code>
*/
public static IApiComponent getComponent(IApiComponent[] components, String typeName) {
if (components == null) return null;
for (int i = 0, max = components.length; i < max; i++) {
IApiComponent apiComponent = components[i];
if (apiComponent != null) {
try {
IClassFile classFile = apiComponent.findClassFile(typeName);
if (classFile != null) {
return apiComponent;
}
} catch (CoreException e) {
// ignore
}
}
}
return null;
}
/**
* @return the id of the default execution environment specified in the workspace,
* or 'JavaSE-1.6' if none can be derived
*/
public static String getDefaultEEId() {
String eeid = "JavaSE-1.6"; //$NON-NLS-1$
IVMInstall install = JavaRuntime.getDefaultVMInstall();
if (install != null) {
IExecutionEnvironment[] environments = JavaRuntime.getExecutionEnvironmentsManager().getExecutionEnvironments();
for (int i = 0; i < environments.length; i++) {
if (environments[i].isStrictlyCompatible(install)) {
return environments[i].getId();
}
}
}
return eeid;
}
/**
* Return a string that represents the element type of the given delta.
* Returns {@link #UNKNOWN_ELEMENT_TYPE} if the element type cannot be determined.
*
* @param delta the given delta
* @return a string that represents the element type of the given delta.
*/
public static String getDeltaElementType(IDelta delta) {
return getDeltaElementType(delta.getElementType());
}
/**
* Returns a text representation of a marker severity level
* @param severity
* @return text of a marker severity level
*/
public static String getSeverity(int severity) {
switch(severity) {
case IMarker.SEVERITY_ERROR: {
return "ERROR"; //$NON-NLS-1$
}
case IMarker.SEVERITY_INFO: {
return "INFO"; //$NON-NLS-1$
}
case IMarker.SEVERITY_WARNING: {
return "WARNING"; //$NON-NLS-1$
}
default: {
return "UNKNOWN_SEVERITY"; //$NON-NLS-1$
}
}
}
/**
* Return a string that represents the given element type
* Returns {@link #UNKNOWN_ELEMENT_TYPE} if the element type cannot be determined.
*
* @param elementType the given element type
* @return a string that represents the given element type.
*/
public static String getDeltaElementType(int elementType) {
switch(elementType) {
case IDelta.ANNOTATION_ELEMENT_TYPE :
return "ANNOTATION_ELEMENT_TYPE"; //$NON-NLS-1$
case IDelta.INTERFACE_ELEMENT_TYPE :
return "INTERFACE_ELEMENT_TYPE"; //$NON-NLS-1$
case IDelta.ENUM_ELEMENT_TYPE :
return "ENUM_ELEMENT_TYPE"; //$NON-NLS-1$
case IDelta.API_COMPONENT_ELEMENT_TYPE :
return "API_COMPONENT_ELEMENT_TYPE"; //$NON-NLS-1$
case IDelta.API_PROFILE_ELEMENT_TYPE :
return "API_PROFILE_ELEMENT_TYPE"; //$NON-NLS-1$
case IDelta.CONSTRUCTOR_ELEMENT_TYPE :
return "CONSTRUCTOR_ELEMENT_TYPE"; //$NON-NLS-1$
case IDelta.MEMBER_ELEMENT_TYPE :
return "MEMBER_ELEMENT_TYPE"; //$NON-NLS-1$
case IDelta.METHOD_ELEMENT_TYPE :
return "METHOD_ELEMENT_TYPE"; //$NON-NLS-1$
case IDelta.FIELD_ELEMENT_TYPE :
return "FIELD_ELEMENT_TYPE"; //$NON-NLS-1$
case IDelta.CLASS_ELEMENT_TYPE :
return "CLASS_ELEMENT_TYPE"; //$NON-NLS-1$
}
return UNKNOWN_ELEMENT_TYPE;
}
/**
* Return a string that represents the flags of the given delta.
* Returns {@link #UNKNOWN_FLAGS} if the flags cannot be determined.
*
* @param delta the given delta
* @return a string that represents the flags of the given delta.
*/
public static String getDeltaFlagsName(IDelta delta) {
return getDeltaFlagsName(delta.getFlags());
}
/**
* Return a string that represents the given flags
* Returns {@link #UNKNOWN_FLAGS} if the flags cannot be determined.
*
* @param flags the given delta's flags
* @return a string that represents the given flags.
*/
public static String getDeltaFlagsName(int flags) {
switch(flags) {
case IDelta.ABSTRACT_TO_NON_ABSTRACT : return "ABSTRACT_TO_NON_ABSTRACT"; //$NON-NLS-1$
case IDelta.ANNOTATION_DEFAULT_VALUE : return "ANNOTATION_DEFAULT_VALUE"; //$NON-NLS-1$
case IDelta.API_COMPONENT : return "API_COMPONENT"; //$NON-NLS-1$
case IDelta.ARRAY_TO_VARARGS : return "ARRAY_TO_VARARGS"; //$NON-NLS-1$
case IDelta.CHECKED_EXCEPTION : return "CHECKED_EXCEPTION"; //$NON-NLS-1$
case IDelta.CLASS_BOUND : return "CLASS_BOUND"; //$NON-NLS-1$
case IDelta.CLINIT : return "CLINIT"; //$NON-NLS-1$
case IDelta.CONSTRUCTOR : return "CONSTRUCTOR"; //$NON-NLS-1$
case IDelta.CONTRACTED_SUPERCLASS_SET : return "CONTRACTED_SUPERCLASS_SET"; //$NON-NLS-1$
case IDelta.CONTRACTED_SUPERINTERFACES_SET : return "CONTRACTED_SUPERINTERFACES_SET"; //$NON-NLS-1$
case IDelta.DECREASE_ACCESS : return "DECREASE_ACCESS"; //$NON-NLS-1$
case IDelta.ENUM_CONSTANT : return "ENUM_CONSTANT"; //$NON-NLS-1$
case IDelta.EXECUTION_ENVIRONMENT : return "EXECUTION_ENVIRONMENT"; //$NON-NLS-1$
case IDelta.EXPANDED_SUPERCLASS_SET : return "EXPANDED_SUPERCLASS_SET"; //$NON-NLS-1$
case IDelta.EXPANDED_SUPERINTERFACES_SET : return "EXPANDED_SUPERINTERFACES_SET"; //$NON-NLS-1$
case IDelta.FIELD : return "FIELD"; //$NON-NLS-1$
case IDelta.FIELD_MOVED_UP : return "FIELD_MOVED_UP"; //$NON-NLS-1$
case IDelta.FINAL_TO_NON_FINAL : return "FINAL_TO_NON_FINAL"; //$NON-NLS-1$
case IDelta.FINAL_TO_NON_FINAL_NON_STATIC : return "FINAL_TO_NON_FINAL_NON_STATIC"; //$NON-NLS-1$
case IDelta.FINAL_TO_NON_FINAL_STATIC_CONSTANT : return "FINAL_TO_NON_FINAL_STATIC_CONSTANT"; //$NON-NLS-1$
case IDelta.FINAL_TO_NON_FINAL_STATIC_NON_CONSTANT : return "FINAL_TO_NON_FINAL_STATIC_NON_CONSTANT"; //$NON-NLS-1$
case IDelta.INCREASE_ACCESS : return "INCREASE_ACCESS"; //$NON-NLS-1$
case IDelta.INTERFACE_BOUND : return "INTERFACE_BOUND"; //$NON-NLS-1$
case IDelta.INTERFACE_BOUNDS : return "INTERFACE_BOUNDS"; //$NON-NLS-1$
case IDelta.METHOD : return "METHOD"; //$NON-NLS-1$
case IDelta.METHOD_MOVED_UP : return "METHOD_MOVED_UP"; //$NON-NLS-1$
case IDelta.METHOD_WITH_DEFAULT_VALUE : return "METHOD_WITH_DEFAULT_VALUE"; //$NON-NLS-1$
case IDelta.METHOD_WITHOUT_DEFAULT_VALUE : return "METHOD_WITHOUT_DEFAULT_VALUE"; //$NON-NLS-1$
case IDelta.NATIVE_TO_NON_NATIVE : return "NATIVE_TO_NON_NATIVE"; //$NON-NLS-1$
case IDelta.NON_ABSTRACT_TO_ABSTRACT : return "NON_ABSTRACT_TO_ABSTRACT"; //$NON-NLS-1$
case IDelta.NON_FINAL_TO_FINAL : return "NON_FINAL_TO_FINAL"; //$NON-NLS-1$
case IDelta.NON_NATIVE_TO_NATIVE : return "NON_NATIVE_TO_NATIVE"; //$NON-NLS-1$
case IDelta.NON_STATIC_TO_STATIC : return "NON_STATIC_TO_STATIC"; //$NON-NLS-1$
case IDelta.NON_SYNCHRONIZED_TO_SYNCHRONIZED : return "NON_SYNCHRONIZED_TO_SYNCHRONIZED"; //$NON-NLS-1$
case IDelta.NON_TRANSIENT_TO_TRANSIENT : return "NON_TRANSIENT_TO_TRANSIENT"; //$NON-NLS-1$
case IDelta.STATIC_TO_NON_STATIC : return "STATIC_TO_NON_STATIC"; //$NON-NLS-1$
case IDelta.SUPERCLASS : return "SUPERCLASS"; //$NON-NLS-1$
case IDelta.SYNCHRONIZED_TO_NON_SYNCHRONIZED : return "SYNCHRONIZED_TO_NON_SYNCHRONIZED"; //$NON-NLS-1$
case IDelta.TO_ANNOTATION : return "TO_ANNOTATION"; //$NON-NLS-1$
case IDelta.TO_CLASS : return "TO_CLASS"; //$NON-NLS-1$
case IDelta.TO_ENUM : return "TO_ENUM"; //$NON-NLS-1$
case IDelta.TO_INTERFACE : return "TO_INTERFACE"; //$NON-NLS-1$
case IDelta.TRANSIENT_TO_NON_TRANSIENT : return "TRANSIENT_TO_NON_TRANSIENT"; //$NON-NLS-1$
case IDelta.TYPE : return "TYPE"; //$NON-NLS-1$
case IDelta.TYPE_ARGUMENTS : return "TYPE_ARGUMENTS"; //$NON-NLS-1$
case IDelta.TYPE_MEMBER : return "TYPE_MEMBER"; //$NON-NLS-1$
case IDelta.TYPE_PARAMETER : return "TYPE_PARAMETER"; //$NON-NLS-1$
case IDelta.TYPE_PARAMETER_NAME : return "TYPE_PARAMETER_NAME"; //$NON-NLS-1$
case IDelta.TYPE_PARAMETERS : return "TYPE_PARAMETERS"; //$NON-NLS-1$
case IDelta.TYPE_VISIBILITY : return "TYPE_VISIBILITY"; //$NON-NLS-1$
case IDelta.UNCHECKED_EXCEPTION : return "UNCHECKED_EXCEPTION"; //$NON-NLS-1$
case IDelta.VALUE : return "VALUE"; //$NON-NLS-1$
case IDelta.VARARGS_TO_ARRAY : return "VARARGS_TO_ARRAY"; //$NON-NLS-1$
case IDelta.RESTRICTIONS : return "RESTRICTIONS"; //$NON-NLS-1$
}
return UNKNOWN_FLAGS;
}
/**
* Return a string that represents the kind of the given delta.
* Returns {@link #UNKNOWN_KIND} if the kind cannot be determined.
*
* @param delta the given delta
* @return a string that represents the kind of the given delta.
*/
public static String getDeltaKindName(IDelta delta) {
return getDeltaKindName(delta.getKind());
}
/**
* Return a string that represents the given kind.
* Returns {@link #UNKNOWN_KIND} if the kind cannot be determined.
*
* @param delta the given kind
* @return a string that represents the given kind.
*/
public static String getDeltaKindName(int kind) {
switch(kind) {
case IDelta.ADDED :
return "ADDED"; //$NON-NLS-1$
case IDelta.CHANGED :
return "CHANGED"; //$NON-NLS-1$
case IDelta.REMOVED :
return "REMOVED"; //$NON-NLS-1$
}
return UNKNOWN_KIND;
}
/**
* Returns the preference key for the given element type, the given kind and the given flags.
*
* @param elementType the given element type (retrieved using {@link IDelta#getElementType()}
* @param kind the given kind (retrieved using {@link IDelta#getKind()}
* @param flags the given flags (retrieved using {@link IDelta#getFlags()}
* @return the preference key for the given element type, the given kind and the given flags.
*/
public static String getDeltaPrefererenceKey(int elementType, int kind, int flags) {
StringBuffer buffer = new StringBuffer(Util.getDeltaElementType(elementType));
buffer.append('_').append(Util.getDeltaKindName(kind));
if (flags != -1) {
buffer.append('_').append(Util.getDeltaFlagsName(flags));
}
return String.valueOf(buffer);
}
/**
* Returns the details of the api delta as a string
* @param delta
* @return the details of the delta as a string
*/
public static String getDetail(IDelta delta) {
StringBuffer buffer = new StringBuffer();
switch(delta.getElementType()) {
case IDelta.CLASS_ELEMENT_TYPE :
buffer.append("class"); //$NON-NLS-1$
break;
case IDelta.ANNOTATION_ELEMENT_TYPE :
buffer.append("annotation"); //$NON-NLS-1$
break;
case IDelta.INTERFACE_ELEMENT_TYPE :
buffer.append("interface"); //$NON-NLS-1$
break;
case IDelta.API_COMPONENT_ELEMENT_TYPE :
buffer.append("api component"); //$NON-NLS-1$
break;
case IDelta.API_PROFILE_ELEMENT_TYPE :
buffer.append("api profile"); //$NON-NLS-1$
break;
case IDelta.METHOD_ELEMENT_TYPE:
buffer.append("method"); //$NON-NLS-1$
break;
case IDelta.MEMBER_ELEMENT_TYPE :
buffer.append("member"); //$NON-NLS-1$
break;
case IDelta.CONSTRUCTOR_ELEMENT_TYPE :
buffer.append("constructor"); //$NON-NLS-1$
break;
case IDelta.ENUM_ELEMENT_TYPE :
buffer.append("enum"); //$NON-NLS-1$
break;
case IDelta.FIELD_ELEMENT_TYPE :
buffer.append("field"); //$NON-NLS-1$
break;
}
buffer.append(' ');
switch(delta.getKind()) {
case IDelta.ADDED :
buffer.append("added"); //$NON-NLS-1$
break;
case IDelta.REMOVED :
buffer.append("removed"); //$NON-NLS-1$
break;
case IDelta.CHANGED :
buffer.append("changed"); //$NON-NLS-1$
break;
default:
buffer.append("unknown kind"); //$NON-NLS-1$
break;
}
buffer.append(' ').append(getDeltaFlagsName(delta.getFlags())).append(' ').append(delta.getTypeName()).append("#").append(delta.getKey()); //$NON-NLS-1$
return String.valueOf(buffer);
}
/**
* Returns the {@link IDocument} for the specified {@link ICompilationUnit}
* @param cu
* @return the {@link IDocument} for the specified {@link ICompilationUnit}
* @throws CoreException
*/
public static IDocument getDocument(ICompilationUnit cu) throws CoreException {
if (cu.getOwner() == null) {
IFile file= (IFile) cu.getResource();
if (file.exists()) {
ITextFileBufferManager bufferManager= FileBuffers.getTextFileBufferManager();
IPath path= cu.getPath();
bufferManager.connect(path, LocationKind.IFILE, new NullProgressMonitor());
return bufferManager.getTextFileBuffer(path, LocationKind.IFILE).getDocument();
}
}
return new org.eclipse.jface.text.Document(cu.getSource());
}
/**
* Retrieve EE properties from the ee.file property.
* @param eeFileProperty the given ee.file property
*
* @return the corresponding properties or null if none
*/
public static Properties getEEProfile(File eeFileProperty) {
if (!eeFileProperty.exists()) {
return null;
}
EEVMType.clearProperties(eeFileProperty);
String ee = EEVMType.getProperty(EEVMType.PROP_CLASS_LIB_LEVEL, eeFileProperty);
if (ee == null) {
return null;
}
String profileName = ee + ".profile"; //$NON-NLS-1$
InputStream stream = Util.class.getResourceAsStream("profiles/" + profileName); //$NON-NLS-1$
if (stream != null) {
try {
Properties profile = new Properties();
profile.load(stream);
return profile;
} catch (IOException e) {
ApiPlugin.log(e);
} finally {
try {
stream.close();
} catch(IOException e) {
ApiPlugin.log(e);
}
}
}
return null;
}
/**
* Retrieve EE properties for the given ee name.
* @param eeName the given ee name
*
* @return the corresponding properties or null if none
*/
public static Properties getEEProfile(String eeName) {
if (eeName == null) {
return null;
}
String profileName = eeName + ".profile"; //$NON-NLS-1$
InputStream stream = Util.class.getResourceAsStream("profiles/" + profileName); //$NON-NLS-1$
if (stream != null) {
try {
Properties profile = new Properties();
profile.load(stream);
return profile;
} catch (IOException e) {
ApiPlugin.log(e);
} finally {
try {
stream.close();
} catch(IOException e) {
ApiPlugin.log(e);
}
}
}
return null;
}
/**
* Returns the number of fragments for the given version value, -1 if the format is unknown.
* The version is formed like: [optional plugin name] major.minor.micro.qualifier.
*
* @param version the given version value
* @return the number of fragments for the given version value or -1 if the format is unknown
* @throws IllegalArgumentException if version is null
*/
public static final int getFragmentNumber(String version) {
if (version == null) throw new IllegalArgumentException("The given version should not be null"); //$NON-NLS-1$
int index = version.indexOf(' ');
char[] charArray = version.toCharArray();
int length = charArray.length;
if (index + 1 >= length) {
return -1;
}
int counter = 1;
for (int i = index + 1; i < length; i++) {
switch(charArray[i]) {
case '0' :
case '1' :
case '2' :
case '3' :
case '4' :
case '5' :
case '6' :
case '7' :
case '8' :
case '9' :
continue;
case '.' :
counter++;
break;
default :
return -1;
}
}
return counter;
}
public static IMember getIMember(IDelta delta, IJavaProject javaProject) {
String typeName = delta.getTypeName();
if (typeName == null) return null;
IType type = null;
try {
type = javaProject.findType(typeName.replace('$', '.'));
} catch (JavaModelException e) {
// ignore
}
if (type == null) return null;
String key = delta.getKey();
switch(delta.getElementType()) {
case IDelta.FIELD_ELEMENT_TYPE : {
IField field = type.getField(key);
if (field.exists()) {
return field;
}
}
break;
case IDelta.CLASS_ELEMENT_TYPE :
case IDelta.ANNOTATION_ELEMENT_TYPE :
case IDelta.INTERFACE_ELEMENT_TYPE :
case IDelta.ENUM_ELEMENT_TYPE :
case IDelta.MEMBER_ELEMENT_TYPE :
// we report the marker on the type
switch(delta.getKind()) {
case IDelta.ADDED :
switch(delta.getFlags()) {
case IDelta.FIELD :
IField field = type.getField(key);
if (field.exists()) {
return field;
}
break;
case IDelta.METHOD :
case IDelta.CONSTRUCTOR :
int indexOf = key.indexOf('(');
if (indexOf == -1) {
return null;
}
int index = indexOf;
String selector = key.substring(0, index);
String descriptor = key.substring(index, key.length());
return getMethod(type, selector, descriptor);
case IDelta.TYPE_MEMBER :
IType type2 = type.getType(key);
if (type2.exists()) {
return type2;
}
}
}
return type;
case IDelta.METHOD_ELEMENT_TYPE :
case IDelta.CONSTRUCTOR_ELEMENT_TYPE : {
int indexOf = key.indexOf('(');
if (indexOf == -1) {
return null;
}
int index = indexOf;
String selector = key.substring(0, index);
String descriptor = key.substring(index, key.length());
return getMethod(type, selector, descriptor);
}
}
return null;
}
private static IMember getMethod(IType type, String selector, String descriptor) {
IMethod method = null;
String signature = descriptor.replace('/', '.');
String[] parameterTypes = Signature.getParameterTypes(signature);
try {
method = type.getMethod(selector, parameterTypes);
} catch (IllegalArgumentException e) {
ApiPlugin.log(e);
}
if (method == null) {
return null;
}
if (method.exists()) {
return method;
} else {
// try to check by selector
IMethod[] methods = null;
try {
methods = type.getMethods();
} catch (JavaModelException e) {
ApiPlugin.log(e);
return type;
}
List list = new ArrayList();
for (int i = 0, max = methods.length; i < max; i++) {
IMethod method2 = methods[i];
if (selector.equals(method2.getElementName())) {
list.add(method2);
}
}
switch(list.size()) {
case 0 :
return type;
case 1 :
return (IMember) list.get(0);
default:
// need to find a matching parameters
for (Iterator iterator = list.iterator(); iterator.hasNext(); ) {
IMethod method2 = (IMethod) iterator.next();
try {
if (Util.matchesSignatures(method2.getSignature(), signature)) {
return method2;
}
} catch (JavaModelException e) {
// ignore
}
}
}
}
return type;
}
/**
* Returns the given input stream as a byte array
* @param stream the stream to get as a byte array
* @param length the length to read from the stream or -1 for unknown
* @return the given input stream as a byte array
* @throws IOException
*/
public static byte[] getInputStreamAsByteArray(InputStream stream, int length) throws IOException {
byte[] contents;
if (length == -1) {
contents = new byte[0];
int contentsLength = 0;
int amountRead = -1;
do {
// read at least 8K
int amountRequested = Math.max(stream.available(), DEFAULT_READING_SIZE);
// resize contents if needed
if (contentsLength + amountRequested > contents.length) {
System.arraycopy(contents,
0,
contents = new byte[contentsLength + amountRequested],
0,
contentsLength);
}
// read as many bytes as possible
amountRead = stream.read(contents, contentsLength, amountRequested);
if (amountRead > 0) {
// remember length of contents
contentsLength += amountRead;
}
} while (amountRead != -1);
// resize contents if necessary
if (contentsLength < contents.length) {
System.arraycopy(contents, 0, contents = new byte[contentsLength], 0, contentsLength);
}
} else {
contents = new byte[length];
int len = 0;
int readSize = 0;
while ((readSize != -1) && (len != length)) {
// See PR 1FMS89U
// We record first the read size. In this case length is the actual
// read size.
len += readSize;
readSize = stream.read(contents, len, length - len);
}
}
return contents;
}
/**
* Returns the given input stream's contents as a character array.
* If a length is specified (i.e. if length != -1), this represents the number of bytes in the stream.
* Note the specified stream is not closed in this method
* @param stream the stream to get convert to the char array
* @param length the length of the input stream, or -1 if unknown
* @param encoding the encoding to use when reading the stream
* @return the given input stream's contents as a character array.
* @throws IOException if a problem occurred reading the stream.
*/
public static char[] getInputStreamAsCharArray(InputStream stream, int length, String encoding) throws IOException {
Charset charset = null;
try {
charset = Charset.forName(encoding);
} catch (IllegalCharsetNameException e) {
System.err.println("Illegal charset name : " + encoding); //$NON-NLS-1$
return null;
} catch(UnsupportedCharsetException e) {
System.err.println("Unsupported charset : " + encoding); //$NON-NLS-1$
return null;
}
CharsetDecoder charsetDecoder = charset.newDecoder();
charsetDecoder.onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE);
byte[] contents = getInputStreamAsByteArray(stream, length);
ByteBuffer byteBuffer = ByteBuffer.allocate(contents.length);
byteBuffer.put(contents);
byteBuffer.flip();
return charsetDecoder.decode(byteBuffer).array();
}
public static IResource getManifestFile(IProject currentProject) {
return currentProject.findMember("META-INF/MANIFEST.MF"); //$NON-NLS-1$
}
/**
* Returns a string representation of the category of an api problem
* @param category
* @return the string of the api problem category
*/
public static String getProblemCategory(int category) {
if(category == IApiProblem.CATEGORY_BINARY) {
return "BINARY"; //$NON-NLS-1$
}
if(category == IApiProblem.CATEGORY_SINCETAGS) {
return "SINCETAGS"; //$NON-NLS-1$
}
if(category == IApiProblem.CATEGORY_USAGE) {
return "USAGE"; //$NON-NLS-1$
}
if(category == IApiProblem.CATEGORY_VERSION) {
return "VERSION"; //$NON-NLS-1$
}
if(category == IApiProblem.CATEGORY_API_PROFILE) {
return "API_PROFILE"; //$NON-NLS-1$
}
return "UNKNOWN_CATEGORY"; //$NON-NLS-1$
}
/**
* Returns the string representation of the element kind of an
* {@link IApiProblem}, given its category
* @param category
* @param kind
* @return the string of the {@link IApiProblem} element kind
*/
public static String getProblemElementKind(int category, int kind) {
switch(category) {
case IApiProblem.CATEGORY_BINARY:
case IApiProblem.CATEGORY_SINCETAGS:{
return getDeltaElementType(kind);
}
case IApiProblem.CATEGORY_USAGE:
case IApiProblem.CATEGORY_VERSION:
case IApiProblem.CATEGORY_API_PROFILE: {
return getDescriptorKind(kind);
}
}
return "UNKNOWN_KIND"; //$NON-NLS-1$
}
/**
* Return the string representation of the flags for a problem
* @param category
* @param flags
* @return the string for the problem flags
*/
public static String getProblemFlagsName(int category, int flags) {
switch(category) {
case IApiProblem.CATEGORY_BINARY: {
return getDeltaFlagsName(flags);
}
case IApiProblem.CATEGORY_SINCETAGS:
case IApiProblem.CATEGORY_USAGE:
case IApiProblem.CATEGORY_VERSION:
case IApiProblem.CATEGORY_API_PROFILE: {
switch(flags) {
case IApiProblem.LEAK_EXTENDS: {
return "LEAK_EXTENDS"; //$NON-NLS-1$
}
case IApiProblem.LEAK_FIELD: {
return "LEAK_FIELD"; //$NON-NLS-1$
}
case IApiProblem.LEAK_IMPLEMENTS: {
return "LEAK_IMPLEMENTS"; //$NON-NLS-1$
}
case IApiProblem.LEAK_METHOD_PARAMETER: {
return "LEAK_METHOD_PARAMETER"; //$NON-NLS-1$
}
case IApiProblem.LEAK_RETURN_TYPE: {
return "LEAK_RETURN_TYPE"; //$NON-NLS-1$
}
}
}
}
return "UNKNOWN_KIND"; //$NON-NLS-1$
}
/**
* Returns the string representation of the kind of an
* {@link IApiProblem}, given its category
* @param category
* @param kind
* @return the string of the {@link IApiProblem} kind
*/
public static String getProblemKind(int category, int kind) {
switch(category) {
case IApiProblem.CATEGORY_BINARY: {
return getDeltaKindName(kind);
}
case IApiProblem.CATEGORY_SINCETAGS: {
return getTagsProblemKindName(kind);
}
case IApiProblem.CATEGORY_USAGE: {
return getUsageProblemKindName(kind);
}
case IApiProblem.CATEGORY_VERSION: {
return getVersionProblemKindName(kind);
}
case IApiProblem.CATEGORY_API_PROFILE: {
return getApiProfileProblemKindName(kind);
}
}
return "UNKNOWN_KIND"; //$NON-NLS-1$
}
/**
* Returns the string representation of the API profile problem kind
* @param kind
* @return the string of the API profile problem kind
*/
public static String getApiProfileProblemKindName(int kind) {
switch(kind) {
case IApiProblem.API_PROFILE_MISSING: {
return "API_PROFILE_MISSING"; //$NON-NLS-1$
}
}
return "UNKOWN_KIND"; //$NON-NLS-1$
}
/**
* Returns the string representation of the version problem kind.
* @param kind
* @return the string of the version API problem kind
*/
public static String getVersionProblemKindName(int kind) {
switch(kind) {
case IApiProblem.MINOR_VERSION_CHANGE: {
return "MINOR_VERSION_CHANGE"; //$NON-NLS-1$
}
case IApiProblem.MAJOR_VERSION_CHANGE: {
return "MAJOR_VERSION_CHANGE"; //$NON-NLS-1$
}
case IApiProblem.MAJOR_VERSION_CHANGE_NO_BREAKAGE: {
return "MAJOR_VERSION_CHANGE_NO_BREAKAGE"; //$NON-NLS-1$
}
}
return "UNKNOWN_KIND"; //$NON-NLS-1$
}
/**
* Returns the string representation of the kind of usage problem for
* an {@link IApiProblem} kind
* @param kind
* @return the string for the usage api problem kind
*/
public static String getUsageProblemKindName(int kind) {
switch(kind) {
case IApiProblem.ILLEGAL_EXTEND: {
return "ILLEGAL_EXTEND"; //$NON-NLS-1$
}
case IApiProblem.ILLEGAL_IMPLEMENT: {
return "ILLEGAL_IMPLEMENT"; //$NON-NLS-1$
}
case IApiProblem.ILLEGAL_INSTANTIATE: {
return "ILLEGAL_INSTANTIATE"; //$NON-NLS-1$
}
case IApiProblem.ILLEGAL_REFERENCE: {
return "ILLEGAL_REFERENCE"; //$NON-NLS-1$
}
case IApiProblem.ILLEGAL_OVERRIDE: {
return "ILLEGAL_OVERRIDE"; //$NON-NLS-1$
}
case IApiProblem.API_LEAK: {
return "API_LEAK"; //$NON-NLS-1$
}
}
return "UNKNOWN_KIND"; //$NON-NLS-1$
}
/**
* Returns the string representation of the kind of since tab
* api problem
* @param kind
* @return the string for the since tag api problem kind
*/
public static String getTagsProblemKindName(int kind) {
switch(kind) {
case IApiProblem.SINCE_TAG_INVALID: {
return "INVALID_SINCE_TAGS"; //$NON-NLS-1$
}
case IApiProblem.SINCE_TAG_MALFORMED: {
return "MALFORMED_SINCE_TAGS"; //$NON-NLS-1$
}
case IApiProblem.SINCE_TAG_MISSING: {
return "MISSING_SINCE_TAGS"; //$NON-NLS-1$
}
}
return "UNKNOWN_KIND"; //$NON-NLS-1$
}
/**
* Creates a method signature from a specified {@link MethodDeclaration}
* @param node
* @return the signature for the given method node or <code>null</code>
*/
public static String getMethodSignatureFromNode(MethodDeclaration node) {
if(!node.isConstructor()) {
List params = node.parameters();
List rparams = new ArrayList(params.size());
SingleVariableDeclaration param = null;
String pname = null;
for(Iterator iter = params.iterator(); iter.hasNext();) {
param = (SingleVariableDeclaration) iter.next();
pname = Util.getTypeSignature(param.getType());
if(pname != null) {
rparams.add(pname);
}
}
if(rparams.size() == params.size()) {
Type returnType = node.getReturnType2();
if (returnType != null) {
String rtype = Util.getTypeSignature(returnType);
if(rtype != null) {
return Signature.createMethodSignature((String[]) rparams.toArray(new String[rparams.size()]), rtype);
}
}
}
}
return null;
}
/**
* The type name is dot-separated
* @param typeName the given type name
* @return the package name for the given type name or an empty string if none
*/
public static String getPackageName(String typeName) {
int index = typeName.lastIndexOf('.');
return index == -1 ? DEFAULT_PACKAGE_NAME : typeName.substring(0, index);
}
/**
* Returns the string representation of an element descriptor type or <code>null</code>
* if the kind is unknown
* @param kind
* @return the string of the kind or <code>null</code>
*/
public static String getDescriptorKind(int kind) {
switch(kind) {
case IElementDescriptor.T_PACKAGE: {
return "PACKAGE"; //$NON-NLS-1$
}
case IElementDescriptor.T_ARRAY_TYPE: {
return "ARRAY_TYPE"; //$NON-NLS-1$
}
case IElementDescriptor.T_FIELD: {
return "FIELD"; //$NON-NLS-1$
}
case IElementDescriptor.T_METHOD: {
return "METHOD"; //$NON-NLS-1$
}
case IElementDescriptor.T_PRIMITIVE_TYPE: {
return "PRIMITIVE_TYPE"; //$NON-NLS-1$
}
case IElementDescriptor.T_REFERENCE_TYPE: {
return "REFERENCE_TYPE"; //$NON-NLS-1$
}
case IElementDescriptor.T_RESOURCE: {
return "RESOURCE"; //$NON-NLS-1$
}
}
return "UNKOWN_ELEMENT_KIND"; //$NON-NLS-1$
}
/**
* Returns the string representation of the specified visibility modifier or <code>null</code>
* if the kind is unknown
* @param kind
* @return
*/
public static String getVisibilityKind(int kind) {
switch(kind) {
case VisibilityModifiers.ALL_VISIBILITIES: {
return "ALL_VISIBILITIES"; //$NON-NLS-1$
}
case VisibilityModifiers.API: {
return "API"; //$NON-NLS-1$
}
case VisibilityModifiers.PRIVATE: {
return "PRIVATE"; //$NON-NLS-1$
}
case VisibilityModifiers.PRIVATE_PERMISSIBLE: {
return "PRIVATE_PERMISSIBLE"; //$NON-NLS-1$
}
case VisibilityModifiers.SPI: {
return "SPI"; //$NON-NLS-1$
}
}
return null;
}
/**
* Returns the string representation of the specified restriction kind or <code>null</code>
* if the kind is unknown
* @param kind
* @return the string for the kind or <code>null</code>
*/
public static String getRestrictionKind(int kind) {
switch(kind) {
case RestrictionModifiers.ALL_RESTRICTIONS: {
return "ALL_RESTRICTIONS"; //$NON-NLS-1$
}
case RestrictionModifiers.NO_EXTEND: {
return "NO_EXTEND"; //$NON-NLS-1$
}
case RestrictionModifiers.NO_IMPLEMENT: {
return "NO_IMPLEMENT"; //$NON-NLS-1$
}
case RestrictionModifiers.NO_INSTANTIATE: {
return "NO_INSTANTIATE"; //$NON-NLS-1$
}
case RestrictionModifiers.NO_REFERENCE: {
return "NO_REFERENCE"; //$NON-NLS-1$
}
case RestrictionModifiers.NO_RESTRICTIONS: {
return "NO_RESTRICTIONS"; //$NON-NLS-1$
}
}
return "UNKNOWN_KIND"; //$NON-NLS-1$
}
/**
* Returns the string representation for the given reference kind
* @param kind
* @return the string for the reference kind
*/
public static final String getReferenceKind(int kind) {
switch(kind) {
case ReferenceModifiers.REF_EXTENDS: {
return "EXTENDS"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_IMPLEMENTS: {
return "IMPLEMENTS"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_SPECIALMETHOD: {
return "INVOKED_SPECIAL"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_STATICMETHOD: {
return "INVOKED_STATIC"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_PUTFIELD: {
return "PUT_FIELD"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_PUTSTATIC: {
return "PUT_STATIC_FIELD"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_FIELDDECL: {
return "DECLARED_FIELD"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_PARAMETERIZED_TYPEDECL: {
return "DECLARED_PARAMETERIZED_TYPE"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_PARAMETERIZED_FIELDDECL: {
return "DECLARED_PARAMETERIZED_FIELD"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_PARAMETERIZED_METHODDECL: {
return "DECLARED_PARAMETERIZED_METHOD"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_PARAMETER: {
return "PARAMETER"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_LOCALVARIABLEDECL: {
return "LOCAL_VAR_DECLARED"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_PARAMETERIZED_VARIABLE: {
return "DECLARED_PARAMETERIZED_VARIABLE"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_THROWS: {
return "THROWS"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_CHECKCAST: {
return "CASTS"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_ARRAYALLOC: {
return "ALLOCATES_ARRAY"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_CATCHEXCEPTION: {
return "CATCHES_EXCEPTION"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_GETFIELD: {
return "GETS_FIELD"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_GETSTATIC: {
return "GETS_STATIC_FIELD"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_INSTANCEOF: {
return "INSTANCEOF"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_INTERFACEMETHOD: {
return "INTERFACE_METHOD"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_CONSTRUCTORMETHOD: {
return "CONSTRUCTOR_METHOD"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_LOCALVARIABLE: {
return "LOCAL_VARIABLE"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_PASSEDPARAMETER: {
return "PASSED_PARAMETER"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_RETURNTYPE: {
return "RETURN_TYPE"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_VIRTUALMETHOD: {
return "VIRTUAL_METHOD"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_CONSTANTPOOL: {
return "CONSTANT_POOL"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_INSTANTIATE: {
return "INSTANTIATION"; //$NON-NLS-1$
}
case ReferenceModifiers.REF_OVERRIDE : {
return "OVERRIDE"; //$NON-NLS-1$
}
}
return null;
}
/**
* Returns a reference type for the given fully qualified type name.
*
* @param fullyQualifiedName type name
* @return reference type
*/
public static IReferenceTypeDescriptor getType(String fullyQualifiedName) {
int index = fullyQualifiedName.lastIndexOf('.');
String pkg = index == -1 ? DEFAULT_PACKAGE_NAME : fullyQualifiedName.substring(0, index);
String type = index == -1 ? fullyQualifiedName : fullyQualifiedName.substring(index + 1);
return Factory.packageDescriptor(pkg).getType(type);
}
/**
* Returns a reference type for the given fully qualified type name with the
* given modifiers
*
* @param fullyQualifiedName type name
* @param modifiers access flags as defined by {@link Flags}
* @return reference type
*/
public static IReferenceTypeDescriptor getType(String fullyQualifiedName, int modifiers) {
int index = fullyQualifiedName.lastIndexOf('.');
String pkg = index == -1 ? DEFAULT_PACKAGE_NAME : fullyQualifiedName.substring(0, index);
String type = index == -1 ? fullyQualifiedName : fullyQualifiedName.substring(index + 1);
return Factory.packageDescriptor(pkg).getType(type, modifiers);
}
/**
* Returns the simple name of the type, by stripping off the last '.' segment and returning it.
* This method assumes that qualified type names are '.' separated. If the type specified is a package
* than an empty string is returned.
* @param qualifiedname the fully qualified name of a type, '.' separated (e.g. a.b.c.Type)
* @return the simple name from the qualified name. For example if the qualified name is a.b.c.Type this method
* will return Type (stripping off the package qualification)
*/
public static String getTypeName(String qualifiedname) {
int idx = qualifiedname.lastIndexOf('.');
idx++;
if(idx > 0) {
return qualifiedname.substring(idx, qualifiedname.length());
}
// default package
return qualifiedname;
}
/**
* Processes the signature for the given {@link Type}
* @param type the type to process
* @return the signature for the type or <code>null</code> if one could not be
* derived
*/
public static String getTypeSignature(Type type) {
switch(type.getNodeType()) {
case ASTNode.SIMPLE_TYPE: {
return Signature.createTypeSignature(((SimpleType) type).getName().getFullyQualifiedName(), false);
}
case ASTNode.QUALIFIED_TYPE: {
return Signature.createTypeSignature(((QualifiedType)type).getName().getFullyQualifiedName(), false);
}
case ASTNode.ARRAY_TYPE: {
ArrayType a = (ArrayType) type;
return Signature.createArraySignature(getTypeSignature(a.getElementType()), a.getDimensions());
}
case ASTNode.PARAMETERIZED_TYPE: {
//we don't need to care about the other scoping types only the base type
return getTypeSignature(((ParameterizedType) type).getType());
}
case ASTNode.PRIMITIVE_TYPE: {
return Signature.createTypeSignature(((PrimitiveType)type).getPrimitiveTypeCode().toString(), false);
}
}
return null;
}
public static boolean isAbstract(int accessFlags) {
return (accessFlags & Opcodes.ACC_ABSTRACT) != 0;
}
public static boolean isAnnotation(int accessFlags) {
return (accessFlags & Opcodes.ACC_ANNOTATION) != 0;
}
/**
* Returns if the specified file name is an archive name. A name is
* considered to be an archive name if it ends with either '.zip' or '.jar'
*
* @param fileName
* @return true if the file name is an archive name false otherwise
*/
public static boolean isArchive(String fileName) {
String normalizedFileName = fileName.toLowerCase();
return normalizedFileName.endsWith(".zip") || normalizedFileName.endsWith(".jar"); //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Returns if the flags are for a bridge
* @param accessFlags
* @return
*/
public static boolean isBridge(int accessFlags) {
return (accessFlags & Opcodes.ACC_BRIDGE) != 0;
}
/**
* Returns if the flags are for a class
* @param accessFlags
* @return
*/
public static boolean isClass(int accessFlags) {
return (accessFlags & (Opcodes.ACC_ENUM | Opcodes.ACC_ANNOTATION | Opcodes.ACC_INTERFACE)) == 0;
}
/**
* Returns if the specified file name is for a class file. A name is
* considered to be a class file if it ends in '.class'
*
* @param fileName
* @return true if the name is for a class file false otherwise
*/
public static boolean isClassFile(String fileName) {
return fileName.toLowerCase().endsWith(DOT_CLASS_SUFFIX);
}
public static boolean isDefault(int accessFlags) {
// none of the private, protected or public bit is set
return (accessFlags & (Opcodes.ACC_PRIVATE
| Opcodes.ACC_PROTECTED
| Opcodes.ACC_PUBLIC)) == 0;
}
public static boolean isDeprecated(int accessFlags) {
return (accessFlags & Opcodes.ACC_DEPRECATED) != 0;
}
public static boolean isEnum(int accessFlags) {
return (accessFlags & Opcodes.ACC_ENUM) != 0;
}
public static boolean isFinal(int accessFlags) {
return (accessFlags & Opcodes.ACC_FINAL) != 0;
}
public static final boolean isGreatherVersion(String versionToBeChecked, String referenceVersion) {
SinceTagVersion sinceTagVersion1 = null;
SinceTagVersion sinceTagVersion2 = null;
try {
sinceTagVersion1 = new SinceTagVersion(versionToBeChecked);
sinceTagVersion2 = new SinceTagVersion(referenceVersion);
} catch (IllegalArgumentException e) {
// We cannot compare the two versions as their format is unknown
// TODO (olivier) should we report these as malformed tags?
return false;
}
Version version1 = sinceTagVersion1.getVersion();
Version version2 = sinceTagVersion2.getVersion();
if (version1.getMajor() > version2.getMajor()) {
return true;
}
if (version1.getMinor() > version2.getMinor()) {
return true;
}
if (version1.getMicro() > version2.getMicro()) {
return true;
}
String qualifier1 = version1.getQualifier();
String qualifier2 = version2.getQualifier();
if (qualifier1 == null) {
return false;
} else if (qualifier2 == null) {
return true;
} else {
return qualifier1.compareTo(qualifier2) > 0;
}
}
public static final boolean isDifferentVersion(String versionToBeChecked, String referenceVersion) {
SinceTagVersion sinceTagVersion1 = null;
SinceTagVersion sinceTagVersion2 = null;
try {
sinceTagVersion1 = new SinceTagVersion(versionToBeChecked);
sinceTagVersion2 = new SinceTagVersion(referenceVersion);
} catch (IllegalArgumentException e) {
// We cannot compare the two versions as their format is unknown
// TODO (olivier) should we report these as malformed tags?
return false;
}
Version version1 = sinceTagVersion1.getVersion();
Version version2 = sinceTagVersion2.getVersion();
if (version1.getMajor() != version2.getMajor()) {
return true;
}
if (version1.getMinor() != version2.getMinor()) {
return true;
}
if (version1.getMicro() != version2.getMicro()) {
return true;
}
return false;
}
public static boolean isInterface(int accessFlags) {
return (accessFlags & Opcodes.ACC_INTERFACE) != 0;
}
/**
* Returns if the specified file name is for a java source file. A name is
* considered to be a java source file if it ends in '.java'
*
* @param fileName
* @return true if the name is for a java source file, false otherwise
*/
public static boolean isJavaFileName(String fileName) {
return fileName.toLowerCase().endsWith(".java"); //$NON-NLS-1$
}
/**
* Returns if the given name is {@link java.lang.Object}
* @param name
* @return true if the name is java.lang.Object, false otherwise
*/
public static boolean isJavaLangObject(String name) {
return name != null && name.equals(JAVA_LANG_OBJECT);
}
/**
* Return if the name is {@link java.lang.RuntimeException}
* @param name
* @return true if the name is java.lang.RuntimeException, false otherwise
*/
public static boolean isJavaLangRuntimeException(String name) {
return name != null && name.equals(JAVA_LANG_RUNTIMEEXCEPTION);
}
public static boolean isNative(int accessFlags) {
return (accessFlags & Opcodes.ACC_NATIVE) != 0;
}
public static boolean isPrivate(int accessFlags) {
return (accessFlags & Opcodes.ACC_PRIVATE) != 0;
}
public static boolean isProtected(int accessFlags) {
return (accessFlags & Opcodes.ACC_PROTECTED) != 0;
}
public static boolean isPublic(int accessFlags) {
return (accessFlags & Opcodes.ACC_PUBLIC) != 0;
}
public static boolean isStatic(int accessFlags) {
return (accessFlags & Opcodes.ACC_STATIC) != 0;
}
public static boolean isStrict(int accessFlags) {
return (accessFlags & Opcodes.ACC_STRICT) != 0;
}
public static boolean isSynchronized(int accessFlags) {
return (accessFlags & Opcodes.ACC_SYNCHRONIZED) != 0;
}
public static boolean isSynthetic(int accessFlags) {
return (accessFlags & Opcodes.ACC_SYNTHETIC) != 0;
}
public static boolean isTransient(int accessFlags) {
return (accessFlags & Opcodes.ACC_TRANSIENT) != 0;
}
public static boolean isVarargs(int accessFlags) {
return (accessFlags & Opcodes.ACC_VARARGS) != 0;
}
public static boolean isVolatile(int accessFlags) {
return (accessFlags & Opcodes.ACC_VOLATILE) != 0;
}
public static boolean isVisible(IDelta delta) {
int modifiers = delta.getModifiers();
return isProtected(modifiers) || isPublic(modifiers);
}
/**
* Returns a new XML document.
*
* @return document
* @throws CoreException if unable to create a new document
*/
public static Document newDocument() throws CoreException {
DocumentBuilderFactory dfactory= DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = null;
try {
docBuilder = dfactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
abort("Unable to create new XML document.", e); //$NON-NLS-1$
}
Document doc= docBuilder.newDocument();
return doc;
}
/**
* Parses the given string representing an XML document, returning its
* root element.
*
* @param document XML document as a string
* @return the document's root element
* @throws CoreException if unable to parse the document
*/
public static Element parseDocument(String document) throws CoreException {
Element root = null;
InputStream stream = null;
try{
DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
parser.setErrorHandler(new DefaultHandler());
stream = new ByteArrayInputStream(document.getBytes());
root = parser.parse(stream).getDocumentElement();
} catch (ParserConfigurationException e) {
abort("Unable to parse XML document.", e); //$NON-NLS-1$
} catch (FactoryConfigurationError e) {
abort("Unable to parse XML document.", e); //$NON-NLS-1$
} catch (SAXException e) {
abort("Unable to parse XML document.", e); //$NON-NLS-1$
} catch (IOException e) {
abort("Unable to parse XML document.", e); //$NON-NLS-1$
} finally {
try{
if (stream != null) {
stream.close();
}
} catch(IOException e) {
abort("Unable to parse XML document.", e); //$NON-NLS-1$
}
}
return root;
}
/**
* Save the given contents into the given file. The file parent folder must exist.
*
* @param file the given file target
* @param contents the given contents
* @throws IOException if an IOException occurs while saving the file
*/
public static void saveFile(File file, String contents) throws IOException {
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(file));
writer.write(contents);
writer.flush();
} finally {
if (writer != null) {
try {
writer.close();
} catch(IOException e) {
// ignore
}
}
}
}
/**
* Returns the given string as an {@link InputStream}
* @param string the string to convert
* @return the {@link InputStream} for the given string
*/
public static InputStream getInputStreamFromString(String string) {
try {
return new ByteArrayInputStream(string.getBytes(IApiCoreConstants.UTF_8));
}
catch(UnsupportedEncodingException uee) {
ApiPlugin.log(uee);
}
return null;
}
/**
* Serializes the given XML document into a UTF-8 string.
*
* @param document XML document to serialize
* @return a string representing the given document
* @throws CoreException if unable to serialize the document
*/
public static String serializeDocument(Document document) throws CoreException {
try {
ByteArrayOutputStream s = new ByteArrayOutputStream();
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount","4"); //$NON-NLS-1$ //$NON-NLS-2$
DOMSource source = new DOMSource(document);
StreamResult outputTarget = new StreamResult(s);
transformer.transform(source, outputTarget);
return s.toString(IApiCoreConstants.UTF_8);
} catch (TransformerException e) {
abort("Unable to serialize XML document.", e); //$NON-NLS-1$
} catch (IOException e) {
abort("Unable to serialize XML document.",e); //$NON-NLS-1$
}
return null;
}
/**
* Unzip the contents of the given zip in the given directory (create it if it doesn't exist)
*/
public static void unzip(String zipPath, String destDirPath) throws IOException {
InputStream zipIn = new FileInputStream(zipPath);
byte[] buf = new byte[8192];
File destDir = new File(destDirPath);
ZipInputStream zis = new ZipInputStream(zipIn);
FileOutputStream fos = null;
try {
ZipEntry zEntry;
while ((zEntry = zis.getNextEntry()) != null) {
// if it is empty directory, create it
if (zEntry.isDirectory()) {
new File(destDir, zEntry.getName()).mkdirs();
continue;
}
// if it is a file, extract it
String filePath = zEntry.getName();
int lastSeparator = filePath.lastIndexOf("/"); //$NON-NLS-1$
String fileDir = ""; //$NON-NLS-1$
if (lastSeparator >= 0) {
fileDir = filePath.substring(0, lastSeparator);
}
//create directory for a file
new File(destDir, fileDir).mkdirs();
//write file
File outFile = new File(destDir, filePath);
fos = new FileOutputStream(outFile);
int n = 0;
while ((n = zis.read(buf)) >= 0) {
fos.write(buf, 0, n);
}
fos.close();
}
} catch (IOException ioe) {
if (fos != null) {
try {
fos.close();
} catch (IOException ioe2) {
}
}
} finally {
try {
zipIn.close();
zis.close();
} catch (IOException ioe) {
}
}
}
/**
* Gets the .ee file supplied to run tests based on system
* property.
*
* @return
*/
public static File getEEDescriptionFile() {
// generate a fake 1.5 ee file
File fakeEEFile = null;
PrintWriter writer = null;
try {
fakeEEFile = File.createTempFile("eefile", ".ee"); //$NON-NLS-1$ //$NON-NLS-2$
writer = new PrintWriter(new BufferedWriter(new FileWriter(fakeEEFile)));
writer.print("-Djava.home="); //$NON-NLS-1$
writer.println(System.getProperty("java.home")); //$NON-NLS-1$
writer.print("-Dee.bootclasspath="); //$NON-NLS-1$
writer.println(getJavaClassLibsAsString());
writer.println("-Dee.language.level=1.6"); //$NON-NLS-1$
writer.println("-Dee.class.library.level=JavaSE-1.6"); //$NON-NLS-1$
writer.flush();
} catch (IOException e) {
// ignore
} finally {
if (writer != null) {
writer.close();
}
}
return fakeEEFile;
}
/**
* @return a string representation of all of the libraries from the bootpath
* of the current default system VM.
*/
public static String getJavaClassLibsAsString() {
String[] libs = Util.getJavaClassLibs();
StringBuffer buffer = new StringBuffer();
for (int i = 0, max = libs.length; i < max; i++) {
if (i > 0) {
buffer.append(File.pathSeparatorChar);
}
buffer.append(libs[i]);
}
return String.valueOf(buffer);
}
/**
* @return an array of the library names from the bootpath of the current default system VM
*/
public static String[] getJavaClassLibs() {
// check bootclasspath properties for Sun, JRockit and Harmony VMs
String bootclasspathProperty = System.getProperty("sun.boot.class.path"); //$NON-NLS-1$
if ((bootclasspathProperty == null) || (bootclasspathProperty.length() == 0)) {
// IBM J9 VMs
bootclasspathProperty = System.getProperty("vm.boot.class.path"); //$NON-NLS-1$
if ((bootclasspathProperty == null) || (bootclasspathProperty.length() == 0)) {
// Harmony using IBM VME
bootclasspathProperty = System.getProperty("org.apache.harmony.boot.class.path"); //$NON-NLS-1$
}
}
String[] jars = null;
if ((bootclasspathProperty != null) && (bootclasspathProperty.length() != 0)) {
StringTokenizer tokenizer = new StringTokenizer(bootclasspathProperty, File.pathSeparator);
final int size = tokenizer.countTokens();
jars = new String[size];
int i = 0;
while (tokenizer.hasMoreTokens()) {
final String fileName = toNativePath(tokenizer.nextToken());
if (new File(fileName).exists()) {
jars[i] = fileName;
i++;
}
}
if (size != i) {
// resize
System.arraycopy(jars, 0, (jars = new String[i]), 0, i);
}
} else {
String jreDir = System.getProperty("java.home"); //$NON-NLS-1$
final String osName = System.getProperty("os.name"); //$NON-NLS-1$
if (jreDir == null) {
return new String[] {};
}
if (osName.startsWith("Mac")) { //$NON-NLS-1$
return new String[] {
toNativePath(jreDir + "/../Classes/classes.jar") //$NON-NLS-1$
};
}
final String vmName = System.getProperty("java.vm.name"); //$NON-NLS-1$
if ("J9".equals(vmName)) { //$NON-NLS-1$
return new String[] {
toNativePath(jreDir + "/lib/jclMax/classes.zip") //$NON-NLS-1$
};
}
String[] jarsNames = null;
ArrayList paths = new ArrayList();
if ("DRLVM".equals(vmName)) { //$NON-NLS-1$
FilenameFilter jarFilter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".jar") & !name.endsWith("-src.jar"); //$NON-NLS-1$//$NON-NLS-2$
}
};
jarsNames = new File(jreDir + "/lib/boot/").list(jarFilter); //$NON-NLS-1$
addJarEntries(jreDir + "/lib/boot/", jarsNames, paths); //$NON-NLS-1$
} else {
jarsNames = new String[] {
"/lib/vm.jar", //$NON-NLS-1$
"/lib/rt.jar", //$NON-NLS-1$
"/lib/core.jar", //$NON-NLS-1$
"/lib/security.jar", //$NON-NLS-1$
"/lib/xml.jar", //$NON-NLS-1$
"/lib/graphics.jar" //$NON-NLS-1$
};
addJarEntries(jreDir, jarsNames, paths);
}
jars = new String[paths.size()];
paths.toArray(jars);
}
return jars;
}
/**
* Makes the given path a path using native path separators as returned by File.getPath()
* and trimming any extra slash.
*/
public static String toNativePath(String path) {
String nativePath = path.replace('\\', File.separatorChar).replace('/', File.separatorChar);
return
nativePath.endsWith("/") || nativePath.endsWith("\\") ? //$NON-NLS-1$ //$NON-NLS-2$
nativePath.substring(0, nativePath.length() - 1) :
nativePath;
}
private static void addJarEntries(String jreDir, String[] jarNames, ArrayList paths) {
for (int i = 0, max = jarNames.length; i < max; i++) {
final String currentName = jreDir + jarNames[i];
File f = new File(currentName);
if (f.exists()) {
paths.add(toNativePath(currentName));
}
}
}
/**
* Delete a file or directory and insure that the file is no longer present
* on file system. In case of directory, delete all the hierarchy underneath.
*
* @param file The file or directory to delete
* @return true iff the file was really delete, false otherwise
*/
public static boolean delete(File file) {
// flush all directory content
if (file.isDirectory()) {
flushDirectoryContent(file);
}
// remove file
file.delete();
if (isFileDeleted(file)) {
return true;
}
return waitUntilFileDeleted(file);
}
public static void flushDirectoryContent(File dir) {
File[] files = dir.listFiles();
if (files == null) return;
for (int i = 0, max = files.length; i < max; i++) {
delete(files[i]);
}
}
/**
* Wait until the file is _really_ deleted on file system.
*
* @param file Deleted file
* @return true if the file was finally deleted, false otherwise
*/
private static boolean waitUntilFileDeleted(File file) {
int count = 0;
int delay = 10; // ms
int maxRetry = DELETE_MAX_WAIT / delay;
int time = 0;
while (count < maxRetry) {
try {
count++;
Thread.sleep(delay);
time += delay;
if (time > DELETE_MAX_TIME) DELETE_MAX_TIME = time;
if (DELETE_DEBUG) System.out.print('.');
if (file.exists()) {
if (file.delete()) {
// SUCCESS
return true;
}
}
if (isFileDeleted(file)) {
// SUCCESS
return true;
}
// Increment waiting delay exponentially
if (count >= 10 && delay <= 100) {
count = 1;
delay *= 10;
maxRetry = DELETE_MAX_WAIT / delay;
if ((DELETE_MAX_WAIT%delay) != 0) {
maxRetry++;
}
}
}
catch (InterruptedException ie) {
break; // end loop
}
}
System.err.println();
System.err.println(" !!! ERROR: "+file+" was never deleted even after having waited "+DELETE_MAX_TIME+"ms!!!"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
System.err.println();
return false;
}
/**
* Returns whether a file is really deleted or not.
* Does not only rely on {@link File#exists()} method but also
* look if it's not in its parent children {@link #getParentChildFile(File)}.
*
* @param file The file to test if deleted
* @return true if the file does not exist and was not found in its parent children.
*/
public static boolean isFileDeleted(File file) {
return !file.exists() && getParentChildFile(file) == null;
}
/**
* Returns the parent's child file matching the given file or null if not found.
*
* @param file The searched file in parent
* @return The parent's child matching the given file or null if not found.
*/
private static File getParentChildFile(File file) {
File parent = file.getParentFile();
if (parent == null || !parent.exists()) return null;
File[] files = parent.listFiles();
int length = files==null ? 0 : files.length;
if (length > 0) {
for (int i=0; i<length; i++) {
if (files[i] == file) {
return files[i];
} else if (files[i].equals(file)) {
return files[i];
} else if (files[i].getPath().equals(file.getPath())) {
return files[i];
}
}
}
return null;
}
public static boolean matchesSignatures(String signature, String signature2) {
if (!matches(Signature.getReturnType(signature), Signature.getReturnType(signature2))) {
return false;
}
String[] parameterTypes = Signature.getParameterTypes(signature);
String[] parameterTypes2 = Signature.getParameterTypes(signature2);
int length = parameterTypes.length;
int length2 = parameterTypes2.length;
if (length != length2) return false;
for (int i = 0; i < length2; i++) {
if (!matches(parameterTypes[i], parameterTypes2[i])) {
return false;
}
}
return true;
}
private static boolean matches(String type, String type2) {
if (type.length() == 1) {
if (type2.length() != 1) {
return false;
}
return type.charAt(0) == type2.charAt(0);
} else if (type2.length() == 1) {
return false;
}
char[] typeChars = type.toCharArray();
char[] type2Chars = type2.toCharArray();
// return types are reference types
if (typeChars[0] == Signature.C_ARRAY) {
// array type
if (type2Chars[0] != Signature.C_ARRAY) {
// not an array type
return false;
}
// check array types
// get type1 dimensions
int dims1 = Signature.getArrayCount(typeChars);
if (dims1 != Signature.getArrayCount(type2Chars)) {
return false;
}
return matches(CharOperation.subarray(typeChars, dims1, typeChars.length),
CharOperation.subarray(type2Chars, dims1, type2Chars.length));
}
if (type2.charAt(0) == Signature.C_ARRAY) {
// an array type
return false;
}
// check reference types
return matches(typeChars, type2Chars);
}
private static boolean matches(char[] type, char[] type2) {
char[] typeName = Signature.toCharArray(type);
char[] typeName2 = Signature.toCharArray(type2);
if (CharOperation.lastIndexOf(Signature.C_DOLLAR, typeName2) == -1) {
// no member type
int index = CharOperation.indexOf(typeName, typeName2, true);
return index != -1 && ((index + typeName.length) == typeName2.length);
}
// member type
int index = CharOperation.indexOf(typeName, typeName2, true);
if (index != -1 && ((index + typeName.length) == typeName2.length)) {
return true;
}
int dotIndex = CharOperation.lastIndexOf(Signature.C_DOT, typeName);
if (dotIndex == -1) {
return false;
}
typeName[dotIndex] = Signature.C_DOLLAR;
index = CharOperation.indexOf(typeName, typeName2, true);
return index != -1 && ((index + typeName.length) == typeName2.length);
}
public static Set convertAsSet(String[] values) {
Set set = new HashSet();
if (values != null && values.length != 0) {
for (int i = 0, max = values.length; i < max; i++) {
set.add(values[i]);
}
}
return set;
}
}