/*******************************************************************************
* Copyright (c) 2006-2015
* Software Technology Group, Dresden University of Technology
* DevBoost GmbH, Dresden, Amtsgericht Dresden, HRB 34001
*
* 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:
* Software Technology Group - TU Dresden, Germany;
* DevBoost GmbH - Dresden, Germany
* - initial API and implementation
******************************************************************************/
package de.devboost.buildboost.discovery;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import de.devboost.buildboost.BuildException;
import de.devboost.buildboost.artifacts.InvalidMetadataException;
import de.devboost.buildboost.artifacts.Plugin;
import de.devboost.buildboost.model.BuildEventType;
import de.devboost.buildboost.model.IArtifact;
import de.devboost.buildboost.model.IBuildContext;
import de.devboost.buildboost.model.IBuildListener;
import de.devboost.buildboost.util.ArtifactUtil;
import de.devboost.buildboost.util.EclipsePluginHelper;
/**
* A {@link PluginFinder} can be used to discover Eclipse plug-in projects. Such projects typically contain a file
* called '.project'.
*
* TODO inherit from {@link AbstractFileFinder}?
*/
public class PluginFinder extends AbstractArtifactDiscoverer {
private final File directory;
public PluginFinder(File directory) {
this.directory = directory;
}
public Collection<IArtifact> discoverArtifacts(IBuildContext context) throws BuildException {
IBuildListener buildListener = context.getBuildListener();
Collection<File> allProjectDirs = findProjectDirs(directory, buildListener);
allProjectDirs = sortByPathName(allProjectDirs);
checkForDuplicates(allProjectDirs, buildListener);
Set<IArtifact> allPlugins = convertToPlugins(allProjectDirs, context.getBuildListener());
// make unmodifiable
return Collections.unmodifiableSet(new ArtifactUtil().getSetOfArtifacts(allPlugins));
}
private Set<File> findProjectDirs(File directory, IBuildListener buildListener) {
Set<File> projectDirs = new LinkedHashSet<File>();
if (!directory.exists()) {
buildListener.handleBuildEvent(BuildEventType.ERROR, "Directory " + directory.getAbsolutePath()
+ " does not exist.");
return projectDirs;
}
if (!directory.isDirectory()) {
buildListener.handleBuildEvent(BuildEventType.ERROR, "File " + directory.getAbsolutePath()
+ " is not a directory.");
return projectDirs;
}
boolean isProject = EclipsePluginHelper.INSTANCE.isProject(directory);
if (isProject) {
projectDirs.add(directory);
// do not examine children of projects
return projectDirs;
}
// dive into child directories
File[] children = directory.listFiles();
if (children == null) {
return projectDirs;
}
for (File child : children) {
if (!child.isDirectory()) {
continue;
}
projectDirs.addAll(findProjectDirs(child, buildListener));
}
return projectDirs;
}
private Collection<File> sortByPathName(Collection<File> allProjectDirs) {
List<File> unsorted = new ArrayList<File>();
unsorted.addAll(allProjectDirs);
Collections.sort(unsorted, new Comparator<File>() {
public int compare(File file1, File file2) {
String path1 = file1.getAbsolutePath();
String path2 = file2.getAbsolutePath();
return path1.compareTo(path2);
}
});
return unsorted;
}
private void checkForDuplicates(Collection<File> allProjectDirs, IBuildListener listener) {
// check whether there are multiple projects with the same name
for (File projectDir : allProjectDirs) {
for (File otherDir : allProjectDirs) {
if (projectDir == otherDir) {
continue;
}
if (otherDir.getName().equals(projectDir.getName())) {
listener.handleBuildEvent(BuildEventType.WARNING, "Found plug-ins with duplicate name at: "
+ projectDir.getAbsolutePath() + " and " + otherDir.getAbsolutePath());
}
}
}
}
private Set<IArtifact> convertToPlugins(Collection<File> projectDirs, IBuildListener listener)
throws BuildException {
Set<IArtifact> pluginsAndExportedPackages = new LinkedHashSet<IArtifact>();
for (File projectDir : projectDirs) {
Plugin newPlugin;
try {
newPlugin = new Plugin(projectDir);
} catch (IOException e) {
throw new BuildException(e.getMessage());
} catch (InvalidMetadataException e) {
// Skip plug-ins with invalid meta data
continue;
}
if (newPlugin.isExperimental()) {
listener.handleBuildEvent(BuildEventType.INFO,
"Ignoring EXPERIMENTAL project: " + newPlugin.getIdentifier());
continue;
}
if (newPlugin.getSourceFolders().length == 0) {
listener.handleBuildEvent(BuildEventType.INFO,
"Project without source folders: " + newPlugin.getIdentifier());
}
listener.handleBuildEvent(BuildEventType.INFO, "Discovered project: " + newPlugin.getIdentifier());
pluginsAndExportedPackages.add(newPlugin);
pluginsAndExportedPackages.addAll(newPlugin.getExportedPackages());
}
return pluginsAndExportedPackages;
}
@Override
public String toString() {
return getClass().getSimpleName() + " [" + directory.getAbsolutePath() + "]";
}
}