This project has retired. For details please refer to its Attic page.
Lock xref
View Javadoc
1   package org.apache.archiva.common.filelock;
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.Closeable;
23  import java.io.IOException;
24  import java.nio.channels.FileChannel;
25  import java.nio.channels.FileLock;
26  import java.nio.file.Path;
27  import java.nio.file.StandardOpenOption;
28  import java.util.HashMap;
29  import java.util.Map;
30  import java.util.concurrent.atomic.AtomicBoolean;
31  import java.util.concurrent.atomic.AtomicInteger;
32  
33  /**
34   * @author Olivier Lamy
35   * @since 2.0.0
36   */
37  public class Lock implements Closeable
38  {
39      private Path file;
40  
41      private AtomicBoolean write;
42  
43      private final Map<Thread, AtomicInteger> fileClients = new HashMap<>();
44  
45      private FileLock fileLock;
46  
47      private FileChannel fileChannel;
48  
49      public Lock( Path file )
50      {
51          this.file = file;
52      }
53  
54      public Lock( Path file, boolean write )
55              throws IOException
56      {
57          this.file = file;
58          this.write = new AtomicBoolean( write );
59          fileChannel = write ? FileChannel.open(file, StandardOpenOption.WRITE, StandardOpenOption.READ) : FileChannel.open(file, StandardOpenOption.READ);
60      }
61  
62      public Path getFile()
63      {
64          return file;
65      }
66  
67      public AtomicBoolean isWrite()
68      {
69          return write;
70      }
71  
72      public void setFile( Path file )
73      {
74          this.file = file;
75      }
76  
77      public void setWrite( boolean write )
78      {
79          this.write.set( write );
80      }
81  
82      public boolean isShared()
83      {
84          return this.fileLock.isValid() && this.fileLock.isShared();
85      }
86  
87      public boolean isValid()
88      {
89          return this.fileLock!=null && this.fileLock.isValid();
90      }
91  
92      public Map<Thread, AtomicInteger> getFileClients()
93      {
94          return fileClients;
95      }
96  
97      public void addFileClient( Thread thread )
98      {
99          this.fileClients.put( thread, new AtomicInteger( 1 ) );
100     }
101 
102     public boolean removeFileClient( Thread thread )
103     {
104         return this.fileClients.remove( thread ) != null;
105     }
106 
107     public void close()
108         throws IOException
109     {
110         IOException ioException = null;
111         try
112         {
113             if (this.fileLock!=null) {
114                 this.fileLock.release();
115             }
116         }
117         catch ( IOException e )
118         {
119             ioException = e;
120         } finally {
121             closeQuietly( fileChannel );
122             fileClients.remove( Thread.currentThread() );
123         }
124 
125         if ( ioException != null )
126         {
127             throw ioException;
128         }
129 
130     }
131 
132     protected void openLock( boolean write, boolean timeout )
133         throws IOException
134     {
135         fileClients.put( Thread.currentThread(), new AtomicInteger( 1 ) );
136 
137         this.fileLock = timeout
138             ? fileChannel.tryLock( 0L, Long.MAX_VALUE, write ? false : true )
139             : fileChannel.lock( 0L, Long.MAX_VALUE, write ? false : true );
140 
141     }
142 
143 
144 
145     private void closeQuietly( Closeable closeable )
146     {
147         try
148         {
149             closeable.close();
150         }
151         catch ( IOException e )
152         {
153             // ignore
154         }
155     }
156 
157 
158     @Override
159     public String toString()
160     {
161         final StringBuilder sb = new StringBuilder( "Lock{" );
162         sb.append( "file=" ).append( file );
163         sb.append( '}' );
164         return sb.toString();
165     }
166 }