This project has retired. For details please refer to its Attic page.
Source code
001package org.apache.archiva.common.filelock;
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.io.Closeable;
023import java.io.IOException;
024import java.nio.channels.FileChannel;
025import java.nio.channels.FileLock;
026import java.nio.file.Path;
027import java.nio.file.StandardOpenOption;
028import java.util.HashMap;
029import java.util.Map;
030import java.util.concurrent.atomic.AtomicBoolean;
031import java.util.concurrent.atomic.AtomicInteger;
032
033/**
034 * @author Olivier Lamy
035 * @since 2.0.0
036 */
037public class Lock implements Closeable
038{
039    private Path file;
040
041    private AtomicBoolean write;
042
043    private final Map<Thread, AtomicInteger> fileClients = new HashMap<>();
044
045    private FileLock fileLock;
046
047    private FileChannel fileChannel;
048
049    public Lock( Path file )
050    {
051        this.file = file;
052    }
053
054    public Lock( Path file, boolean write )
055            throws IOException
056    {
057        this.file = file;
058        this.write = new AtomicBoolean( write );
059        fileChannel = write ? FileChannel.open(file, StandardOpenOption.WRITE, StandardOpenOption.READ) : FileChannel.open(file, StandardOpenOption.READ);
060    }
061
062    public Path getFile()
063    {
064        return file;
065    }
066
067    public AtomicBoolean isWrite()
068    {
069        return write;
070    }
071
072    public void setFile( Path file )
073    {
074        this.file = file;
075    }
076
077    public void setWrite( boolean write )
078    {
079        this.write.set( write );
080    }
081
082    public boolean isShared()
083    {
084        return this.fileLock.isValid() && this.fileLock.isShared();
085    }
086
087    public boolean isValid()
088    {
089        return this.fileLock!=null && this.fileLock.isValid();
090    }
091
092    public Map<Thread, AtomicInteger> getFileClients()
093    {
094        return fileClients;
095    }
096
097    public void addFileClient( Thread thread )
098    {
099        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}