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.File;
024import java.io.FileNotFoundException;
025import java.io.IOException;
026import java.io.RandomAccessFile;
027import java.nio.channels.FileChannel;
028import java.nio.channels.FileLock;
029import java.util.HashMap;
030import java.util.Map;
031import java.util.concurrent.atomic.AtomicBoolean;
032import java.util.concurrent.atomic.AtomicInteger;
033
034/**
035 * @author Olivier Lamy
036 * @since 2.0.0
037 */
038public class Lock
039{
040    private File file;
041
042    private AtomicBoolean write;
043
044    private final Map<Thread, AtomicInteger> fileClients = new HashMap<>();
045
046    private FileLock fileLock;
047
048    private RandomAccessFile randomAccessFile;
049
050    private FileChannel fileChannel;
051
052    public Lock( File file )
053    {
054        this.file = file;
055    }
056
057    public Lock( File file, boolean write )
058        throws FileNotFoundException
059    {
060        this.file = file;
061        this.write = new AtomicBoolean( write );
062        randomAccessFile = new RandomAccessFile( file, write ? "rw" : "r" );
063        fileChannel = randomAccessFile.getChannel();
064    }
065
066    public File getFile()
067    {
068        return file;
069    }
070
071    public AtomicBoolean isWrite()
072    {
073        return write;
074    }
075
076    public void setFile( File file )
077    {
078        this.file = file;
079    }
080
081    public void setWrite( boolean write )
082    {
083        this.write.set( write );
084    }
085
086    public boolean isShared()
087    {
088        return this.fileLock.isValid() && this.fileLock.isShared();
089    }
090
091    public boolean isValid()
092    {
093        return this.fileLock!=null && this.fileLock.isValid();
094    }
095
096    public Map<Thread, AtomicInteger> getFileClients()
097    {
098        return fileClients;
099    }
100
101    public void addFileClient( Thread thread )
102    {
103        this.fileClients.put( thread, new AtomicInteger( 1 ) );
104    }
105
106    public boolean removeFileClient( Thread thread )
107    {
108        return this.fileClients.remove( thread ) != null;
109    }
110
111    protected void close()
112        throws IOException
113    {
114        IOException ioException = null;
115        try
116        {
117            this.fileLock.release();
118        }
119        catch ( IOException e )
120        {
121            ioException = e;
122        }
123
124        closeQuietly( fileChannel );
125        closeQuietly( randomAccessFile );
126
127        fileClients.remove( Thread.currentThread() );
128
129        if ( ioException != null )
130        {
131            throw ioException;
132        }
133
134    }
135
136    protected void openLock( boolean write, boolean timeout )
137        throws IOException
138    {
139        fileClients.put( Thread.currentThread(), new AtomicInteger( 1 ) );
140
141        this.fileLock = timeout
142            ? fileChannel.tryLock( 0L, Long.MAX_VALUE, write ? false : true )
143            : fileChannel.lock( 0L, Long.MAX_VALUE, write ? false : true );
144
145    }
146
147    protected RandomAccessFile getRandomAccessFile()
148    {
149        return randomAccessFile;
150    }
151
152    private void closeQuietly( Closeable closeable )
153    {
154        try
155        {
156            closeable.close();
157        }
158        catch ( IOException e )
159        {
160            // ignore
161        }
162    }
163
164
165    @Override
166    public String toString()
167    {
168        final StringBuilder sb = new StringBuilder( "Lock{" );
169        sb.append( "file=" ).append( file );
170        sb.append( '}' );
171        return sb.toString();
172    }
173}