1 /*
2  * Copyright 2008-2019 by Emeric Vernat
3  *
4  *     This file is part of Java Melody.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18 package net.bull.javamelody.internal.model;
19
20 import java.io.File;
21 import java.io.IOException;
22 import java.io.RandomAccessFile;
23 import java.nio.channels.FileChannel;
24 import java.nio.channels.FileLock;
25 import java.nio.channels.OverlappingFileLockException;
26
27 import net.bull.javamelody.internal.common.Parameters;
28
29 /**
30  * Lock sur le répertoire de stockage pour détecter si des instances distinctes écrivent dans le même répertoire.
31  * @author Emeric Vernat
32  */

33 class StorageLock {
34     private static final String LOCK_FILENAME = "javamelody.lock";
35     private final File lockFile;
36     private RandomAccessFile input;
37     private FileChannel fileChannel;
38     private FileLock fileLock;
39
40     StorageLock(String application) {
41         this(new File(Parameters.getStorageDirectory(application), LOCK_FILENAME));
42     }
43
44     StorageLock(File lockFile) {
45         super();
46         this.lockFile = lockFile;
47         // initialize the lock
48         getFileLock();
49     }
50
51     void release() throws IOException {
52         try {
53             if (fileLock != null && fileLock.isValid()) {
54                 fileLock.release();
55             }
56         } finally {
57             try {
58                 if (fileChannel != null) {
59                     fileChannel.close();
60                 }
61             } finally {
62                 if (input != null) {
63                     input.close();
64                 }
65             }
66         }
67     }
68
69     private FileLock getFileLock() {
70         if (fileLock == null) {
71             try {
72                 final File storageDir = lockFile.getParentFile();
73                 if (!storageDir.mkdirs() && !storageDir.exists()) {
74                     return null;
75                 }
76                 if (input == null || fileChannel == null) {
77                     input = new RandomAccessFile(lockFile, "rw");
78                     fileChannel = input.getChannel();
79                 }
80                 fileLock = fileChannel.tryLock();
81             } catch (final IOException | OverlappingFileLockException e) {
82                 return null;
83             }
84         }
85         return fileLock;
86     }
87
88     boolean isAcquired() {
89         return getFileLock() != null && getFileLock().isValid();
90     }
91 }
92