| /* |
| * 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.idea.blaze.base.sync.libraries; |
| |
| import com.google.common.collect.Lists; |
| import com.google.common.collect.Sets; |
| import com.google.idea.blaze.base.model.BlazeLibrary; |
| import com.google.idea.blaze.base.model.BlazeProjectData; |
| import com.google.idea.blaze.base.model.LibraryKey; |
| import com.google.idea.blaze.base.scope.BlazeContext; |
| import com.google.idea.blaze.base.scope.output.PrintOutput; |
| import com.google.idea.blaze.base.sync.BlazeSyncPlugin; |
| import com.google.idea.blaze.base.sync.workspace.ArtifactLocationDecoder; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.roots.ModifiableRootModel; |
| import com.intellij.openapi.roots.OrderRootType; |
| import com.intellij.openapi.roots.impl.libraries.ProjectLibraryTable; |
| import com.intellij.openapi.roots.libraries.Library; |
| import com.intellij.openapi.roots.libraries.LibraryTable; |
| import java.util.Collection; |
| import java.util.List; |
| import java.util.Objects; |
| import java.util.Set; |
| import java.util.function.Predicate; |
| import java.util.stream.Collectors; |
| |
| /** Edits IntelliJ libraries */ |
| public class LibraryEditor { |
| private static final Logger LOG = Logger.getInstance(LibraryEditor.class); |
| |
| public static void updateProjectLibraries( |
| Project project, |
| BlazeContext context, |
| BlazeProjectData blazeProjectData, |
| Collection<BlazeLibrary> libraries) { |
| Set<LibraryKey> intelliJLibraryState = Sets.newHashSet(); |
| for (Library library : ProjectLibraryTable.getInstance(project).getLibraries()) { |
| String name = library.getName(); |
| if (name != null) { |
| intelliJLibraryState.add(LibraryKey.fromIntelliJLibraryName(name)); |
| } |
| } |
| context.output(PrintOutput.log(String.format("Workspace has %d libraries", libraries.size()))); |
| |
| LibraryTable libraryTable = ProjectLibraryTable.getInstance(project); |
| LibraryTable.ModifiableModel libraryTableModel = libraryTable.getModifiableModel(); |
| try { |
| for (BlazeLibrary library : libraries) { |
| updateLibrary( |
| project, |
| blazeProjectData.artifactLocationDecoder, |
| libraryTable, |
| libraryTableModel, |
| library); |
| } |
| |
| // Garbage collect unused libraries |
| List<LibrarySource> librarySources = Lists.newArrayList(); |
| for (BlazeSyncPlugin syncPlugin : BlazeSyncPlugin.EP_NAME.getExtensions()) { |
| LibrarySource librarySource = syncPlugin.getLibrarySource(blazeProjectData); |
| if (librarySource != null) { |
| librarySources.add(librarySource); |
| } |
| } |
| Predicate<Library> gcRetentionFilter = |
| librarySources |
| .stream() |
| .map(LibrarySource::getGcRetentionFilter) |
| .filter(Objects::nonNull) |
| .reduce(Predicate::or) |
| .orElse(o -> false); |
| |
| Set<LibraryKey> newLibraryKeys = |
| libraries.stream().map((blazeLibrary) -> blazeLibrary.key).collect(Collectors.toSet()); |
| for (LibraryKey libraryKey : intelliJLibraryState) { |
| String libraryIntellijName = libraryKey.getIntelliJLibraryName(); |
| if (!newLibraryKeys.contains(libraryKey)) { |
| Library library = libraryTable.getLibraryByName(libraryIntellijName); |
| if (!gcRetentionFilter.test(library)) { |
| if (library != null) { |
| libraryTableModel.removeLibrary(library); |
| } |
| } |
| } |
| } |
| } finally { |
| libraryTableModel.commit(); |
| } |
| } |
| |
| public static void updateLibrary( |
| Project project, |
| ArtifactLocationDecoder artifactLocationDecoder, |
| LibraryTable libraryTable, |
| LibraryTable.ModifiableModel libraryTableModel, |
| BlazeLibrary blazeLibrary) { |
| String libraryName = blazeLibrary.key.getIntelliJLibraryName(); |
| |
| Library library = libraryTable.getLibraryByName(libraryName); |
| boolean libraryExists = library != null; |
| if (!libraryExists) { |
| library = libraryTableModel.createLibrary(libraryName); |
| } |
| Library.ModifiableModel libraryModel = library.getModifiableModel(); |
| if (libraryExists) { |
| for (String url : libraryModel.getUrls(OrderRootType.CLASSES)) { |
| libraryModel.removeRoot(url, OrderRootType.CLASSES); |
| } |
| for (String url : libraryModel.getUrls(OrderRootType.SOURCES)) { |
| libraryModel.removeRoot(url, OrderRootType.SOURCES); |
| } |
| } |
| try { |
| blazeLibrary.modifyLibraryModel(project, artifactLocationDecoder, libraryModel); |
| } finally { |
| libraryModel.commit(); |
| } |
| } |
| |
| public static void configureDependencies( |
| ModifiableRootModel modifiableRootModel, Collection<BlazeLibrary> libraries) { |
| for (BlazeLibrary library : libraries) { |
| updateLibraryDependency(modifiableRootModel, library.key); |
| } |
| } |
| |
| private static void updateLibraryDependency(ModifiableRootModel model, LibraryKey libraryKey) { |
| LibraryTable libraryTable = ProjectLibraryTable.getInstance(model.getProject()); |
| Library library = libraryTable.getLibraryByName(libraryKey.getIntelliJLibraryName()); |
| if (library == null) { |
| LOG.error( |
| "Library missing: " |
| + libraryKey.getIntelliJLibraryName() |
| + ". Please resync project to resolve."); |
| return; |
| } |
| model.addLibraryEntry(library); |
| } |
| } |