blob: aa81d957b905609d85504b94cac1057ed24ca93e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2017 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.debug.ui.launcher;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IOrdinaryClassFile;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.internal.debug.core.JavaDebugUtils;
import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.osgi.util.NLS;
public class AppletLaunchConfigurationUtils {
/**
* Throws a core exception with an error status object built from
* the given message, lower level exception, and error code.
*
* @param message the status message
* @param exception lower level exception associated with the
* error, or <code>null</code> if none
* @param code error code
*/
public static void abort(String message, Throwable exception, int code)
throws CoreException {
throw new CoreException(
new Status(
IStatus.ERROR,
JDIDebugUIPlugin.getUniqueIdentifier(),
code,
message,
exception));
}
/**
* Return the <code>IType</code> referenced by the specified name and contained in
* the specified project or throw a <code>CoreException</code> whose message explains why
* this couldn't be done.
*/
public static IType getMainType(String mainTypeName, IJavaProject javaProject) throws CoreException {
if ((mainTypeName == null) || (mainTypeName.trim().length() < 1)) {
abort(LauncherMessages.appletlauncher_utils_error_main_type_not_specified, null, IJavaLaunchConfigurationConstants.ERR_UNSPECIFIED_MAIN_TYPE);
}
IType mainType = null;
try {
mainType = findType(javaProject, mainTypeName);
} catch (JavaModelException jme) {
}
if (mainType == null) {
abort(NLS.bind(LauncherMessages.appletlauncher_utils_error_main_type_does_not_exist, new String[] {mainTypeName, javaProject.getElementName()}), null, IJavaLaunchConfigurationConstants.ERR_UNSPECIFIED_MAIN_TYPE);
}
return mainType;
}
/**
* Find the specified (fully-qualified) type name in the specified java project.
*/
public static IType findType(IJavaProject javaProject, String mainTypeName) throws CoreException {
IJavaElement javaElement= JavaDebugUtils.findElement(mainTypeName, javaProject);
if (javaElement == null) {
return null;
} else if (javaElement instanceof IType) {
return (IType)javaElement;
} else if (javaElement.getElementType() == IJavaElement.COMPILATION_UNIT) {
String simpleName= Signature.getSimpleName(mainTypeName);
return ((ICompilationUnit) javaElement).getType(simpleName);
} else if (javaElement.getElementType() == IJavaElement.CLASS_FILE && javaElement instanceof IOrdinaryClassFile) {
return ((IOrdinaryClassFile) javaElement).getType();
}
return null;
}
/**
*
*/
public static Set<IType> collectAppletTypesInProject(IProgressMonitor monitor, IJavaProject project) {
IType[] types;
HashSet<IType> result = new HashSet<>(5);
try {
IType javaLangApplet = AppletLaunchConfigurationUtils.getMainType("java.applet.Applet", project); //$NON-NLS-1$
ITypeHierarchy hierarchy = javaLangApplet.newTypeHierarchy(project, new SubProgressMonitor(monitor, 1));
types = hierarchy.getAllSubtypes(javaLangApplet);
int length = types.length;
if (length != 0) {
for (int i = 0; i < length; i++) {
if (!types[i].isBinary()) {
result.add(types[i]);
}
}
}
} catch(JavaModelException jme) {
} catch(CoreException e) {
}
monitor.done();
return result;
}
public static void collectTypes(Object element, IProgressMonitor monitor, Set<Object> result) throws JavaModelException/*, InvocationTargetException*/ {
element= computeScope(element);
while(element instanceof IMember) {
if(element instanceof IType) {
if (isSubclassOfApplet(monitor, (IType)element)) {
result.add(element);
monitor.done();
return;
}
}
element= ((IJavaElement)element).getParent();
}
if (element instanceof ICompilationUnit) {
ICompilationUnit cu= (ICompilationUnit)element;
for (IType type : cu.getAllTypes()) {
if (isSubclassOfApplet(monitor, type)) {
result.add(type);
}
}
} else if (element instanceof IOrdinaryClassFile) {
IType type = ((IOrdinaryClassFile) element).getType();
if (isSubclassOfApplet(monitor, type)) {
result.add(type);
}
} else if (element instanceof IJavaElement) {
IJavaElement parent = (IJavaElement) element;
List<IType> found= searchSubclassesOfApplet(monitor, (IJavaElement)element);
// filter within the parent element
Iterator<IType> iterator = found.iterator();
while (iterator.hasNext()) {
IJavaElement target = iterator.next();
IJavaElement child = target;
while (child != null) {
if (child.equals(parent)) {
result.add(target);
break;
}
child = child.getParent();
}
}
}
monitor.done();
}
private static List<IType> searchSubclassesOfApplet(IProgressMonitor pm, IJavaElement javaElement) {
return new ArrayList<>(collectAppletTypesInProject(pm, javaElement.getJavaProject()));
}
private static boolean isSubclassOfApplet(IProgressMonitor pm, IType type) {
return collectAppletTypesInProject(pm, type.getJavaProject()).contains(type);
}
private static Object computeScope(Object element) {
if (element instanceof IJavaElement) {
return element;
}
if (element instanceof IAdaptable) {
element = ((IAdaptable)element).getAdapter(IResource.class);
}
if (element instanceof IResource) {
IJavaElement javaElement = JavaCore.create((IResource)element);
if (javaElement != null && !javaElement.exists()) {
// do not consider the resource - corresponding java element does not exist
element = null;
} else {
element= javaElement;
}
}
return element;
}
/**
* Searches for applets from within the given scope of elements
* @param context
* @param elements the search scope
* @return and array of <code>IType</code>s of matches for java types that extend <code>Applet</code> (directly or indirectly)
* @throws InvocationTargetException
* @throws InterruptedException
*/
public static IType[] findApplets(IRunnableContext context, final Object[] elements) throws InvocationTargetException, InterruptedException {
final Set<Object> result= new HashSet<>();
if (elements.length > 0) {
IRunnableWithProgress runnable= new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor pm) throws InterruptedException {
int nElements= elements.length;
pm.beginTask(LauncherMessages.appletlauncher_search_task_inprogress, nElements);
try {
for (int i= 0; i < nElements; i++) {
try {
collectTypes(elements[i], new SubProgressMonitor(pm, 1), result);
} catch (JavaModelException jme) {
JDIDebugUIPlugin.log(jme.getStatus());
}
if (pm.isCanceled()) {
throw new InterruptedException();
}
}
} finally {
pm.done();
}
}
};
context.run(true, true, runnable);
}
return result.toArray(new IType[result.size()]) ;
}
}