001package org.eclipse.aether.synccontext; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.util.Collection; 023import java.util.concurrent.locks.Lock; 024import java.util.concurrent.locks.ReentrantReadWriteLock; 025 026import javax.annotation.Priority; 027import javax.inject.Named; 028import javax.inject.Singleton; 029 030import org.eclipse.aether.RepositorySystemSession; 031import org.eclipse.aether.SyncContext; 032import org.eclipse.aether.artifact.Artifact; 033import org.eclipse.aether.impl.SyncContextFactory; 034import org.eclipse.aether.metadata.Metadata; 035import org.slf4j.Logger; 036import org.slf4j.LoggerFactory; 037 038/** 039 * A singleton factory to create synchronization contexts using a global lock based on 040 * {@link ReentrantReadWriteLock}. Explicit artifacts and metadata passed are ignored. 041 * <p> 042 * <strong>Note: This component is still considered to be experimental, use with caution!</strong> 043 */ 044@Named 045@Priority( Integer.MAX_VALUE ) 046@Singleton 047public class GlobalSyncContextFactory 048 implements SyncContextFactory 049{ 050 private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); 051 052 public SyncContext newInstance( RepositorySystemSession session, boolean shared ) 053 { 054 return new GlobalSyncContext( shared ? lock.readLock() : lock.writeLock(), shared ); 055 } 056 057 static class GlobalSyncContext 058 implements SyncContext 059 { 060 private static final Logger LOGGER = LoggerFactory.getLogger( GlobalSyncContext.class ); 061 062 private final Lock lock; 063 private final boolean shared; 064 private int lockHoldCount; 065 066 private GlobalSyncContext( Lock lock, boolean shared ) 067 { 068 this.lock = lock; 069 this.shared = shared; 070 } 071 072 public void acquire( Collection<? extends Artifact> artifact, Collection<? extends Metadata> metadata ) 073 { 074 LOGGER.trace( "Acquiring global {} lock (currently held: {})", 075 shared ? "read" : "write", lockHoldCount ); 076 lock.lock(); 077 lockHoldCount++; 078 } 079 080 public void close() 081 { 082 while ( lockHoldCount > 0 ) 083 { 084 LOGGER.trace( "Releasing global {} lock (currently held: {})", 085 shared ? "read" : "write", lockHoldCount ); 086 lock.unlock(); 087 lockHoldCount--; 088 } 089 } 090 091 } 092 093}