/************************************************************************************* * Copyright (c) 2008-2013 Red Hat, Inc. 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: * JBoss by Red Hat - Initial implementation. ************************************************************************************/ package org.jboss.tools.arquillian.core.internal.util; import java.io.File; import java.io.FileFilter; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.eclipse.core.internal.runtime.InternalPlatform; 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.IResourceProxy; 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.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.jdt.core.Flags; import org.eclipse.jdt.core.IAnnotation; import org.eclipse.jdt.core.IClassFile; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaModelMarker; import org.eclipse.jdt.core.IJavaModelStatusConstants; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IMember; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IRegion; import org.eclipse.jdt.core.ISourceRange; 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.core.compiler.CharOperation; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTParser; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.IAnnotationBinding; import org.eclipse.jdt.core.dom.IBinding; import org.eclipse.jdt.core.dom.IMemberValuePairBinding; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.Modifier; import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.jdt.core.search.IJavaSearchConstants; import org.eclipse.jdt.core.search.IJavaSearchScope; import org.eclipse.jdt.core.search.SearchEngine; import org.eclipse.jdt.core.search.SearchMatch; import org.eclipse.jdt.core.search.SearchParticipant; import org.eclipse.jdt.core.search.SearchPattern; import org.eclipse.jdt.core.search.SearchRequestor; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.junit.JUnitMessages; import org.eclipse.jdt.internal.junit.launcher.ITestKind; import org.eclipse.jdt.internal.junit.util.CoreTestSearchEngine; import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jst.j2ee.internal.common.operations.JavaModelUtil; import org.jboss.tools.arquillian.core.ArquillianCoreActivator; import org.jboss.tools.arquillian.core.internal.ArquillianConstants; import org.jboss.tools.arquillian.core.internal.compiler.SourceFile; import org.osgi.framework.Bundle; /** * * @author snjeza * */ public class ArquillianSearchEngine { private static final String VALUE = "value"; //$NON-NLS-1$ public static final String ARQUILLIAN_JUNIT_ARQUILLIAN = "org.jboss.arquillian.junit.Arquillian"; //$NON-NLS-1$ public static final String CONTAINER_DEPLOYABLE_CONTAINER = "org.jboss.arquillian.container.spi.client.container.DeployableContainer"; //$NON-NLS-1$ public static final int CONTAINER_DEPLOYABLE_CONTAINER_NOT_EXISTS = 0; private static class Annotation { private static final Annotation RUN_WITH = new Annotation("org.junit.runner.RunWith"); //$NON-NLS-1$ private static final Annotation TEST = new Annotation("org.junit.Test"); //$NON-NLS-1$ private static final Annotation DEPLOYMENT = new Annotation(ArquillianUtility.ORG_JBOSS_ARQUILLIAN_CONTAINER_TEST_API_DEPLOYMENT); private final String fName; private Annotation(String name) { fName= name; } private String getName() { return fName; } public boolean annotatesTypeOrSuperTypes(ITypeBinding type, String value) { while (type != null) { if (annotates(type.getAnnotations(), fName, value)) { return true; } type= type.getSuperclass(); } return false; } public boolean annotatesAtLeastOneMethod(ITypeBinding type) { while (type != null) { IMethodBinding[] declaredMethods= type.getDeclaredMethods(); for (int i= 0; i < declaredMethods.length; i++) { IMethodBinding curr= declaredMethods[i]; if (annotates(curr.getAnnotations(), fName, null)) { return true; } } type= type.getSuperclass(); } return false; } public boolean annotatesAtLeastOneMethod(ITypeBinding type, String value) { while (type != null) { IMethodBinding[] declaredMethods= type.getDeclaredMethods(); for (int i= 0; i < declaredMethods.length; i++) { IMethodBinding curr= declaredMethods[i]; if (annotates(curr.getAnnotations(), fName, value)) { return true; } } type= type.getSuperclass(); } return false; } } private static class AnnotationSearchRequestor extends SearchRequestor { private final Collection fResult; private final ITypeHierarchy fHierarchy; public AnnotationSearchRequestor(ITypeHierarchy hierarchy, Collection result) { fHierarchy= hierarchy; fResult= result; } public void acceptSearchMatch(SearchMatch match) throws CoreException { if (match.getAccuracy() == SearchMatch.A_ACCURATE && !match.isInsideDocComment()) { Object element= match.getElement(); if (element instanceof IType || element instanceof IMethod) { IMember member= (IMember) element; IType type= member.getElementType() == IJavaElement.TYPE ? (IType) member : member.getDeclaringType(); addTypeAndSubtypes(type); } } } private void addTypeAndSubtypes(IType type) { if (fResult.add(type)) { IType[] subclasses= fHierarchy.getSubclasses(type); for (int i= 0; i < subclasses.length; i++) { addTypeAndSubtypes(subclasses[i]); } } } } public static boolean isArquillianJUnitTest(IJavaElement element, boolean checkDeployment, boolean checkTest) { try { IType testType= null; if (element instanceof ICompilationUnit) { testType= (((ICompilationUnit) element)).findPrimaryType(); } else if (element instanceof IClassFile) { testType= (((IClassFile) element)).getType(); } else if (element instanceof IType) { testType= (IType) element; } else if (element instanceof IMember) { testType= ((IMember) element).getDeclaringType(); } if (testType != null && testType.exists()) { return isArquillianJUnitTest(testType, checkDeployment, checkTest); } } catch (CoreException e) { // ignore, return false } return false; } public static boolean isAccessibleClass(IType type) throws JavaModelException { if (type == null) { return false; } int flags= type.getFlags(); if (Flags.isInterface(flags)) { return false; } IJavaElement parent= type.getParent(); while (true) { if (parent instanceof ICompilationUnit || parent instanceof IClassFile) { return true; } if (!(parent instanceof IType) || !Flags.isStatic(flags) || !Flags.isPublic(flags)) { return false; } flags= ((IType) parent).getFlags(); parent= parent.getParent(); } } public static boolean hasSuiteMethod(IType type) throws JavaModelException { IMethod method= type.getMethod("suite", new String[0]); //$NON-NLS-1$ if (!method.exists()) return false; if (!Flags.isStatic(method.getFlags()) || !Flags.isPublic(method.getFlags())) { return false; } if (!Signature.getSimpleName(Signature.toString(method.getReturnType())).equals(ArquillianUtility.SIMPLE_TEST_INTERFACE_NAME)) { return false; } return true; } private static boolean isArquillianJUnitTest(IType type, boolean checkDeployment, boolean checkTest) throws JavaModelException { if (isAccessibleClass(type)) { ITypeBinding binding = getTypeBinding(type); if (binding != null) { return isTest(binding, checkDeployment, checkTest); } } return false; } private static ITypeBinding getTypeBinding(IType type) throws JavaModelException { ASTParser parser= ASTParser.newParser(AST.JLS4); if (type.getCompilationUnit() != null) { parser.setSource(type.getCompilationUnit()); } else if (!isAvailable(type.getSourceRange())) { // class file with no source parser.setProject(type.getJavaProject()); IBinding[] bindings= parser.createBindings(new IJavaElement[] { type }, null); if (bindings.length == 1 && bindings[0] instanceof ITypeBinding) { return (ITypeBinding) bindings[0]; } return null; } else { parser.setSource(type.getClassFile()); } parser.setFocalPosition(0); parser.setResolveBindings(true); CompilationUnit root= (CompilationUnit) parser.createAST(null); ASTNode node= root.findDeclaringNode(type.getKey()); if (node instanceof TypeDeclaration) { return ((TypeDeclaration) node).resolveBinding(); } return null; } static boolean isAvailable(ISourceRange range) { return range != null && range.getOffset() != -1; } static boolean isTest(ITypeBinding binding, boolean checkDeployment, boolean checkTest) { if (Modifier.isAbstract(binding.getModifiers())) return false; if (Annotation.RUN_WITH.annotatesTypeOrSuperTypes(binding, ARQUILLIAN_JUNIT_ARQUILLIAN)) { if (checkDeployment && !Annotation.DEPLOYMENT.annotatesAtLeastOneMethod(binding)) { return false; } if (checkTest && !Annotation.TEST.annotatesAtLeastOneMethod(binding)) { return false; } return true; } return isTestImplementor(binding); } public static boolean isTestImplementor(ITypeBinding type) { ITypeBinding superType= type.getSuperclass(); if (superType != null && isTestImplementor(superType)) { return true; } ITypeBinding[] interfaces= type.getInterfaces(); for (int i= 0; i < interfaces.length; i++) { ITypeBinding curr= interfaces[i]; if (ArquillianUtility.TEST_INTERFACE_NAME.equals(curr.getQualifiedName()) || isTestImplementor(curr)) { return true; } } return false; } public static IStatus validateDeployableContainer(IJavaProject javaProject) { try { IType type = javaProject.findType(CONTAINER_DEPLOYABLE_CONTAINER); if (type == null) { return new Status( IStatus.ERROR, ArquillianCoreActivator.PLUGIN_ID, CONTAINER_DEPLOYABLE_CONTAINER_NOT_EXISTS, "Cannot find 'org.jboss.arquillian.container.spi.client.container.DeployableContainer' on project build path. Do you want to add it.", null); } ITypeHierarchy hierarchy = type.newTypeHierarchy(javaProject, new NullProgressMonitor()); IType[] subTypes = hierarchy.getAllSubtypes(type); int count = 0; for (IType subType:subTypes) { if (isNonAbstractClass(subType)) { count++; } } if (count != 1) { return new Status(IStatus.ERROR, ArquillianCoreActivator.PLUGIN_ID, 1 , "Arquillian tests require exactly one implementation of DeploymentContainer on the build path. Do you want to configure it?", null); } } catch (JavaModelException e) { return new Status(IStatus.ERROR, ArquillianCoreActivator.PLUGIN_ID, e.getLocalizedMessage(), e); } return Status.OK_STATUS; } public static boolean isNonAbstractClass(IType type) throws JavaModelException { int flags= type.getFlags(); if (Flags.isInterface(flags)) { return false; } if (Flags.isAbstract(flags)) { return false; } return true; } public static IType[] findTests(IRunnableContext context, final IJavaElement element, final ITestKind testKind) throws InvocationTargetException, InterruptedException { final Set<IType> result= new HashSet<IType>(); IRunnableWithProgress runnable= new IRunnableWithProgress() { public void run(IProgressMonitor pm) throws InterruptedException, InvocationTargetException { try { findTestsInContainer(element, result, pm); } catch (CoreException e) { throw new InvocationTargetException(e); } } }; context.run(true, true, runnable); return result.toArray(new IType[result.size()]); } public static void findTestsInContainer(IJavaElement element, Set result, IProgressMonitor pm) throws CoreException { findTestsInContainer(element, result, pm, true, true, true); } public static void findTestsInContainer(IJavaElement element, Set result, IProgressMonitor pm, boolean checkDeployment, boolean checkTest, boolean checkSuite) throws CoreException { if (element == null || result == null) { throw new IllegalArgumentException(); } if (element instanceof IType) { if (isArquillianJUnitTest((IType) element, checkDeployment, checkTest)) { result.add(element); return; } } if (pm == null) pm= new NullProgressMonitor(); try { pm.beginTask(JUnitMessages.JUnit4TestFinder_searching_description, 4); IRegion region= CoreTestSearchEngine.getRegion(element); ITypeHierarchy hierarchy= JavaCore.newTypeHierarchy(region, null, new SubProgressMonitor(pm, 1)); IType[] allClasses= hierarchy.getAllClasses(); // search for all types with references to RunWith and Test and all subclasses HashSet candidates= new HashSet(allClasses.length); SearchRequestor requestor= new AnnotationSearchRequestor(hierarchy, candidates); IJavaSearchScope scope= SearchEngine.createJavaSearchScope(allClasses, IJavaSearchScope.SOURCES); int matchRule= SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE; SearchPattern runWithPattern= SearchPattern.createPattern(Annotation.RUN_WITH.getName(), IJavaSearchConstants.ANNOTATION_TYPE, IJavaSearchConstants.ANNOTATION_TYPE_REFERENCE, matchRule); //SearchPattern testPattern= SearchPattern.createPattern(Annotation.TEST.getName(), IJavaSearchConstants.ANNOTATION_TYPE, IJavaSearchConstants.ANNOTATION_TYPE_REFERENCE, matchRule); //SearchPattern annotationsPattern= SearchPattern.crateOrPattern(runWithPattern, testPattern); SearchPattern annotationsPattern = runWithPattern; SearchParticipant[] searchParticipants= new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() }; new SearchEngine().search(annotationsPattern, searchParticipants, scope, requestor, new SubProgressMonitor(pm, 2)); // find all classes in the region for (Iterator iterator= candidates.iterator(); iterator.hasNext();) { IType curr= (IType) iterator.next(); if (isAccessibleClass(curr) && !Flags.isAbstract(curr.getFlags()) && region.contains(curr)) { ITypeBinding binding = getTypeBinding(curr); if (binding != null && isTest(binding, true, true)) { result.add(curr); } } } if (checkSuite) { CoreTestSearchEngine.findSuiteMethods(element, result, new SubProgressMonitor(pm, 1)); } } finally { pm.done(); } } public static boolean hasArquillianType(IJavaProject javaProject) { if (javaProject == null) { return false; } try { IType type = javaProject.findType(ARQUILLIAN_JUNIT_ARQUILLIAN); return type != null; } catch (JavaModelException e) { // ignore } return false; } public static boolean isArquillianJUnitTest(IResourceProxy proxy, IJavaProject project) { if (proxy == null || project == null || ! (proxy.requestResource() instanceof IFile)) { return false; } IFile file = (IFile) proxy.requestResource(); IJavaElement element = JavaCore.create(file); if (!(element instanceof ICompilationUnit)) { return false; } ICompilationUnit cu = (ICompilationUnit) element; IType type = cu.findPrimaryType(); ITypeBinding binding; try { if (!isAccessibleClass(type)) { return false; } binding = getTypeBinding(type); if (binding == null) { return false; } } catch (JavaModelException e) { ArquillianCoreActivator.log(e); return false; } if (Modifier.isAbstract(binding.getModifiers())) { return false; } if (!Annotation.RUN_WITH.annotatesTypeOrSuperTypes(binding, ARQUILLIAN_JUNIT_ARQUILLIAN)) { return false; } return true; } public static boolean hasDeploymentMethod(SourceFile sourceFile, IJavaProject project) { IType type = getType(sourceFile); if (type == null) { return false; } return hasDeploymentMethod(type); } public static IType getType(SourceFile sourceFile) { IFile file = sourceFile.resource; IJavaElement element = JavaCore.create(file); if (!(element instanceof ICompilationUnit)) { return null; } ICompilationUnit cu = (ICompilationUnit) element; IType type = cu.findPrimaryType(); return type; } private static boolean hasDeploymentMethod(IType type) { if (type == null) { return false; } try { ITypeBinding binding = getTypeBinding(type); return Annotation.DEPLOYMENT.annotatesAtLeastOneMethod(binding); } catch (JavaModelException e) { ArquillianCoreActivator.log(e); return false; } } public static boolean hasTestMethod(SourceFile sourceFile, IJavaProject project) { IType type = getType(sourceFile); try { ITypeBinding binding = getTypeBinding(type); return Annotation.TEST.annotatesAtLeastOneMethod(binding); } catch (JavaModelException e) { ArquillianCoreActivator.log(e); return false; } } public static boolean annotates(IAnnotationBinding[] annotations, String fName, String val) { for (int i= 0; i < annotations.length; i++) { ITypeBinding annotationType= annotations[i].getAnnotationType(); if (annotationType != null && (annotationType.getQualifiedName().equals(fName))) { if (val == null) { return true; } IMemberValuePairBinding[] pairs = annotations[i].getAllMemberValuePairs(); if (pairs != null) { for (IMemberValuePairBinding pair : pairs) { if (VALUE.equals(pair.getName())) { Object object = pair.getValue(); if (object instanceof ITypeBinding) { ITypeBinding value = (ITypeBinding) object; if (val.equals(value.getQualifiedName())) { return true; } } } } } } } return false; } public static List<File> getDeploymentArchives(IType type) { return getDeploymentArchives(type, false); } private static List<File> getDeploymentArchives(IType type, boolean force) { List<File> archives = new ArrayList<File>(); if (type == null || !hasDeploymentMethod(type)) { return archives; } Bundle bundle = Platform.getBundle(ArquillianCoreActivator.PLUGIN_ID); if (bundle == null) { ArquillianCoreActivator.log("The " + ArquillianCoreActivator.PLUGIN_ID + "bundle is invalid."); return archives; } IPath stateLocation = InternalPlatform.getDefault().getStateLocation( bundle, true); String projectName = null; ICompilationUnit cu = type.getCompilationUnit(); IJavaProject javaProject = null; if (cu != null) { IResource resource = cu.getResource(); if (resource != null) { // try { // resource.deleteMarkers(ArquillianConstants.MARKER_RESOURCE_ID, false, IResource.DEPTH_INFINITE); // } catch (CoreException e) { // ArquillianCoreActivator.log(e); // } IProject project = resource.getProject(); if (project != null) { projectName = project.getName(); javaProject = JavaCore.create(project); } } } if (projectName == null) { ArquillianCoreActivator.log("Cannot find any project for the " + type.getElementName() + "type."); return archives; } IPath location = stateLocation.append(projectName); location = location.append("arquillianDeploymentArchives"); String fqn = type.getFullyQualifiedName(); fqn = fqn.replace(".", "/"); location = location.append(fqn); try { List<IMethodBinding> deploymentMethods = getDeploymentMethods(type); for (IMethodBinding deploymentMethod : deploymentMethods) { String name = deploymentMethod.getName(); IPath methodLocation = location.append(name); File file = methodLocation.toFile(); if (file.exists()) { if (force) { if (!ArquillianUtility.deleteFile(file)) { ArquillianCoreActivator.log("Cannot delete " + file.getAbsolutePath()); } } } if (!file.exists()) { createArchive(javaProject, type, deploymentMethod, file); } if (file.isDirectory()) { File[] files = file.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { return pathname.isFile() && pathname.getName().startsWith("archive"); } }); if (files != null && files.length > 0 && files[0].isFile()) { archives.add(files[0]); } } } } catch (JavaModelException e) { ArquillianCoreActivator.log(e); } return archives; } private static File createArchive(IJavaProject javaProject, IType type, IMethodBinding deploymentMethod, File file) { String className = type.getFullyQualifiedName(); String methodName = deploymentMethod.getName(); ClassLoader loader = ArquillianCoreActivator.getDefault().getClassLoader(javaProject); ClassLoader oldLoader = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(loader); Class<?> clazz = Class.forName(className, true, loader); Object object = clazz.newInstance(); Method method = clazz.getMethod(methodName, new Class[0]); Object archiveObject = method.invoke(object, new Object[0]); Class<?> archiveClass = archiveObject.getClass(); //archive.as(ZipExporter.class).exportTo( // new File("/home/alr/Desktop/myPackage.jar"), true); Class<?> exporterClass = Class.forName("org.jboss.shrinkwrap.api.exporter.ZipExporter", true, loader); Method asMethod = archiveClass.getMethod("as", new Class[] { Class.class }); Object asObject = asMethod.invoke(archiveObject, new Object[] {exporterClass}); Class<?> asClass = asObject.getClass(); Method exportToMethod = asClass.getMethod("exportTo", new Class[] {File.class, boolean.class }); Class<?> jarClass = Class.forName(ArquillianUtility.ORG_JBOSS_SHRINKWRAP_API_SPEC_JAVA_ARCHIVE, true, loader); if (jarClass.isAssignableFrom(archiveClass)) { File jarFile = new File(file, "archive.jar"); file.mkdirs(); exportToMethod.invoke(asObject, new Object[] {jarFile, Boolean.TRUE}); return jarFile; } Class<?> warClass = Class.forName(ArquillianUtility.ORG_JBOSS_SHRINKWRAP_API_SPEC_WEB_ARCHIVE, true, loader); if (warClass.isAssignableFrom(archiveClass)) { File warFile = new File(file, "archive.war"); file.mkdirs(); exportToMethod.invoke(asObject, new Object[] {warFile, Boolean.TRUE}); return warFile; } } catch (Exception e) { //ArquillianCoreActivator.log(e); String message = e.getLocalizedMessage(); Throwable cause = e.getCause(); int i = 0; while (cause != null && i++ < 5) { message = cause.getLocalizedMessage(); cause = cause.getCause(); } ArquillianCoreActivator.log(message); try { Integer severity = ArquillianUtility.getSeverity(ArquillianUtility.getPreference(ArquillianConstants.DEPLOYMENT_ARCHIVE_CANNOT_BE_CREATED)); createProblem(message, type, deploymentMethod, severity); } catch (CoreException e1) { ArquillianCoreActivator.log(e1); } } finally { Thread.currentThread().setContextClassLoader(oldLoader); } return null; } private static void createProblem(String message, IType type, IMethodBinding deploymentMethod, Integer severity) throws CoreException { if (severity == null || type == null || type.getJavaProject() == null) { return; } boolean enable = ArquillianUtility.isValidatorEnabled(type.getJavaProject().getProject()); if (!enable) { return; } ICompilationUnit cu = type.getCompilationUnit(); if (cu == null) { return; } IResource resource = cu.getResource(); if (resource == null) { return; } IMarker marker = resource .createMarker(ArquillianConstants.MARKER_RESOURCE_ID); String[] allNames = { IMarker.MESSAGE, IMarker.SEVERITY, IJavaModelMarker.ID, IMarker.CHAR_START, IMarker.CHAR_END, IMarker.SOURCE_ID, }; Object[] allValues = new Object[allNames.length]; int index = 0; allValues[index++] = message; allValues[index++] = severity; allValues[index++] = ArquillianConstants.ARQUILLIAN_PROBLEM_ID; IJavaElement javaElement = deploymentMethod.getJavaElement(); ISourceRange range = null; if (javaElement instanceof IMember) { IMember member = (IMember) javaElement; if (javaElement != null) { try { range = member.getNameRange(); } catch (JavaModelException e) { if (e.getJavaModelStatus().getCode() != IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST) { throw e; } if (!CharOperation.equals(javaElement.getElementName() .toCharArray(), TypeConstants.PACKAGE_INFO_NAME)) { throw e; } } } } int start = range == null ? 0 : range.getOffset(); int end = range == null ? 1 : start + range.getLength(); allValues[index++] = new Integer(start); // start allValues[index++] = new Integer(end > 0 ? end + 1 : end); // end allValues[index++] = ArquillianConstants.SOURCE_ID; marker.setAttributes(allNames, allValues); } private static List<IMethodBinding> getDeploymentMethods(IType type) throws JavaModelException { List<IMethodBinding> methodBindings = new ArrayList<IMethodBinding>(); if (type == null) { return methodBindings; } ITypeBinding binding = getTypeBinding(type); while (binding != null) { IMethodBinding[] declaredMethods= binding.getDeclaredMethods(); for (IMethodBinding curr:declaredMethods) { if (isDeploymentMethod(curr)) { methodBindings.add(curr); } } binding = binding.getSuperclass(); } return methodBindings; } public static boolean isDeploymentMethod(IMethodBinding methodBinding) { if (annotates(methodBinding.getAnnotations(), ArquillianUtility.ORG_JBOSS_ARQUILLIAN_CONTAINER_TEST_API_DEPLOYMENT, null)) { int modifiers = methodBinding.getModifiers(); if ( (modifiers & Modifier.PUBLIC) != 0 && (modifiers & Modifier.STATIC) != 0 && methodBinding.getParameterTypes().length == 0) { ITypeBinding returnType = methodBinding.getReturnType(); if ("org.jboss.shrinkwrap.api.Archive".equals(returnType.getBinaryName())) { return true; } } } return false; } public static boolean isDeploymentMethod(IMethod method) { if (method == null || !method.exists()) return false; try { if (!Flags.isStatic(method.getFlags()) || !Flags.isPublic(method.getFlags())) { return false; } if (method.getParameters().length > 0) { return false; } String type = method.getReturnType(); if (type == null) { return false; } String typeSig = Signature.toString(type); if (!"Archive<?>".equals(typeSig)) { return false; } IAnnotation deployment = method.getAnnotation("Deployment"); if (deployment != null && deployment.exists()) { return true; } } catch (JavaModelException e) { ArquillianCoreActivator.log(e); return false; } return false; } }