org.netbeans.modules.java.testrunner.JavaUtils Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.java.testrunner;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.project.JavaProjectConstants;
import org.netbeans.api.java.queries.UnitTestForSourceQuery;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.api.project.SourceGroupModifier;
import org.netbeans.api.project.Sources;
import org.netbeans.modules.gsf.testrunner.api.TestCreatorProvider;
import org.netbeans.modules.gsf.testrunner.plugin.RootsProvider;
import org.netbeans.modules.java.testrunner.providers.JavaRootsProvider;
import org.openide.ErrorManager;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.URLMapper;
import org.openide.util.Lookup;
import org.openide.util.Utilities;
/**
*
* @author Marian Petras
*/
public final class JavaUtils {
/** */
private final Project project;
/** */
private boolean sourceGroupsOnly = true;
/** */
private SourceGroup[] javaSourceGroups;
/** */
private Map sourcesToTestsMap;
/** */
private Map foldersToSourceGroupsMap;
/**
* Since 8.1, "junit" library definition and junit-3.8.2 binaries were
* removed. This property is saved in project.properties file once the
* project problems are resolved by updating test dependency to JUnit 4.x.
* The possible values are "3" or "4" to indicate JUnit 3.x or JUnit 4.x
* style for the test case sceletons.
*/
public static final String PROP_JUNIT_SELECTED_VERSION = "junit.selected.version";
/**
*
*/
public JavaUtils(Project project) {
this.project = project;
}
/**
* Check whether this implementation supports given FileObjects.
*
* @param activatedFOs FileObjects to check
* @return {@code true} if this instance supports given FileObjects, {@code false} otherwise
*/
public static boolean isSupportEnabled(Class lookupClass, FileObject[] activatedFOs) {
if (activatedFOs.length == 0) {
return false;
}
final FileObject firstFile = activatedFOs[0];
Project p = FileOwnerQuery.getOwner(firstFile);
if (p == null) {
return false;
}
if(p.getLookup().lookup(lookupClass) == null) {
return false;
}
final SourceGroup sourceGroup = findSourceGroup(firstFile);
if (sourceGroup == null) {
return false;
}
final FileObject rootFolder = sourceGroup.getRootFolder();
if (UnitTestForSourceQuery.findUnitTests(rootFolder).length == 0) {
return false;
}
/*
* Now we know that source folder of the first file has a corresponding
* test folder (possible non-existent).
*/
if (activatedFOs.length == 1) {
/* ... if there is just one file selected, it is all we need: */
return true;
}
/*
* ...for multiple files, we just check that all the selected files
* have the same root folder:
*/
for (int i = 1; i < activatedFOs.length; i++) {
FileObject fileObj = activatedFOs[i];
if (!FileUtil.isParentOf(rootFolder, fileObj)
|| !sourceGroup.contains(fileObj)) {
return false;
}
}
return true;
}
/**
* Finds a Java source group the given file belongs to.
*
* @param file {@literal FileObject} to find a {@literal SourceGroup} for
* @return the found {@literal SourceGroup}, or {@literal null} if the given
* file does not belong to any Java source group
*/
private static SourceGroup findSourceGroup(FileObject file) {
final Project project = FileOwnerQuery.getOwner(file);
if (project == null) {
return null;
}
Sources src = ProjectUtils.getSources(project);
SourceGroup[] srcGrps = src.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
for (SourceGroup srcGrp : srcGrps) {
FileObject rootFolder = srcGrp.getRootFolder();
if (((file == rootFolder) || FileUtil.isParentOf(rootFolder, file))
&& srcGrp.contains(file)) {
return srcGrp;
}
}
return null;
}
/**
* Finds SourceGroup
s where a test for the given class
* can be created (so that it can be found by the projects infrastructure
* when a test for the class is to be opened or run).
*
* @param fo FileObject
to find Source and Test filenames for
* @param isTestNG {@code true} if user wants to create TestNG test, {@code false} otherwise
* @param isSelenium {@code true} if user wants to create Selenium test, {@code false} otherwise
* @return an array of Strings - the first one being the source class name
* and the second being the test class name.
* the returned array may be empty but not null
*/
public static String[] getSourceAndTestClassNames(FileObject fo, boolean isTestNG, boolean isSelenium) {
String[] result = {"", ""};
ClassPath cp = ClassPath.getClassPath(fo, ClassPath.SOURCE);
if (cp != null) {
result[0] = cp.getResourceName(fo, '.', false);
String suffix = "";
if(isTestNG) {
suffix = TestCreatorProvider.TESTNG_TEST_CLASS_SUFFIX;
}
if(isSelenium) {
suffix = TestCreatorProvider.INTEGRATION_TEST_CLASS_SUFFIX;
} else {
suffix = suffix.concat(TestCreatorProvider.TEST_CLASS_SUFFIX);
}
result[1] = result[0].concat(suffix);
}
return result;
}
/**
* Finds SourceGroup
s where a test for the given class
* can be created (so that it can be found by the projects infrastructure
* when a test for the class is to be opened or run).
*
* @param createdSourceRoots
* @param fileObject FileObject
to find target
* SourceGroup
(s) for
* @return an array of objects - each of them can be either
* a SourceGroup
for a possible target folder
* or simply a FileObject
representing a possible
* target folder (if SourceGroup
) for the folder
* was not found);
* the returned array may be empty but not null
*/
public static Object[] getTestSourceRoots(Collection createdSourceRoots, FileObject fileObject) {
Object[] targetFolders = CommonTestUtil.getTestTargets(fileObject);
if (targetFolders == null || targetFolders.length == 0) {
Project owner = FileOwnerQuery.getOwner(fileObject);
if (owner != null) {
String type = "";
String hint = "";
Collection extends RootsProvider> rootProviders = Lookup.getDefault().lookupAll(RootsProvider.class);
for (RootsProvider rootProvider : rootProviders) {
if(rootProvider instanceof JavaRootsProvider) {
type = rootProvider.getSourceRootType();
hint = rootProvider.getProjectTestsHint();
}
}
final SourceGroup grp = SourceGroupModifier.createAssociatedSourceGroup(owner, findSourceGroup(fileObject), type, hint);
if (grp != null) {
createdSourceRoots.add(grp);
targetFolders = CommonTestUtil.getTestTargets(fileObject);
}
}
}
return targetFolders;
}
/** */
static FileObject findTestsRoot(Project project) {
final SourceGroup[] sourceGroups
= new JavaUtils(project).getJavaSourceGroups();
for (int i = 0; i < sourceGroups.length; i++) {
FileObject root = sourceGroups[i].getRootFolder();
if (root.getName().equals(JavaProjectConstants.SOURCES_TYPE_JAVA)) {
return root;
}
}
return null;
}
/** */
static FileObject getPackageFolder(
FileObject root,
String pkgName) throws IOException {
String relativePathName = pkgName.replace('.', '/');
FileObject folder = root.getFileObject(relativePathName);
if (folder == null) {
folder = FileUtil.createFolder(root, relativePathName);
}
return folder;
}
/**
* Identifies and collects SourceGroup
s and folders
* of a given project which may serve as target folders for newly created
* test classes.
*
* @param project project whose folders are to be checked
* @param sourceGroupsOnly return only SourceGroup
s
* - ignore target folders not having
* a corresponding SourceGroup
* @return collection which may contain FileObject
s
* or SourceGroup
s (or both);
* it may be empty but not null
* @author Marian Petras
*/
static Collection getTestTargets(Project project,
final boolean sourceGroupsOnly) {
final JavaUtils utils = new JavaUtils(project);
return utils.getTestTargets(sourceGroupsOnly);
}
/**
* Identifies and collects root test folders of a given project.
*
* @param project project whose test folders are to be found
* @return collection of found {@code FileObject}s, possibly empty
* (but not {@code null})
*/
public static Collection getTestFolders(Project project) {
return new JavaUtils(project).getTestFolders();
}
/**
* Builds a map that containing relation between SourceGroup
s
* and their respective test SourceGroup
s.
* Each entry of the map contains a SourceGroup
as a key
* and an array of test SourceGroup
s returned by
* UnitTestForSourceQuery
for that SourceGroup
* as a value. SourceGroup
s that have no test
* SourceGroup
s assigned are omitted, i.e. the resulting
* map does not contain entries that would have empty arrays as their
* values.
*
* @param project project whose SourceGroup
s are to be
* checked
* @param sourceGroupsOnly return only SourceGroup
s
* - ignore test folders not having
* a corresponding SourceGroup
* @return created map - may be empty, may be unmodifiable
* never null
*/
static Map getSourcesToTestsMap(Project project,
final boolean sourceGroupsOnly) {
final JavaUtils utils = new JavaUtils(project);
return utils.getSourcesToTestsMap(sourceGroupsOnly);
}
/**
*
*/
Project getProject() {
return project;
}
/**
* Identifies and collects root test folders of the project.
*
* @return collection of found {@code FileObject}s
* - may be empty but never {@code null}
*/
private Collection getTestFolders() {
/*
* Idea:
* 1) Get all SourceGroups
* 2) For each SourceGroup, ask UnitTestForSourceQuery for its related
* test SourceGroups
*/
/* .) get all SourceGroups: */
final SourceGroup[] sourceGroups = getJavaSourceGroups();
if (sourceGroups.length == 0) {
return Collections.emptyList();
}
List result = null;
/* .) for each SourceGroup, ask for test root folders: */
for (SourceGroup sourceGroup : sourceGroups) {
FileObject srcFolder = sourceGroup.getRootFolder();
FileObject[] tstFoldersRaw = getTestFoldersRaw(srcFolder);
if (tstFoldersRaw.length == 0) {
continue;
}
for (FileObject tstFolder : tstFoldersRaw) {
if (tstFolder == null) {
continue;
}
if (result == null) {
result = new ArrayList(2);
}
if (!result.contains(tstFolder)) {
result.add(tstFolder);
}
}
}
/* .) pack the results: */
if (result == null) {
return Collections.emptyList();
} else {
assert !result.isEmpty();
return (result.size() == 1)
? Collections.singleton(result.get(0))
: result;
}
}
/**
* Identifies and collects SourceGroup
s and folders
* which may serve as target folders for newly created test classes.
*
* @param sourceGroupsOnly return only SourceGroup
s
* (skip target folders without matching
* SourceGroup
)
* @return collection which may contain FileObject
s
* or SourceGroup
s (or both);
* it may be empty but not null
* @see #getTestTargets(Project, boolean)
* @author Marian Petras
*/
private Collection
© 2015 - 2025 Weber Informatics LLC | Privacy Policy