mirror of
https://github.com/ACINQ/eclair.git
synced 2024-11-19 01:43:22 +01:00
Added simple plugin support (#927)
Using org.clapper:classutil library and a very simple `Plugin` interface.
This commit is contained in:
parent
f563ca0897
commit
c530b23175
11
README.md
11
README.md
@ -152,6 +152,17 @@ If you want to persist the data directory, you can make the volume to your host
|
||||
docker run -ti --rm -v "/path_on_host:/data" -e "JAVA_OPTS=-Declair.printToConsole" acinq/eclair
|
||||
```
|
||||
|
||||
## Plugins
|
||||
|
||||
For advanced usage, Eclair supports plugins written in Scala, Java, or any JVM-compatible language.
|
||||
|
||||
A valid plugin is a jar that contains an implementation of the [Plugin](eclair-node/src/main/scala/fr/acinq/eclair/Plugin.scala) interface.
|
||||
|
||||
Here is how to run Eclair with plugins:
|
||||
```shell
|
||||
java -jar eclair-node-<version>-<commit_id>.jar <plugin1.jar> <plugin2.jar> <...>
|
||||
```
|
||||
|
||||
## Mainnet usage
|
||||
|
||||
Following are the minimum configuration files you need to use for Bitcoin Core and Eclair.
|
||||
|
@ -74,6 +74,12 @@
|
||||
<artifactId>eclair-core_${scala.version.short}</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<!-- for plugins -->
|
||||
<groupId>org.clapper</groupId>
|
||||
<artifactId>classutil_${scala.version.short}</artifactId>
|
||||
<version>1.4.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
|
@ -22,6 +22,7 @@ import akka.actor.ActorSystem
|
||||
import grizzled.slf4j.Logging
|
||||
|
||||
import scala.concurrent.ExecutionContext
|
||||
import scala.util.{Failure, Success}
|
||||
|
||||
/**
|
||||
* Created by PM on 25/01/2016.
|
||||
@ -31,10 +32,15 @@ object Boot extends App with Logging {
|
||||
val datadir = new File(System.getProperty("eclair.datadir", System.getProperty("user.home") + "/.eclair"))
|
||||
|
||||
try {
|
||||
val plugins = Plugin.loadPlugins(args.map(new File(_)))
|
||||
plugins.foreach(plugin => logger.info(s"loaded plugin ${plugin.getClass.getSimpleName}"))
|
||||
implicit val system: ActorSystem = ActorSystem("eclair-node")
|
||||
implicit val ec: ExecutionContext = system.dispatcher
|
||||
new Setup(datadir).bootstrap onFailure {
|
||||
case t: Throwable => onError(t)
|
||||
val setup = new Setup(datadir)
|
||||
plugins.foreach(_.onSetup(setup))
|
||||
setup.bootstrap onComplete {
|
||||
case Success(kit) => plugins.foreach(_.onKit(kit))
|
||||
case Failure(t) => onError(t)
|
||||
}
|
||||
} catch {
|
||||
case t: Throwable => onError(t)
|
||||
@ -47,4 +53,3 @@ object Boot extends App with Logging {
|
||||
System.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
|
29
eclair-node/src/main/scala/fr/acinq/eclair/Plugin.scala
Normal file
29
eclair-node/src/main/scala/fr/acinq/eclair/Plugin.scala
Normal file
@ -0,0 +1,29 @@
|
||||
package fr.acinq.eclair
|
||||
|
||||
import java.io.File
|
||||
import java.net.{URL, URLClassLoader}
|
||||
|
||||
import org.clapper.classutil.ClassFinder
|
||||
|
||||
trait Plugin {
|
||||
|
||||
def onSetup(setup: Setup): Unit
|
||||
|
||||
def onKit(kit: Kit): Unit
|
||||
|
||||
}
|
||||
|
||||
object Plugin {
|
||||
|
||||
def loadPlugins(jars: Seq[File]): Seq[Plugin] = {
|
||||
val finder = ClassFinder(jars)
|
||||
val classes = finder.getClasses
|
||||
val urls = jars.map(f => new URL(s"file:${f.getCanonicalPath}"))
|
||||
val loader = new URLClassLoader(urls.toArray, ClassLoader.getSystemClassLoader)
|
||||
classes
|
||||
.filter(_.isConcrete)
|
||||
.filter(_.implements(classOf[Plugin].getName))
|
||||
.map(c => Class.forName(c.name, true, loader).getDeclaredConstructor().newInstance().asInstanceOf[Plugin])
|
||||
.toList
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user