blob: bdd0082b3e0b27eb2f06667f5c97b3c69416be8d [file] [log] [blame]
// Copyright 2016 The Bazel Authors. All rights reserved.
//
// Licensed 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 com.google.devtools.bazel.e4b.classpath;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.osgi.service.prefs.BackingStoreException;
import com.google.devtools.bazel.e4b.Activator;
import com.google.devtools.bazel.e4b.command.BazelCommand.BazelInstance;
import com.google.devtools.bazel.e4b.command.BazelNotFoundException;
import com.google.devtools.bazel.e4b.command.IdeBuildInfo;
import com.google.devtools.bazel.e4b.command.IdeBuildInfo.Jars;
public class BazelClasspathContainer implements IClasspathContainer {
public static final String CONTAINER_NAME = "com.google.devtools.bazel.e4b.BAZEL_CONTAINER";
private final IPath path;
private final IJavaProject project;
private final BazelInstance instance;
public BazelClasspathContainer(IPath path, IJavaProject project)
throws IOException, InterruptedException, BackingStoreException, JavaModelException,
BazelNotFoundException {
this.path = path;
this.project = project;
this.instance = Activator.getBazelCommandInstance(project.getProject());
}
private boolean isSourcePath(String path) throws JavaModelException, BackingStoreException {
Path pp = new File(instance.getWorkspaceRoot().toString() + File.separator + path).toPath();
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
for (IClasspathEntry entry : project.getRawClasspath()) {
if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
IResource res = root.findMember(entry.getPath());
if (res != null) {
String file = res.getLocation().toOSString();
if (!file.isEmpty() && pp.startsWith(file)) {
IPath[] inclusionPatterns = entry.getInclusionPatterns();
if (!matchPatterns(pp, entry.getExclusionPatterns()) && (inclusionPatterns == null
|| inclusionPatterns.length == 0 || matchPatterns(pp, inclusionPatterns))) {
return true;
}
}
}
}
}
return false;
}
private boolean matchPatterns(Path path, IPath[] patterns) {
if (patterns != null) {
for (IPath p : patterns) {
PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:" + p.toOSString());
if (matcher.matches(path)) {
return true;
}
}
}
return false;
}
private boolean isSourceInPaths(List<String> sources)
throws JavaModelException, BackingStoreException {
for (String s : sources) {
if (isSourcePath(s)) {
return true;
}
}
return false;
}
@Override
public IClasspathEntry[] getClasspathEntries() {
try {
List<String> targets = Activator.getTargets(project.getProject());
Map<String, IdeBuildInfo> infos = instance.getIdeInfo(targets);
Set<Jars> jars = new HashSet<>();
for (IdeBuildInfo s : infos.values()) {
jars.addAll(s.getGeneratedJars());
if (!isSourceInPaths(s.getSources())) {
jars.addAll(s.getJars());
}
}
return jarsToClasspathEntries(jars);
} catch (JavaModelException | BackingStoreException | IOException | InterruptedException e) {
Activator.error("Unable to compute classpath containers entries.", e);
return new IClasspathEntry[] {};
} catch (BazelNotFoundException e) {
Activator.error("Bazel not found: " + e.getMessage());
return new IClasspathEntry[] {};
}
}
private IClasspathEntry[] jarsToClasspathEntries(Set<Jars> jars) {
IClasspathEntry[] entries = new IClasspathEntry[jars.size()];
int i = 0;
File execRoot = instance.getExecRoot();
for (Jars j : jars) {
entries[i] = JavaCore.newLibraryEntry(getJarIPath(execRoot, j.getJar()),
getJarIPath(execRoot, j.getSrcJar()), null);
i++;
}
return entries;
}
private static IPath getJarIPath(File execRoot, String file) {
if (file == null) {
return null;
}
File path = new File(execRoot, file);
return org.eclipse.core.runtime.Path.fromOSString(path.toString());
}
@Override
public String getDescription() {
return "Bazel Classpath Container";
}
@Override
public int getKind() {
return K_APPLICATION;
}
@Override
public IPath getPath() {
return path;
}
public boolean isValid() {
return instance != null;
}
}