-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Breaking API name changes - Improved JavaDoc - Refactoring - Added mvnw executable for Linux and Mac
- Loading branch information
Showing
23 changed files
with
532 additions
and
200 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
target/ | ||
!.mvn/wrapper/maven-wrapper.jar | ||
.mvn/wrapper/maven-wrapper.jar | ||
|
||
### STS ### | ||
.apt_generated | ||
|
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,82 +1,83 @@ | ||
# AppLocker | ||
[![Build Status](https://travis-ci.com/sanyarnd/applocker.svg?branch=master)](https://travis-ci.com/sanyarnd/applocker) | ||
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=io.github.sanyarnd%3Aapp-locker&metric=coverage)](https://sonarcloud.io/dashboard?id=io.github.sanyarnd%3Aapp-locker) | ||
[![Download](https://api.bintray.com/packages/sanya-rnd/maven-projects/applocker/images/download.svg)](https://bintray.com/sanya-rnd/maven-projects/applocker/_latestVersion) | ||
[![FOSSA Status](https://app.fossa.com/api/projects/custom%2B8815%2Fgithub.com%2Fsanyarnd%2Fapplocker.svg?type=shield)](https://app.fossa.com/projects/custom%2B8815%2Fgithub.com%2Fsanyarnd%2Fapplocker?ref=badge_shield) | ||
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) | ||
|
||
AppLocker library adds single instance application functionality, allowing exactly 1 running instance of the application. | ||
|
||
Library is compatible with any JDK8+ version. | ||
|
||
Library has very small footprint (20-30kb) and zero dependencies. | ||
AppLocker library provides single instance functionality, allowing exactly 1 running instance of your application. | ||
|
||
# Features | ||
* File-system based locking mechanism | ||
* IPC: optional communication between already running application and any process which is trying to acquire the same lock | ||
|
||
# Download | ||
|
||
Visit [releases page](https://github.com/sanyarnd/applocker/releases) or [bintray artifactory](https://bintray.com/sanya-rnd/maven-projects/applocker). | ||
* Safe: based on file channel locking, lock will be released even in case of power outrage | ||
* Can communicate with instance which's acquired the lock | ||
* Small memory footprint (~20kb) | ||
* No transitive dependencies | ||
* JDK8+ support | ||
|
||
# How to use | ||
Handlers: | ||
# Usage | ||
Get the `AppLocker`: | ||
```java | ||
AppLocker locker = AppLocker.create("lockID") | ||
.setPath(Paths.get(".")) // where to store locks (default: ".") | ||
.setIdEncoder(this::encode) // how to encode lock files (default: "SHA-1") | ||
.setMessageHandler(e -> e) // handle messages which are sent with locker#send or #onBusy (default: NULL) | ||
.build(); // create instance | ||
``` | ||
public void main() { | ||
final AppLocker locker = AppLocker.create("Unique Lock ID") // identify your application | ||
.setPath(Paths.get("path/to/store/locks")) // we can decide where to store locks (".", ".cache" etc) | ||
.busy(LockMessage.TO_FRONT, this::closeApp) // handles situations, like: failed to lock because `Unique Lock ID` is already taken | ||
.setMessageHandler((LockMessage msg) -> { // message handler will recieve messages from `.busy` and answer back | ||
if (msg == LockMessage.TO_FRONT) { // there is only one active message handler for each lock id | ||
Ui.run(...); | ||
} | ||
return LockMessage.CLOSE; // return answer | ||
}) | ||
.failed(this::logAndExit) // handles situations, like: provided path for lock storage is non-writable by user, also handles `busy error` if busy handler is missing | ||
.acquired(this::logLockAcquiring) // callback function, which is called if acquiring the lock was successful | ||
.build(); // create AppLocker instance with provided parameters | ||
|
||
// try lock | ||
locker.lock(); | ||
} | ||
enum LockMessage { | ||
CLOSE, TO_FRONT | ||
} | ||
void logAndExit(@Nonnull LockingException ex) { | ||
log.error("An error occurred during locking", ex); | ||
closeApplication(); | ||
There are two ways how to handle errors. | ||
|
||
I encourage you to try smart (fluent) builder: | ||
compact, easy to read and provides expecting functionality right off the bat: | ||
```java | ||
AppLocker locker = AppLocker.create("lockID") | ||
.onSuccess(this::test) // success callback (default: NULL) | ||
.onBusy("close", this::logAndExit) // send message to the instance which currently owns the lock and invoke callback (default: NULL) | ||
.onFail(this::logErrorAndExit) // if a serious error happened during the lock (default: re-throw) | ||
.build(); | ||
locker.lock(); | ||
} | ||
``` | ||
|
||
LockMessage closeApp(LockMessage message) { | ||
log.info("Application is already running"); | ||
log.info("Other application answer: " + message); | ||
// in this example we don't really care for an answer, close the app anyway | ||
closeApplication(); | ||
If it's not suited for you for some reason, use exceptions mechanism: | ||
```java | ||
AppLocker locker = AppLocker.create("lockID").build(); | ||
try { | ||
locker.lock(); | ||
} catch (LockingBusyException ex) { | ||
} catch (LockingCommunicationException ex) { | ||
} catch (LockingMessageServerException ex) { | ||
} catch (LockingFailedException ex) { | ||
} | ||
``` | ||
|
||
void logLockAcquiring() { | ||
log.info("AppLock is acquired"); | ||
} | ||
# Download | ||
Maven: | ||
```xml | ||
<dependency> | ||
<groupId>io.github.sanyarnd</groupId> | ||
<artifactId>app-locker</artifactId> | ||
<version>1.0.3</version> | ||
</dependency> | ||
|
||
<repositories> | ||
<repository> | ||
<id>bintray-sanya-rnd-maven-projects</id> | ||
<name>bintray</name> | ||
<url>https://dl.bintray.com/sanya-rnd/maven-projects</url> | ||
</repository> | ||
</repositories> | ||
``` | ||
Gradle: | ||
```gradle | ||
compile 'io.github.sanyarnd:app-locker:1.0.3' | ||
Exceptions: | ||
``` | ||
public void main() { | ||
final AppLocker locker = AppLocker.create("Unique Lock ID") | ||
.setPath(Paths.get("path/to/store/locks")) | ||
.build(); | ||
try { | ||
locker.lock(); | ||
} catch (LockingBusyException ex) { | ||
... | ||
} catch (LockingFailedException ex) { | ||
... | ||
} catch (...) { | ||
} | ||
repositories { | ||
maven { | ||
url "https://dl.bintray.com/sanya-rnd/maven-projects" | ||
} | ||
} | ||
``` | ||
For more information visit [bintray](https://bintray.com/sanya-rnd/maven-projects/applocker). | ||
|
||
Standalone jars are available on [releases](https://github.com/sanyarnd/applocker/releases) page. | ||
|
||
|
||
#Changelog | ||
To see what has changed in recent versions of AppLocker, see the [CHANGELOG.md](CHANGELOG.md) |
Oops, something went wrong.