001package org.eclipse.aether.named.hazelcast; 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 com.hazelcast.core.HazelcastInstance; 023import com.hazelcast.cp.ISemaphore; 024import org.eclipse.aether.named.support.AdaptedSemaphoreNamedLock; 025import org.eclipse.aether.named.support.AdaptedSemaphoreNamedLock.AdaptedSemaphore; 026import org.eclipse.aether.named.support.NamedLockFactorySupport; 027 028import java.util.concurrent.ConcurrentHashMap; 029import java.util.concurrent.ConcurrentMap; 030import java.util.concurrent.TimeUnit; 031import java.util.function.BiFunction; 032 033/** 034 * Factory of {@link AdaptedSemaphoreNamedLock} instances using adapted Hazelcast {@link ISemaphore}. This class may 035 * use {@link HazelcastInstance} backed by Hazelcast Server or Hazelcast Client. 036 */ 037public class HazelcastSemaphoreNamedLockFactory 038 extends NamedLockFactorySupport 039{ 040 protected static final String NAME_PREFIX = "maven:resolver:"; 041 042 private final HazelcastInstance hazelcastInstance; 043 044 private final BiFunction<HazelcastInstance, String, ISemaphore> semaphoreFunction; 045 046 private final boolean destroySemaphore; 047 048 private final boolean manageHazelcast; 049 050 private final ConcurrentMap<String, ISemaphore> semaphores; 051 052 public HazelcastSemaphoreNamedLockFactory( 053 final HazelcastInstance hazelcastInstance, 054 final BiFunction<HazelcastInstance, String, ISemaphore> semaphoreFunction, 055 final boolean destroySemaphore, 056 final boolean manageHazelcast 057 ) 058 { 059 this.hazelcastInstance = hazelcastInstance; 060 this.semaphoreFunction = semaphoreFunction; 061 this.destroySemaphore = destroySemaphore; 062 this.manageHazelcast = manageHazelcast; 063 this.semaphores = new ConcurrentHashMap<>(); 064 } 065 066 @Override 067 protected AdaptedSemaphoreNamedLock createLock( final String name ) 068 { 069 ISemaphore semaphore = semaphores.computeIfAbsent( name, k -> 070 { 071 ISemaphore result = semaphoreFunction.apply( hazelcastInstance, k ); 072 result.init( Integer.MAX_VALUE ); 073 return result; 074 } ); 075 return new AdaptedSemaphoreNamedLock( name, this, new HazelcastSemaphore( semaphore ) ); 076 } 077 078 @Override 079 public void shutdown() 080 { 081 if ( manageHazelcast ) 082 { 083 hazelcastInstance.shutdown(); 084 } 085 } 086 087 @Override 088 protected void destroyLock( final String name ) 089 { 090 ISemaphore semaphore = semaphores.remove( name ); 091 if ( destroySemaphore ) 092 { 093 if ( semaphore == null ) 094 { 095 throw new IllegalStateException( "Semaphore expected but does not exist: " + name ); 096 } 097 semaphore.destroy(); 098 } 099 } 100 101 private static final class HazelcastSemaphore implements AdaptedSemaphore 102 { 103 private final ISemaphore semaphore; 104 105 private HazelcastSemaphore( final ISemaphore semaphore ) 106 { 107 this.semaphore = semaphore; 108 } 109 110 @Override 111 public boolean tryAcquire( final int perms, final long time, final TimeUnit unit ) 112 throws InterruptedException 113 { 114 return semaphore.tryAcquire( perms, time, unit ); 115 } 116 117 @Override 118 public void release( final int perms ) 119 { 120 semaphore.release( perms ); 121 } 122 } 123}