1 /*******************************************************************************
2  * Copyright (c) 2004, 2013 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *     Danail Nachev (Prosyst) - bug 185654
14  *     Andrei Loskutov - bug 44735
15  *******************************************************************************/
16 package org.eclipse.osgi.internal.location;
17 
18 import java.io.*;
19 import java.nio.channels.FileLock;
20 import java.nio.channels.OverlappingFileLockException;
21 import org.eclipse.osgi.internal.messages.Msg;
22 import org.eclipse.osgi.util.NLS;
23 
24 /**
25  * Internal class.
26  */
27 public class Locker_JavaNio implements Locker {
28 	private final File lockFile;
29 	private final boolean debug;
30 	private FileLock fileLock;
31 	private RandomAccessFile raFile;
32 
Locker_JavaNio(File lockFile, boolean debug)33 	public Locker_JavaNio(File lockFile, boolean debug) {
34 		this.lockFile = lockFile;
35 		this.debug = debug;
36 	}
37 
38 	@Override
lock()39 	public synchronized boolean lock() throws IOException {
40 		raFile = new RandomAccessFile(lockFile, "rw"); //$NON-NLS-1$
41 		try {
42 			/*
43 			 * fix for bug http://bugs.sun.com/view_bug.do?bug_id=6628575 and
44 			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=44735#c17
45 			 */
46 			fileLock = raFile.getChannel().tryLock(0, 1, false);
47 		} catch (IOException ioe) {
48 			// print exception if debugging
49 			if (debug)
50 				System.out.println(NLS.bind(Msg.location_cannotLock, lockFile));
51 			// produce a more specific message for clients
52 			String specificMessage = NLS.bind(Msg.location_cannotLockNIO, new Object[] {lockFile, ioe.getMessage(), "\"-D" + LocationHelper.PROP_OSGI_LOCKING + "=none\""}); //$NON-NLS-1$ //$NON-NLS-2$
53 			throw new IOException(specificMessage);
54 		} catch (OverlappingFileLockException e) {
55 			// handle it as null result
56 			fileLock = null;
57 		} finally {
58 			if (fileLock != null)
59 				return true;
60 			raFile.close();
61 			raFile = null;
62 		}
63 		return false;
64 	}
65 
66 	@Override
release()67 	public synchronized void release() {
68 		if (fileLock != null) {
69 			try {
70 				fileLock.release();
71 			} catch (IOException e) {
72 				//don't complain, we're making a best effort to clean up
73 			}
74 			fileLock = null;
75 		}
76 		if (raFile != null) {
77 			try {
78 				raFile.close();
79 			} catch (IOException e) {
80 				//don't complain, we're making a best effort to clean up
81 			}
82 			raFile = null;
83 		}
84 	}
85 
86 	@Override
isLocked()87 	public synchronized boolean isLocked() throws IOException {
88 		if (fileLock != null)
89 			return true;
90 		try {
91 			RandomAccessFile temp = new RandomAccessFile(lockFile, "rw"); //$NON-NLS-1$
92 			FileLock tempLock = null;
93 			try {
94 				/*
95 				 * fix for bug http://bugs.sun.com/view_bug.do?bug_id=6628575 and
96 				 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=44735#c17
97 				 */
98 				try {
99 					tempLock = temp.getChannel().tryLock(0, 1, false);
100 				} catch (IOException ioe) {
101 					if (debug)
102 						System.out.println(NLS.bind(Msg.location_cannotLock, lockFile));
103 					// produce a more specific message for clients
104 					String specificMessage = NLS.bind(Msg.location_cannotLockNIO, new Object[] {lockFile, ioe.getMessage(), "\"-D" + LocationHelper.PROP_OSGI_LOCKING + "=none\""}); //$NON-NLS-1$ //$NON-NLS-2$
105 					throw new IOException(specificMessage);
106 				}
107 				if (tempLock != null) {
108 					tempLock.release(); // allow IOException to propagate because that would mean it is still locked
109 					return false;
110 				}
111 				return true;
112 			} catch (OverlappingFileLockException e) {
113 				return true;
114 			} finally {
115 				temp.close();
116 			}
117 		} catch (FileNotFoundException e) {
118 			return false;
119 		}
120 	}
121 }
122