blob: 73a2201b0eeb6a21bd2c9991d64b4cb3edb6ab15 [file] [log] [blame]
/*
* 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.j2ee.core.api.support;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.api.java.project.JavaProjectConstants;
import org.netbeans.api.java.queries.UnitTestForSourceQuery;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.SourceGroup;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.URLMapper;
import org.openide.util.Parameters;
/**
* This class consists of various static utility methods for working with
* {@link SourceGroup}s.
*
* @author Andrei Badea, Erno Mononen
*/
public final class SourceGroups {
private static final Logger LOGGER = Logger.getLogger(SourceGroups.class.getName());
private SourceGroups() {
}
/**
* Gets the Java source groups of the given <code>project</code>.
*
* @param project the project whose source groups to get; must not be null.
* @return the Java source groups of the given <code>project</code>,
* <strong>excluding</strong> test source groups.
*/
public static SourceGroup[] getJavaSourceGroups(Project project) {
Parameters.notNull("project", project); //NOI18N
SourceGroup[] sourceGroups = ProjectUtils.getSources(project).getSourceGroups(
JavaProjectConstants.SOURCES_TYPE_JAVA);
Set<SourceGroup> testGroups = getTestSourceGroups(sourceGroups);
List<SourceGroup> result = new ArrayList<SourceGroup>();
for(SourceGroup sourceGroup : sourceGroups){
if (!testGroups.contains(sourceGroup)) {
result.add(sourceGroup);
}
}
return result.toArray(new SourceGroup[result.size()]);
}
/**
* Checks whether the folder identified by the given <code>packageName</code> is
* writable or is in a writable parent directory but does not exist yet.
*
* @param sourceGroup the source group of the folder; must not be null.
* @param packageName the package to check; must not be null.
* @return true if the folder is writable or can be created (i.e. the parent
* folder, or the root folder of the given <code>sourceGroup</code> if there is no other
* parent for the folder, is writable), false otherwise.
*/
public static boolean isFolderWritable(SourceGroup sourceGroup, String packageName) {
Parameters.notNull("sourceGroup", sourceGroup); //NOI18N
Parameters.notNull("packageName", packageName); //NOI18N
try {
FileObject fo = getFolderForPackage(sourceGroup, packageName, false);
while ((fo == null) && (packageName.lastIndexOf('.') != -1)) {
packageName = packageName.substring(0, packageName.lastIndexOf('.'));
fo = getFolderForPackage(sourceGroup, packageName, false);
}
return fo == null ? sourceGroup.getRootFolder().canWrite() : fo.canWrite();
} catch (IOException ex) {
LOGGER.log(Level.INFO, null, ex);
return false;
}
}
/**
* Gets the {@link SourceGroup} of the given <code>folder</code>.
*
* @param sourceGroups the source groups to search; must not be null.
* @param folder the folder whose source group is to be get; must not be null.
* @return the source group containing the given <code>folder</code> or
* null if not found.
*/
public static SourceGroup getFolderSourceGroup(SourceGroup[] sourceGroups, FileObject folder) {
Parameters.notNull("sourceGroups", sourceGroups); //NOI18N
Parameters.notNull("folder", folder); //NOI18N
for (int i = 0; i < sourceGroups.length; i++) {
if (FileUtil.isParentOf(sourceGroups[i].getRootFolder(), folder)) {
return sourceGroups[i];
}
}
return null;
}
/**
* Converts the path of the given <code>folder</code> to a package name.
*
* @param sourceGroup the source group for the folder; must not be null.
* @param folder the folder to convert; must not be null.
* @return the package name of the given <code>folder</code>.
* @throws IllegalStateException if the given <code>folder</code> was not
* in the same tree as the root folder of the given <code>sourceGroup</code>.
*/
public static String getPackageForFolder(SourceGroup sourceGroup, FileObject folder) {
Parameters.notNull("sourceGroup", sourceGroup); //NOI18N
Parameters.notNull("folder", folder); //NOI18N
String relative = FileUtil.getRelativePath(sourceGroup.getRootFolder(), folder);
if (relative == null){
throw new IllegalStateException("The given folder [ " + folder.getPath() + "] is not in the " +
"same tree with [" + sourceGroup.getRootFolder().getPath() + "]"); //NOI18N
}
return relative.replace('/', '.'); // NOI18N
}
/**
* Gets the folder representing the given <code>packageName</code>. If the
* folder does not exists, it will be created.
*
* @param sourceGroup the source group of the package.
* @param packageName the name of the package.
* @return the folder representing the given package.
*/
public static FileObject getFolderForPackage(SourceGroup sourceGroup, String packageName) throws IOException {
return getFolderForPackage(sourceGroup, packageName, true);
}
/**
* Gets the folder representing the given <code>packageName</code>.
*
* @param sourceGroup the source group of the package; must not be null.
* @param packageName the name of the package; must not be null.
* @param create specifies whether the folder should be created if it does not exist.
* @return the folder representing the given package or null if it was not found.
*/
public static FileObject getFolderForPackage(SourceGroup sourceGroup, String packageName, boolean create) throws IOException {
Parameters.notNull("sourceGroup", sourceGroup); //NOI18N
Parameters.notNull("packageName", packageName); //NOI18N
String relativePkgName = packageName.replace('.', '/');
FileObject folder = sourceGroup.getRootFolder().getFileObject(relativePkgName);
if (folder != null) {
return folder;
} else if (create) {
return FileUtil.createFolder(sourceGroup.getRootFolder(), relativePkgName);
}
return null;
}
/**
* Gets the {@link SourceGroup} of the given <code>project</code> which contains the
* given <code>fqClassName</code>.
*
* @param project the project; must not be null.
* @param fqClassName the fully qualified name of the class whose
* source group to get; must not be empty or null.
* @return the source group containing the given <code>fqClassName</code> or <code>null</code>
* if the class was not found in the source groups of the project.
*/
public static SourceGroup getClassSourceGroup(Project project, String fqClassName) {
Parameters.notNull("project", project); //NOI18N
Parameters.notEmpty("fqClassName", fqClassName); //NOI18N
String classFile = fqClassName.replace('.', '/') + ".java"; // NOI18N
SourceGroup[] sourceGroups = ProjectUtils.getSources(project).getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
for (SourceGroup sourceGroup : sourceGroups) {
FileObject classFO = sourceGroup.getRootFolder().getFileObject(classFile);
if (classFO != null) {
return sourceGroup;
}
}
return null;
}
private static Map<FileObject, SourceGroup> createFoldersToSourceGroupsMap(final SourceGroup[] sourceGroups) {
Map<FileObject, SourceGroup> result;
if (sourceGroups.length == 0) {
result = Collections.emptyMap();
} else {
result = new HashMap<>(2 * sourceGroups.length, .5f);
for (int i = 0; i < sourceGroups.length; i++) {
SourceGroup sourceGroup = sourceGroups[i];
result.put(sourceGroup.getRootFolder(), sourceGroup);
}
}
return result;
}
private static List<SourceGroup> getTestTargets(SourceGroup sourceGroup, Map<FileObject, SourceGroup> foldersToSourceGroupsMap) {
final URL[] rootURLs = UnitTestForSourceQuery.findUnitTests(sourceGroup.getRootFolder());
if (rootURLs.length == 0) {
return new ArrayList<>();
}
List<SourceGroup> result = new ArrayList<>();
List<FileObject> sourceRoots = getFileObjects(rootURLs);
for (int i = 0; i < sourceRoots.size(); i++) {
FileObject sourceRoot = sourceRoots.get(i);
SourceGroup srcGroup = foldersToSourceGroupsMap.get(sourceRoot);
if (srcGroup != null) {
result.add(srcGroup);
}
}
return result;
}
private static List<FileObject> getFileObjects(URL[] urls) {
List<FileObject> result = new ArrayList<>();
for (int i = 0; i < urls.length; i++) {
FileObject sourceRoot = URLMapper.findFileObject(urls[i]);
if (sourceRoot != null) {
result.add(sourceRoot);
}
}
return result;
}
private static Set<SourceGroup> getTestSourceGroups(SourceGroup[] sourceGroups) {
Map<FileObject, SourceGroup> foldersToSourceGroupsMap = createFoldersToSourceGroupsMap(sourceGroups);
Set<SourceGroup> testGroups = new HashSet<>();
for (int i = 0; i < sourceGroups.length; i++) {
testGroups.addAll(getTestTargets(sourceGroups[i], foldersToSourceGroupsMap));
}
return testGroups;
}
}