| /* |
| * Copyright 2000-2009 JetBrains s.r.o. |
| * |
| * 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 org.jetbrains.idea.maven.server.embedder; |
| |
| import gnu.trove.THashMap; |
| import org.apache.maven.artifact.Artifact; |
| import org.apache.maven.artifact.manager.DefaultWagonManager; |
| import org.apache.maven.artifact.metadata.ArtifactMetadata; |
| import org.apache.maven.artifact.repository.ArtifactRepository; |
| import org.apache.maven.wagon.ResourceDoesNotExistException; |
| import org.apache.maven.wagon.TransferFailedException; |
| import org.apache.maven.wagon.WagonException; |
| import org.jetbrains.idea.maven.server.UnresolvedArtifactsCollector; |
| |
| import java.io.File; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.concurrent.locks.Lock; |
| import java.util.concurrent.locks.ReentrantReadWriteLock; |
| |
| public class CustomMaven3WagonManager extends DefaultWagonManager { |
| private UnresolvedArtifactsCollector myUnresolvedCollector; |
| |
| private final ThreadLocal<Boolean> myInBatchResolve = new ThreadLocal<Boolean>(); |
| private final Map<String, Boolean> myResolutionCache = new THashMap<String, Boolean>(); |
| |
| private final ReentrantReadWriteLock myCacheLock = new ReentrantReadWriteLock(); |
| private final Lock myCacheReadLock = myCacheLock.readLock(); |
| private final Lock myCacheWriteLock = myCacheLock.writeLock(); |
| |
| public void customize(boolean failOnUnresolved) { |
| myUnresolvedCollector = new UnresolvedArtifactsCollector(failOnUnresolved); |
| } |
| |
| public void reset() { |
| // todo todo clear cache too?? |
| myUnresolvedCollector = null; |
| } |
| |
| public UnresolvedArtifactsCollector getUnresolvedCollector() { |
| return myUnresolvedCollector; |
| } |
| |
| @Override |
| public void getArtifact(Artifact artifact, List remoteRepositories) throws TransferFailedException, ResourceDoesNotExistException { |
| myInBatchResolve.set(Boolean.TRUE); |
| try { |
| if (!takeFromCache(artifact)) { |
| try { |
| super.getArtifact(artifact, remoteRepositories); |
| } |
| catch (WagonException ignore) { |
| } |
| cache(artifact); |
| myUnresolvedCollector.collectAndSetResolved(artifact); |
| } |
| } |
| finally { |
| myInBatchResolve.set(Boolean.FALSE); |
| } |
| } |
| |
| @Override |
| public void getArtifact(Artifact artifact, ArtifactRepository repository) throws TransferFailedException, ResourceDoesNotExistException { |
| if (myInBatchResolve.get() == Boolean.TRUE) { |
| super.getArtifact(artifact, repository); |
| return; |
| } |
| |
| if (!takeFromCache(artifact)) { |
| try { |
| super.getArtifact(artifact, repository); |
| } |
| catch (WagonException ignore) { |
| } |
| cache(artifact); |
| myUnresolvedCollector.collectAndSetResolved(artifact); |
| } |
| } |
| |
| @Override |
| public void getArtifactMetadata(ArtifactMetadata metadata, ArtifactRepository repository, File destination, String checksumPolicy) |
| throws TransferFailedException, ResourceDoesNotExistException { |
| // todo use cache here |
| super.getArtifactMetadata(metadata, repository, destination, checksumPolicy); |
| } |
| |
| @Override |
| public void getArtifactMetadataFromDeploymentRepository(ArtifactMetadata metadata, |
| ArtifactRepository repository, |
| File destination, |
| String checksumPolicy) throws TransferFailedException, |
| ResourceDoesNotExistException { |
| // todo use cache here |
| super.getArtifactMetadataFromDeploymentRepository(metadata, repository, destination, checksumPolicy); |
| } |
| |
| private boolean takeFromCache(Artifact artifact) { |
| String key = getKey(artifact); |
| |
| Boolean wasResolved; |
| myCacheReadLock.lock(); |
| try { |
| wasResolved = myResolutionCache.get(key); |
| if (wasResolved == null) return false; |
| } |
| finally { |
| myCacheReadLock.unlock(); |
| } |
| |
| boolean fileWasDeleted = wasResolved && !artifact.getFile().exists(); |
| if (fileWasDeleted) { |
| myCacheWriteLock.lock(); |
| try { |
| myResolutionCache.remove(key); |
| } |
| finally { |
| myCacheWriteLock.unlock(); |
| } |
| return false; // need to resolve again |
| } |
| |
| artifact.setResolved(wasResolved); |
| |
| return true; |
| } |
| |
| private void cache(Artifact artifact) { |
| String key = getKey(artifact); |
| |
| myCacheWriteLock.lock(); |
| try { |
| myResolutionCache.put(key, artifact.isResolved()); |
| } |
| finally { |
| myCacheWriteLock.unlock(); |
| } |
| } |
| |
| private String getKey(Artifact artifact) { |
| return artifact.getGroupId() |
| + ":" + artifact.getArtifactId() |
| + ":" + artifact.getType() |
| + ":" + artifact.getVersion() |
| + ":" + artifact.getClassifier(); |
| } |
| } |