| // 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.BazelProjectSupport; |
| 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 = BazelProjectSupport.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 = BazelProjectSupport.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; |
| } |
| } |