diff --git a/README.md b/README.md index 8e67c1b..22e9769 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,11 @@ [![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: do not allow more than 1 running instance of the application. +AppLocker library adds single instance application functionality, allowing exactly 1 running instance of the application. Library is compatible with any JDK8+ version. -Library does not have any transitive dependencies. +Library has very small footprint (20-30kb) and zero dependencies. # Features * File-system based locking mechanism @@ -17,10 +17,29 @@ Library does not have any transitive dependencies. # Download -Visit [releases page](https://github.com/sanyarnd/applocker/releases) (jar) or [bintray artifactory](https://bintray.com/sanya-rnd/maven-projects/applocker) (maven, gradle, ivy). +Visit [releases page](https://github.com/sanyarnd/applocker/releases) or [bintray artifactory](https://bintray.com/sanya-rnd/maven-projects/applocker). # How to use -```java +Handlers: +``` +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 } @@ -41,21 +60,23 @@ void logLockAcquiring() { log.info("AppLock is acquired"); } -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) -> { // because we have a busy handler, - if (msg == LockMessage.TO_FRONT) { // message handler is processing messages sent from `.busy` and sends an answer back - 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) // simple callback if acquiring the lock was successful - .build(); // create AppLocker instance with provided parameters +``` - // try lock - locker.lock(); +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 (...) { + } } ``` +