JNI Adapter/Tutorial

JNI Adapter tutorial

This tutorial is for build and use pEp JNI adpater from scratch.

Theis adapter is a facade to use pEpEngine from JAVA/JVM Code.

This tutorial is based on MacOS

  1. Setup env
  2. Download/build/install pEp Engine dependencies and requirements (GPG, gpgme, asn1c, libetpan, pyhon, lxml )
  3. Build libpEpAdapter
  4. Build pEp JNI Adapter
  5. Use it (Enjoy!)

Setup Env && Download/build/install pEp Engine dependencies and requirements (GPG, gpgme, asn1c, libetpan, python, lxml, yml)

This steps are based on p≡p engine MacOS README

Installing packaged dependencies

For this tutorial we will use hombrew:

Install Homebrew according to the instructions found here.

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Ensure that Homebrew’s binary path (/usr/local/bin) is in your PATH environment variable.

Once we have brew, we need to install the following packages:

# general
brew install mercurial
# YML2
# If you don't have pip with your Python 2 distribution, you can install it with brew
brew install python
pip2 install --user lxml
# libetpan
brew install git autoconf automake libtool
# asn1c
brew install asn1c
# engine
brew install gpgme

Installing unpackaged dependencies

YML2

To check if lxml is properly installed, you can use this lxml “hello world” command:

python2 -c 'from lxml import etree; root = etree.Element("root"); print(root.tag)'

It should generate the following output:

root

Now we just need to get YML2

mkdir -p ~/code/yml2
hg clone https://pep.foundation/dev/repos/yml2/ ~/code/yml2

libetpan

pEp Engine requires libetpan with a set of patches that have not been upstreamed yet.

mkdir -p ~/code/libetpan
git clone https://github.com/fdik/libetpan ~/code/libetpan
cd ~/code/libetpan
mkdir ~/code/libetpan/build
./autogen.sh --prefix="$HOME/code/libetpan/build"
make
make install

Build pEp Engine (based on ENGINE README)

pEp Engine

mkdir -p ~/code/pep-engine
hg clone https://pep.foundation/dev/repos/pEpEngine/ ~/code/pep-engine
cd ~/code/pep-engine
hg up sync
mkdir ~/code/pep-engine/build

Create a local.conf that sets any of the make variables documented in Makefile.conf. All the default values for the build configuration variables on each platform are documented in default.conf.

If a dependency is not found in your system’s default include or library paths, you will have to specify the according paths in a make variable. Typically, this has to be done at least for YML2, and libetpan.

For a more detailed explanation of the mechanics of these build configuration files, and overriding defaults, see the comments in default.conf.

Below is a sample ./local.conf file, for orientation. IMPORTANT: Create this file before calling make commands

PREFIX=$(HOME)/code/pep-engine/build
SYSTEM_DB=$(PREFIX)/share/pEp/system.db

YML2_PATH=$(HOME)/code/yml2

ETPAN_LIB=-L$(HOME)/code/libetpan/build/lib
ETPAN_INC=-I$(HOME)/code/libetpan/build/include

LDFLAGS+= -install_name ${PREFIX}/lib/$(TARGET)

The engine is built as follows:

make all
make db

If your build fails with an error message similar to the following:

  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/locale.py", line 477, in _parse_localename
    raise ValueError, 'unknown locale: %s' % localename
ValueError: unknown locale: UTF-8

or any other locale-related Python error, make sure Python does not have any locale-related environment variables set. Usually, unset LC_CTYPE is sufficient to take care of the problem, but it depends on your macOS’s regional and language settings and which terminal emulator you use. This is a bug in Python, see https://bugs.python.org/issue18378#msg215215.

Now it must be installed:

make install
make -C db install

Since system.db rarely changes, its installation is not needed for every build.

Build pEp JNI Adapter

pEpJNIAdapter needs libpEpAdapter then we will build it. We need to create a local.conf that sets any of the make variables documented in Makefile.conf for every project (libpEpAdapter and pEpJNIAdapter) ### libpEpAdapter

