| // 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; | |
| } | |
| } |