View Javadoc
1   package org.eclipse.aether.named.providers;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.IOException;
23  import java.io.UncheckedIOException;
24  import java.nio.channels.FileChannel;
25  import java.nio.file.Files;
26  import java.nio.file.Path;
27  import java.nio.file.Paths;
28  import java.nio.file.StandardOpenOption;
29  import java.util.concurrent.ConcurrentHashMap;
30  import java.util.concurrent.ConcurrentMap;
31  
32  import javax.inject.Named;
33  import javax.inject.Singleton;
34  
35  import org.eclipse.aether.named.support.FileLockNamedLock;
36  import org.eclipse.aether.named.support.FileSystemFriendly;
37  import org.eclipse.aether.named.support.NamedLockFactorySupport;
38  import org.eclipse.aether.named.support.NamedLockSupport;
39  
40  /**
41   * Named locks factory of {@link FileLockNamedLock}s. This is a bit special implementation, as it
42   * expects locks names to be fully qualified absolute file system paths.
43   *
44   * @since 1.7.3
45   */
46  @Singleton
47  @Named( FileLockNamedLockFactory.NAME )
48  public class FileLockNamedLockFactory
49      extends NamedLockFactorySupport
50      implements FileSystemFriendly
51  {
52      public static final String NAME = "file-lock";
53  
54      private final ConcurrentMap<String, FileChannel> fileChannels;
55  
56      public FileLockNamedLockFactory()
57      {
58          this.fileChannels = new ConcurrentHashMap<>();
59      }
60  
61      @Override
62      protected NamedLockSupport createLock( final String name )
63      {
64          Path path = Paths.get( name );
65          FileChannel fileChannel = fileChannels.computeIfAbsent( name, k ->
66          {
67              try
68              {
69                  Files.createDirectories( path.getParent() );
70                  return FileChannel.open(
71                          path,
72                          StandardOpenOption.READ, StandardOpenOption.WRITE,
73                          StandardOpenOption.CREATE, StandardOpenOption.DELETE_ON_CLOSE
74                  );
75              }
76              catch ( IOException e )
77              {
78                  throw new UncheckedIOException( "Failed to open file channel for '"
79                      + name + "'", e );
80              }
81          } );
82          return new FileLockNamedLock( name, fileChannel, this );
83      }
84  
85      @Override
86      protected void destroyLock( final String name )
87      {
88          FileChannel fileChannel = fileChannels.remove( name );
89          if ( fileChannel == null )
90          {
91              throw new IllegalStateException( "File channel expected, but does not exist: " + name );
92          }
93  
94          try
95          {
96              fileChannel.close();
97          }
98          catch ( IOException e )
99          {
100             throw new UncheckedIOException( "Failed to close file channel for '"
101                     + name + "'", e );
102         }
103     }
104 }