mkdir -p ~/code/libpEpAdapter
hg clone https://pep.foundation/dev/repos/libpEpAdapter/ ~/code/libpEpAdapter
cd ~/code/libpEpAdapter
mkdir ~/code/libpEpAdapter/build

Below is a sample ./local.conf file, for orientation. IMPORTANT: Create this file before calling make commands

PREFIX=$(HOME)/code/pep-engine/build
ENGINE_LIB=-L$(HOME)/code/pep-engine/build/lib
ENGINE_INC=-I$(HOME)/code/pep-engine/build/include
make
make install

pEpJNIAdapter

mkdir -p ~/code/pep-jniadapter
hg clone https://pep.foundation/dev/repos/pEpJNIAdapter/ ~/code/pep-jniadapter
cd ~/code/pep-jniadapter
hg up sync

Before proceding we need to install JAVA JDK, to do that just download it from: here

once downloaded and installed, set JAVA_HOME:

export JAVA_HOME="$(/usr/libexec/java_home -v 1.8)"

We also need to create ./src/local.conf Below is a sample ./src/local.conf file, for orientation. IMPORTANT: Create this file before calling make commands

YML2_PATH=$(HOME)/code/yml2
YML2_PROC=$(YML2_PATH)/yml2proc $(YML2_OPTS)
YML2_OPTS=--encoding=utf8

ENGINE_LIB=-L$(HOME)/code/pep-engine/build/lib
ENGINE_INC=-I$(HOME)/code/pep-engine/build/include

AD_LIB=-L$(HOME)/code/pep-engine/build/lib
AD_INC=-I$(HOME)/code/pep-engine/build/lib

To build it:

make -C src

to test if it works if we don’t use a VM we need to set a test keyring and another $HOME, as if we do not so, it will mess with our pEp installation (as users)

mkdir -p $HOME/testEnv/gnupg

GNUPGHOME=$HOME/testEnv/gnupg HOME=$HOME/testEnv make -C test

Use it (Enjoy!)

To use it we just need to create a java class and import org.pEp.jniadapter.*

And build it including pEpJNIAdapter src dir on the classpath.

Below you will find a complete example and how to build it.

HelloWorld.java

class HelloWorld {
    
    public static void main(String[] args) {
        
        Engine pEpEngine;
        
        // First of all we need to create a session/instance of the engine.
        // for keyreset and sync will need to set up callbacks.
        try {
            pEpEngine = new Engine();
        } catch (pEpException ex) {
            System.err.println("Cannot load / create engine session");
            return;
        }
        
        // To generate we just need to create an identity and call
        // pEpEngine.myself on it: 
        // myself only generates a key if there is no key yet.
        
        // Keygen
        System.out.println("Generating or retrieving keys: ");
        Identity user = new Identity();
        user.me = true;
        user.user_id = "pEp_own_userId";
        user.username = "Test User";
        user.address = "jniTestUser@peptest.ch";
        user = pEpEngine.myself(user);
        System.out.print("Keys generated: ");
        System.out.println(user.fpr);
        
        // Once we have the key we can operate normaly, but as a helloworld
        // this is enough.

        //Once we finish we need to close the session
        pEpEngine.close();
    }
}

Build && run using terminal

And to build and run it from terminal:

export JNIADAPTER_PATH=$HOME/code/pep-jniadapter/src 
CLASSPATH=.:$JNIADAPTER_PATH javac HelloWorld.java #Build
GNUPGHOME=$HOME/testEnv/gnupg HOME=$HOME/testEnv CLASSPATH=.:$JNIADAPTER_PATH  java -Djava.library.path=$JNIADAPTER_PATH HelloWorld #run

Build && run using eclipse

pEp JNI adapter has two components the java component pEp.jar and the native one libpEpJNI.dylib both are located at ./src/ and this is what we need to import into eclipse.

  1. Create a new eclipse java project
  2. Import pEp components
    • Right click on the project in the side list
    • Select Java Build Path
    • Select Libraries tab
    • Click Add external Library
    • Select pEp.jar and Open
    • Unfold the pEp.jar on the list of libraries
    • Select Native library location
    • Click on Edit (at right)
    • Select the folder where libpEpJNI.dylib is located
    • Apply and close