Browse Source

merge master into Release_2.1 branch

JNI-129
heck 4 years ago
parent
commit
fabf7c81ed
  1. 59
      .gitignore
  2. 34
      Makefile
  3. 62
      Makefile.conf
  4. 91
      README.md
  5. 2
      android/build.gradle
  6. 16
      android/jni/Android.mk
  7. 2
      android/src/foundation/pEp/jniadapter/AndroidHelper.java
  8. 28
      local.conf.example
  9. 289
      src/Makefile
  10. 55
      src/codegen/Makefile
  11. 80
      src/codegen/gen_cpp_Engine.ysl2
  12. 84
      src/codegen/gen_cpp_Message.ysl2
  13. 186
      src/codegen/gen_java_Engine.ysl2
  14. 368
      src/codegen/gen_java_Message.ysl2
  15. 65
      src/codegen/gen_throw_pEp_exception.ysl2
  16. 178
      src/codegen/pEp.yml2
  17. 6
      src/codegen/textutils.ysl2
  18. 0
      src/codegen/types_c.ysl2
  19. 0
      src/codegen/types_java.ysl2
  20. 200
      src/cxx/basic_api.cc
  21. 207
      src/cxx/foundation_pEp_jniadapter_AbstractEngine.cc
  22. 49
      src/cxx/foundation_pEp_jniadapter__Blob.cc
  23. 0
      src/cxx/get_header.cc
  24. 8
      src/cxx/identity_api.cc
  25. 795
      src/cxx/jniutils.cc
  26. 147
      src/cxx/jniutils.hh
  27. 15
      src/cxx/passphrase_callback.hh
  28. 42
      src/cxx/passphrase_callback.hxx
  29. 28
      src/foundation/pEp/jniadapter/Engine.java.target
  30. 218
      src/foundation/pEp/jniadapter/Message.java.target
  31. 11
      src/foundation/pEp/jniadapter/UniquelyIdentifiable.java
  32. 252
      src/gen_java_Message.ysl2
  33. 35
      src/gen_java_exceptions.ysl2
  34. 64
      src/gen_throw_pEp_exception.ysl2
  35. 149
      src/java/foundation/pEp/jniadapter/AbstractEngine.java
  36. 20
      src/java/foundation/pEp/jniadapter/Blob.java
  37. 0
      src/java/foundation/pEp/jniadapter/CommType.java
  38. 38
      src/java/foundation/pEp/jniadapter/Identity.java
  39. 6
      src/java/foundation/pEp/jniadapter/Pair.java
  40. 11
      src/java/foundation/pEp/jniadapter/Sync.java
  41. 12
      src/java/foundation/pEp/jniadapter/UniquelyIdentifiable.java
  42. 115
      src/java/foundation/pEp/jniadapter/Utils.java
  43. 8
      src/java/foundation/pEp/jniadapter/_Blob.java
  44. 10
      src/java/foundation/pEp/jniadapter/_Identity.java
  45. 7
      src/java/foundation/pEp/jniadapter/decrypt_message_Return.java
  46. 30
      src/java/foundation/pEp/jniadapter/interfaces/AbstractEngineInterface.java
  47. 5
      src/java/foundation/pEp/jniadapter/interfaces/BlobInterface.java
  48. 7
      src/java/foundation/pEp/jniadapter/interfaces/IdentityInterface.java
  49. 772
      src/jniutils.cc
  50. 130
      src/jniutils.hh
  51. 14
      src/passphrase_callback.hh
  52. 42
      src/passphrase_callback.hxx
  53. 5
      test/java/foundation/pEp/jniadapter/test/Makefile
  54. 6
      test/java/foundation/pEp/jniadapter/test/Makefile.conf
  55. 13
      test/java/foundation/pEp/jniadapter/test/basic/TestMain.java
  56. 4
      test/java/foundation/pEp/jniadapter/test/jni100/TestMain.java
  57. 20
      test/java/foundation/pEp/jniadapter/test/jni111/TestAlice.java
  58. 1
      test/java/foundation/pEp/jniadapter/test/jni114/TestAlice.java
  59. 15
      test/java/foundation/pEp/jniadapter/test/jni115/TestAlice.java
  60. 37
      test/java/foundation/pEp/jniadapter/test/jni117/Makefile
  61. 34
      test/java/foundation/pEp/jniadapter/test/jni117/TestAlice.java
  62. 37
      test/java/foundation/pEp/jniadapter/test/jni118/Makefile
  63. 107
      test/java/foundation/pEp/jniadapter/test/jni118/TestAlice.java
  64. 37
      test/java/foundation/pEp/jniadapter/test/jni119/Makefile
  65. 37
      test/java/foundation/pEp/jniadapter/test/jni119/TestAlice.java
  66. 2
      test/java/foundation/pEp/jniadapter/test/jni125/Makefile
  67. 2
      test/java/foundation/pEp/jniadapter/test/jni88/TestMain.java
  68. 1
      test/java/foundation/pEp/jniadapter/test/jni91/TestMain.java
  69. 5
      test/java/foundation/pEp/jniadapter/test/jni92/TestMain.java
  70. 10
      test/java/foundation/pEp/jniadapter/test/jni98/TestMain.java
  71. 226
      test/java/foundation/pEp/jniadapter/test/regression/TestMain.java
  72. 2
      test/java/foundation/pEp/jniadapter/test/speedtest/SpeedTest.java
  73. 3
      test/java/foundation/pEp/jniadapter/test/templateAliceBob/MultiPeerCTX.java
  74. 4
      test/java/foundation/pEp/jniadapter/test/templateAliceBob/TestAlice.java
  75. 4
      test/java/foundation/pEp/jniadapter/test/templateAliceBob/TestBob.java
  76. 49
      test/java/foundation/pEp/jniadapter/test/utils/AdapterBaseTestContext.java
  77. 3
      test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/ctx/FsMQManagerBaseTestContext.java
  78. 3
      test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/ctx/FsMQManagerTestContext.java
  79. 2
      test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/identities/Makefile
  80. 3
      test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/identities/TestMain.java
  81. 2
      test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/stateless_ping/Makefile
  82. 2
      test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/stateless_rxtx/Makefile
  83. 4
      test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/stateless_rxtx/TestMain.java
  84. 2
      test/java/foundation/pEp/jniadapter/test/utils/transport/fsmsgqueue/test/regression/Makefile
  85. 4
      test/java/foundation/pEp/jniadapter/test/utils/transport/fsmsgqueue/test/regression/TestMain.java
  86. 2
      test/java/foundation/pEp/pitytest/Makefile
  87. 2
      test/java/foundation/pEp/pitytest/Makefile.conf
  88. 8
      test/java/foundation/pEp/pitytest/TestContextInterface.java
  89. 2
      test/java/foundation/pEp/pitytest/TestSuite.java
  90. 49
      test/java/foundation/pEp/pitytest/TestUnit.java
  91. 2
      test/java/foundation/pEp/pitytest/examples/ctxinitfail/Makefile
  92. 12
      test/java/foundation/pEp/pitytest/examples/ctxinitfail/TestMain.java
  93. 2
      test/java/foundation/pEp/pitytest/examples/ctxmembers/Makefile
  94. 3
      test/java/foundation/pEp/pitytest/examples/ctxmembers/TestMain.java
  95. 2
      test/java/foundation/pEp/pitytest/examples/helloworld/Makefile
  96. 3
      test/java/foundation/pEp/pitytest/examples/helloworld/TestMain.java
  97. 2
      test/java/foundation/pEp/pitytest/examples/testsuite/Makefile
  98. 3
      test/java/foundation/pEp/pitytest/examples/testsuite/TestMain.java
  99. 6
      test/java/foundation/pEp/pitytest/utils/Pair.java
  100. 102
      test/java/foundation/pEp/pitytest/utils/TestUtils.java

59
.gitignore

@ -1,40 +1,52 @@
# ignore all of them
*.class
*.jar
*.swp
*.o
*.a
*.dylib
*.so
*.orig
*~
.DS_Store
*.db
*.log
.DS_Store
# ignore config files
local.conf
# ignore build and dist dirs
build/*
dist/*
# ignore generated files
pEp_*.h
pEp_*.cc
foundation_pEp_*.h
foundation_pEp_*.cc
src/foundation/pEp/jniadapter/pEp*.java
src/foundation/pEp/jniadapter/PassphraseType.java
status_list.yml2
passphrase_status_list.yml2
foundation_pEp_jniadapter__Blob.h
foundation_pEp_jniadapter_AbstractEngine.h
foundation_pEp_jniadapter_Engine.*
foundation_pEp_jniadapter_Message.*
foundation_pEp_jniadapter_Identity.h
throw_pEp_exception.*
src/java/foundation/pEp/jniadapter/exceptions/*.java
CipherSuite.java
Color.java
DecryptFlags.java
Engine.java
EngineInterface.java
IdentityFlags.java
Message.java
DecryptFlags.java
MessageInterface.java
Rating.java
Status.java
SyncHandshakeResult.java
IdentityFlags.java
SyncHandshakeSignal.java
CipherSuite.java
PassphraseType.java
# ignore pep-homes
test/resources/per-user-dirs/alice/.pEp
test/resources/per-user-dirs/bob/.pEp
test/resources/per-user-dirs/carol/.pEp
# FsMsgQueue data
test/resources/fsmsgqueue-test/Alice
test/resources/fsmsgqueue-test/Bob
test/resources/fsmsgqueue-test/Carol
passphrase_status_list.yml2
status_list.yml2
ndk*/
# ignore vim workspace
@ -70,14 +82,11 @@ android/gradlew.bat
androidTests/gradle/wrapper/gradle-wrapper.properties
androidTests/gradlew
androidTests/gradlew.bat
src/org.tar.gz
src/local.conf
org.tar.gz
*.iml
android/external/[?]*
local.conf
src/local.conf
# Default ignored files
?idea/

34
Makefile

@ -3,30 +3,40 @@
# This file may be used under the terms of the GNU General Public License version 3
# see LICENSE.txt
.PHONY: all compile test clean doc doc-cxx doc-java clean-doc install uninstall
.PHONY: all src test clean doxy-all doxy-cxx doxy-java doxy-clean
all: compile
all: src
src:
compile:
$(MAKE) -C src
test: src
test: compile
$(MAKE) -C test/java/foundation/pEp/jniadapter/test/ compile
clean-all: clean clean-doc
clean:
$(MAKE) -C src clean
$(MAKE) -C test/java/foundation/pEp/jniadapter/test/ clean clean-pep-home
# Generate API Documentation
doxy-all: doxy-cxx doxy-java
clean-doc:
rm -rf doc/doxygen/cxx
rm -rf doc/doxygen/java
# Generate API Documentation
doc: doc-cxx doc-java
doxy-cxx: src
dox-cxx: compile
cd doc/doxygen; doxygen doxyfile-cxx
doxy-java: src
doc-java: compile
cd doc/doxygen; doxygen doxyfile-java
doxy-clean:
rm -rf doc/doxygen/cxx
rm -rf doc/doxygen/java
install:
$(MAKE) -C src install
uninstall:
$(MAKE) -C src uninstall

62
Makefile.conf

@ -5,18 +5,22 @@
HERE:=$(dir $(lastword $(MAKEFILE_LIST)))
PLATFORM:=$(shell uname | tr A-Z a-z)
JAVAC_CMD=javac -encoding UTF-8
JAVAH_CMD=javah -encoding UTF-8
# DEV ENV PATHS & CFG
# The dev environment paths and configs are set to a default value which can be overridden by ./local.conf and overridden again by <subdir>/local.conf
######### Build Config Defaults #########
DEBUG=1
YML2_PATH=$(HOME)/yml2
# The build settings are set to a default value which can be overridden by using ./local.conf
######### DEFAULTS #########
DEBUG=0
PREFIX=$(HOME)
YML2_PATH=$(PREFIX)/src/yml2
YML2_PROC=$(YML2_PATH)/yml2proc $(YML2_OPTS)
YML2_OPTS=--encoding=utf8
ENGINE_LIB_PATH=$(HOME)/lib
ENGINE_INC_PATH=$(HOME)/include
AD_LIB_PATH=$(HOME)/lib
AD_INC_PATH=$(HOME)/include
ENGINE_LIB_PATH=$(PREFIX)/lib
ENGINE_INC_PATH=$(PREFIX)/include
AD_LIB_PATH=$(PREFIX)/lib
AD_INC_PATH=$(PREFIX)/include
### Guessing JAVA_HOME
ifeq ($(PLATFORM),linux)
@ -24,13 +28,6 @@ ifeq ($(PLATFORM),linux)
endif
# Old versions of a Java distribution have a `javah` binary, new versions do not. This checks whether or not `javah` can be found in the Java distribution found in the directory `$JAVA_HOME`.
DUMMY:=$(shell which $(JAVA_HOME)/bin/javah)
ifeq ($(.SHELLSTATUS),0)
OLD_JAVA=true
endif
JAVAC_CMD=javac -encoding UTF-8
######### Overrides from the config file(s) #########
ifneq ("$(wildcard $(HERE)local.conf)","")
@ -40,19 +37,28 @@ else
$(info Optional build config not found: $(HERE)local.conf)
endif
ifneq ("$(wildcard $(HERE)src/local.conf)","")
$(info including: $(HERE)src/local.conf)
-include $(HERE)src/local.conf
else
$(info Optional build config not found: $(HERE)src/local.conf)
endif
### Apply config
ENGINE_LIB=-L$(ENGINE_LIB_PATH)
ENGINE_INC=-I$(ENGINE_INC_PATH)
AD_LIB=-L$(AD_LIB_PATH)
AD_INC=-I$(AD_INC_PATH)
ifndef JAVA_HOME
$(error JAVA_HOME is not set!)
endif
# Guessing USE_JAVAH
# cant be guessed earlier, because it depends on JAVA_HOME which can be set in the local.conf
# Old versions of a Java distribution have a `javah` binary, new version do not and the replacement is "javac -h"
# TODO: dont check for presence of javah, but check if javac -h is supported, because some java (RHEL) has javah but supports javac -h (and javac -h is preferred)
ifndef USE_JAVAH
DUMMY:=$(shell which $(JAVA_HOME)/bin/javah)
ifeq ($(.SHELLSTATUS),0)
USE_JAVAH=1
endif
endif
JAVA_BIN_DIR=$(JAVA_HOME)/bin
######### C and C++ #########
CXXFLAGS+=-O0 -std=c++11 -fpermissive -fPIC -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/$(PLATFORM) $(AD_INC) $(ENGINE_INC)
@ -76,3 +82,15 @@ endif
### YML_PATH is needed in the environment of every call to a program of the YML2 distribution
export YML_PATH=$(YML2_PATH)
# BEGIN // kryptic hack to to replace a space with a newline
# $(subst ${ },${space}, whatever)
# maybe not well known: define/endef is custom makefile function definition
null :=
space := ${null} ${null}
${space} := ${space}
define \n
endef
# END // kryptic hack to to replace a space with a newline

91
README.md

@ -1,67 +1,68 @@
# p≡p JNI Adapter
More complete developer instructions can be found here: [https://dev.pep.foundation/JNI%20Adapter/Tutorial]().
## Prerequisites
Please find the complete build instructions here:
https://dev.pep.foundation/Common%20Adapter%20Documentation/Adapter_Build_Instructions
### yml2
To set up yml2 properly, consult the documentation of pEp Engine (linked below). yml2 is a build dependency of pEp Engine.
## Build Result
The binary package resulting from the build will be located under `./dist`.
It merely contains:
* pEp.jar - The java library
* libpEpJNI.dylib - The dynamically linkable native library
* libpEpJNI.a - The statically linkable native library
### C and C++ compiler
Any gcc or clang distribution offered by your OS is fine.
## Build Configuration
### pEp Engine
Instructions for obtaining the pEp Engine can be found on [https://pep.foundation/dev/repos/pEpEngine/file/]().
The build configuration file is called `local.conf`.
Use the file `local.conf.example` as a template.
### libpEpAdapter
Instructions for obtaining libpEpAdapter can be found on [https://pep.foundation/dev/repos/libpEpAdapter/file/]().
```bash
cp local.conf.example local.conf
```
### Java 8 (or newer) JDK
Download Oracle Java from [https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html]().
Then, tweak it to your needs.
OpenJDK can be installed from macports on macOS with one of the following commands:
## Make Targets
~~~
sudo port install openjdk8
sudo port install openjdk11
~~~
The default make target is `compile`.
## Building
### Build
* `make compile`
Builds the whole adapter under `./build`.
The complete distribution ready adapter will be in `./dist`.
Build configuration will be the result of including these files in the following order:
* `Makefile.conf` - Defaults
* `local.conf` - optional cfg (overwrites existing values)
* `src/local.conf`- optional cfg for src dir (overwrites existing values)
### Test
* `make test`
Builds the complete test-suite under `./test`.
An example `local.conf` looks like this:
### Install
* `make install`
Installs the files under `./dist` under $PREFIX (local.conf)
~~~
JAVA_HOME=/Library/Java/JavaVirtualMachines/openjdk8/Contents/Home
* `make uninstall`
Removes all the filenames under `./dist` from $PREFIX (local.conf)
YML2_PATH=$(HOME)/code/yml2
### Doc
In order to generate the API doc you need to have doxygen installed on your system.
ENGINE_INC_PATH=$(HOME)/code/engine/build/include
ENGINE_LIB_PATH=$(HOME)/code/engine/build/lib
* `make doc`
Generates Java and C++ API doc.
AD_INC_PATH=$(HOME)/code/libad/build/include
AD_LIB_PATH=$(HOME)/code/libad/build/lib
~~~
* `make doc-cxx`
Generates the API doc for the C++ part of the adapter.
The the foo_PATH variables will be turned into compiler directives (-I / -L), which can be directly set by just omitting "\_PATH" (e.g. ENGINE_INC). They will take priority.
* `make doc-java`
Generates the API doc for the Java part of the adapter.
Depending on what is already set in your environment, or can be found in your default include/library paths, setting any of these variables may be optional on your platform.
### Clean
* `make clean`
Deletes all the derived objects of the adapter build in `./build` and `./dist`.
Also invokes `make clean` which cleans the whole test-suite.
Does not remove the generated API doc.
Now, build the Adapter with
* `make clean-doc`
Removes all the generated API doc.
On Linux:
* `make clean-all`
Equals `make clean` and `make clean-doc`
~~~
make src
~~~
On macOS:
~~~
make src
~~~
(The GNU Make distributed with macOS might be too old, in this case install GNU Make "gmake" from macPorts).

2
android/build.gradle

@ -94,7 +94,7 @@ android {
// call source generation makefile target
task genSources(type:Exec, dependsOn: 'genpEpEngineAsn1Sources') {
workingDir '../src'
commandLine 'make', 'pEp.jar'
commandLine 'make', 'lib-java'
}
task genpEpEngineSyncSources(type:Exec) {

16
android/jni/Android.mk

@ -47,14 +47,14 @@ LOCAL_STATIC_LIBRARIES := pEpEngine libetpan libiconv libuuid pEpAdapter libsequ
LOCAL_CPP_FEATURES += exceptions
LOCAL_CPPFLAGS += -std=c++11 -DANDROID_STL=c++_shared -DHAVE_PTHREADS -DDISABLE_SYNC -fuse-ld=lld
LOCAL_SRC_FILES := \
../../src/foundation_pEp_jniadapter_AbstractEngine.cc \
../../src/foundation_pEp_jniadapter_Engine.cc \
../../src/foundation_pEp_jniadapter_Message.cc \
../../src/foundation_pEp_jniadapter__Blob.cc \
../../src/throw_pEp_exception.cc \
../../src/basic_api.cc \
../../src/identity_api.cc \
../../src/jniutils.cc
../../src/cxx/foundation_pEp_jniadapter_AbstractEngine.cc \
../../src/cxx/foundation_pEp_jniadapter_Engine.cc \
../../src/cxx/foundation_pEp_jniadapter_Message.cc \
../../src/cxx/foundation_pEp_jniadapter__Blob.cc \
../../src/cxx/throw_pEp_exception.cc \
../../src/cxx/basic_api.cc \
../../src/cxx/identity_api.cc \
../../src/cxx/jniutils.cc
LOCAL_C_INCLUDES += $(GPGBUILD)/$(TARGET_ARCH_ABI)/include
LOCAL_C_INCLUDES += $(LIB_PEP_ADAPTER_PATH)/build-android/include $(SRC_PATH)/libpEpAdapter

2
android/src/foundation/pEp/jniadapter/AndroidHelper.java

@ -10,6 +10,8 @@ import java.io.*;
import java.lang.reflect.Method;
import java.util.Scanner;
import foundation.pEp.jniadapter.exceptions.pEpException;
public class AndroidHelper {
static {
System.loadLibrary("pEpJNIAndroidHelper");

28
local.conf.example

@ -2,23 +2,29 @@
# you might not need this file, but if the defaults dont work for you
# You can override them here.
# Tweak the values to your needs and rename it to local.conf
# These example values here reflect the defaults
############ Install ###########
# PREFIX=$(HOME)
######### C++ Compiler #########
# Should work with clang and g++
# CXX=g++
# DEBUG=1 # DEBUG Build (Default)
# DEBUG=0 # RELEASE Build
# DEBUG=0 # RELEASE Build / set to 1 for DEBUG build
######### JAVA #########
############ JAVA ##############
# JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home
# USE_JAVAH=0 # keep the build from using javah
############ YML2 ##############
# YML2_PATH=$(HOME)/src/yml2
########### Engine #############
# ENGINE_LIB_PATH=$(PREFIX)/lib
# ENGINE_INC_PATH=$(PREFIX)/include
######### YML2 #########
# YML2_PATH=$(HOME)/code/yml2
########## libAdapter ##########
# AD_LIB_PATH=$(PREFIX)/lib
# AD_INC_PATH=$(PREFIX)/include
######### Engine #########
# ENGINE_LIB_PATH=$(HOME)/local/lib
# ENGINE_INC_PATH=$(HOME)/local/include
######### libAdapter #########
# AD_LIB_PATH=$(HOME)/local/lib
# AD_INC_PATH=$(HOME)/local/include

289
src/Makefile

@ -5,10 +5,35 @@
include ../Makefile.conf
# Names of the java and c++ libs to be built
LIB_JAVA_NAME=pEp.jar
LIB_CXX_NAME=libpEpJNI
DIST_DIR=../dist/
LIB_CXX_STATIC_NAME=$(addsuffix .a,$(LIB_CXX_NAME))
ifeq ($(PLATFORM),linux)
LIB_CXX_DYN_NAME=$(addsuffix .so,$(LIB_CXX_NAME))
else ifeq ($(PLATFORM),darwin)
LIB_CXX_DYN_NAME=$(addsuffix .dylib,$(LIB_CXX_NAME))
else
$(error I dont know how to build for $(PLATFORM).)
endif
LIB_JAVA=$(DIST_DIR)/$(LIB_JAVA_NAME)
LIB_CXX_STATIC=$(DIST_DIR)/$(LIB_CXX_STATIC_NAME)
LIB_CXX_DYN=$(DIST_DIR)/$(LIB_CXX_DYN_NAME)
$(info ------------------ DIST FILES ---------------------)
$(info LIB_JAVA: $(LIB_JAVA))
$(info LIB_CXX_STATIC: $(LIB_CXX_STATIC))
$(info LIB_CXX_DYN: $(LIB_CXX_DYN))
$(info ------------------ BUILD INFO ---------------------)
$(info PLATFORM: $(PLATFORM))
$(info DEBUG: $(DEBUG))
$(info CXX: $(CXX))
$(info JAVA_HOME: $(JAVA_HOME))
$(info USE_JAVAH: $(USE_JAVAH))
$(info ENGINE_LIB_PATH: $(ENGINE_LIB_PATH))
$(info ENGINE_INC_PATH: $(ENGINE_INC_PATH))
$(info AD_LIB_PATH: $(AD_LIB_PATH))
@ -17,133 +42,151 @@ $(info YML2_PATH: $(YML2_PATH))
$(info CXXFLAGS: $(CXXFLAGS))
$(info LDFLAGS: $(LDFLAGS))
$(info LDLIBS: $(LDLIBS))
$(info ---------------------------------------------------)
# Dirs
# relative to "src/"
BUILD_ROOT=../build/
CXX_DIR=cxx/
JAVA_DIR=java/
JAVA_PKG_BASENAME=foundation/pEp/jniadapter/
JAVA_PKG_ROOT=$(JAVA_DIR)$(JAVA_PKG_BASENAME)
JAVA_BUILD_ROOT=$(BUILD_ROOT)$(JAVA_DIR)
OBJ_DIR=$(BUILD_ROOT)$(CXX_DIR)
# for "make clean" only
GENERATED_JAVA=\
$(JAVA_PKG_ROOT)/Engine.java \
$(JAVA_PKG_ROOT)/Message.java \
$(JAVA_PKG_ROOT)/CipherSuite.java \
$(JAVA_PKG_ROOT)/Color.java \
$(JAVA_PKG_ROOT)/DecryptFlags.java \
$(JAVA_PKG_ROOT)/IdentityFlags.java \
$(JAVA_PKG_ROOT)/Rating.java \
$(JAVA_PKG_ROOT)/SyncHandshakeResult.java \
$(JAVA_PKG_ROOT)/SyncHandshakeSignal.java \
$(JAVA_PKG_ROOT)/PassphraseType.java \
$(JAVA_PKG_ROOT)/interfaces/EngineInterface.java \
$(JAVA_PKG_ROOT)/interfaces/MessageInterface.java \
$(JAVA_PKG_ROOT)/exceptions/*.java
# files to compile which will be be generated
GENERATED_CC=\
$(CXX_DIR)/foundation_pEp_jniadapter_Engine.cc \
$(CXX_DIR)/foundation_pEp_jniadapter_Message.cc \
$(CXX_DIR)/throw_pEp_exception.cc
# for "make clean" only
GENERATED_HH=\
$(CXX_DIR)/throw_pEp_exception.hh
# Generated JNI headers
JNI_GENERATED_HH=\
$(CXX_DIR)/foundation_pEp_jniadapter_AbstractEngine.h \
$(CXX_DIR)/foundation_pEp_jniadapter__Blob.h \
$(CXX_DIR)/foundation_pEp_jniadapter_Engine.h \
$(CXX_DIR)/foundation_pEp_jniadapter_Identity.h \
$(CXX_DIR)/foundation_pEp_jniadapter_Message.h
# Auto dependencies using gcc/clang
CXXFLAGS+= -MMD -MP
SOURCES=$(wildcard $(CXX_DIR)/*.cc)
SOURCES+=$(GENERATED_CC)
tmp=$(SOURCES:%.cc=%.o)
OBJECTS=$(addprefix $(BUILD_ROOT), $(tmp))
DEPENDS=$(OBJECTS:%.o=%.d)
-include $(DEPENDS)
VPATH = $(CXX_DIR)/
.PHONY: all lib-java lib-cxx compile-java compile-cxx gen-jni-headers codegen clean create-dirs remove-dirs install uninstall
$(info SOURCES: $(SOURCES))
$(info OBJECTS: $(OBJECTS))
$(info DEPENDS: $(DEPENDS))
.DEFAULT_GOAL := all
all: lib-java lib-cxx
# Build only java lib
lib-java: $(LIB_JAVA)
# Build only c++ static/shared lib
lib-cxx: $(LIB_CXX_DYN) $(LIB_CXX_STATIC)
# ---------------- Link -----------------
$(LIB_JAVA): compile-java
$(JAVA_BIN_DIR)/jar cf $@ -C $(JAVA_BUILD_ROOT) foundation
$(LIB_CXX_DYN): compile-cxx
$(CXX) $(OBJ_DIR)*.o $(LDFLAGS) $(LDLIBS) -o $@
$(LIB_CXX_STATIC): compile-cxx
$(AR) -r $@ $(OBJ_DIR)*.o
# -------------- Compile -----------------
compile-java: create-dirs codegen
cd $(JAVA_DIR);$(JAVA_BIN_DIR)/$(JAVAC_CMD) -d ../$(JAVA_BUILD_ROOT) $(JAVA_PKG_BASENAME)/*.java
cd $(JAVA_DIR);$(JAVA_BIN_DIR)/$(JAVAC_CMD) -d ../$(JAVA_BUILD_ROOT) $(JAVA_PKG_BASENAME)/exceptions/*.java
cd $(JAVA_DIR);$(JAVA_BIN_DIR)/$(JAVAC_CMD) -d ../$(JAVA_BUILD_ROOT) $(JAVA_PKG_BASENAME)/interfaces/*.java
compile-cxx: create-dirs gen-jni-headers $(OBJECTS)
$(OBJECTS) : $(BUILD_ROOT)%.o : %.cc
$(CXX) $(CXXFLAGS) -c $< -o $@
ifndef JAVA_HOME
$(error JAVA_HOME is not set!)
endif
JP=$(JAVA_HOME)/bin
# Old versions of a Java distribution have a `javah` binary, new versions do not. This checks whether or not `javah` can be found in the Java distribution found in the directory `$JAVA_HOME`.
NOT_USED:=$(shell which $(JAVA_HOME)/bin/javah)
ifeq ($(.SHELLSTATUS),0)
OLD_JAVA=placeholder
endif
LIBRARY=libpEpJNI.a
JAR=pEp.jar
# --------- Generate JNI headers ----------
gen-jni-headers: codegen $(JNI_GENERATED_HH)
ifeq ($(PLATFORM),linux)
SHARED=libpEpJNI.so
else ifeq ($(PLATFORM),darwin)
SHARED=libpEpJNI.dylib
# "new" javac -h accepts list of java files
# While "old" (Java 8) javah needs a list of java classes (e.g. foundation.pEp.jniadapter.Message)
$(JNI_GENERATED_HH):
ifeq ($(USE_JAVAH),1)
cd $(JAVA_DIR)/;$(JAVA_BIN_DIR)/$(JAVAH_CMD) -d ../$(CXX_DIR) $(subst ${ },${space}\${\n},$(subst /,.,$(patsubst %.java,%, $(subst $(JAVA_DIR),,$(sort $(wildcard $(JAVA_DIR)$(JAVA_PKG_BASENAME)*.java))))))
else
$(error I dont know how to build for $(PLATFORM).)
cd $(JAVA_DIR);$(JAVA_BIN_DIR)/$(JAVAC_CMD) -d ../$(JAVA_BUILD_ROOT) -h ../$(CXX_DIR)/ $(JAVA_PKG_BASENAME)/*.java
endif
JAVA_SOURCES=foundation/pEp/jniadapter/AbstractEngine.java \
foundation/pEp/jniadapter/Blob.java \
foundation/pEp/jniadapter/CommType.java \
foundation/pEp/jniadapter/Identity.java \
foundation/pEp/jniadapter/Pair.java \
foundation/pEp/jniadapter/Sync.java \
foundation/pEp/jniadapter/_Blob.java \
foundation/pEp/jniadapter/_Identity.java \
foundation/pEp/jniadapter/pEpException.java \
foundation/pEp/jniadapter/Message.java \
foundation/pEp/jniadapter/Engine.java \
C_SOURCES=foundation_pEp_jniadapter_Engine.cc \
foundation_pEp_jniadapter_Engine.h \
foundation_pEp_jniadapter_Message.cc \
foundation_pEp_jniadapter_Message.h \
throw_pEp_exception.cc \
throw_pEp_exception.hh \
foundation_pEp_jniadapter_AbstractEngine.h \
foundation_pEp_jniadapter__Blob.cc \
foundation_pEp_jniadapter__Blob.h
PEP_HEADER:=$(shell $(CXX) $(CXXFLAGS) -E -M get_header.cc | grep -oe '[^[:space:]]*pEpEngine\.h' | head -1)
.PHONY: all
all: $(JAR) $(SHARED)
$(JAR): status_list.yml2 passphrase_status_list.yml2 $(JAVA_SOURCES) $(C_SOURCES)
$(JP)/$(JAVAC_CMD) foundation/pEp/jniadapter/*.java
$(JP)/jar cf $@ foundation/pEp/jniadapter/*.class
BLUBB=foundation_pEp_jniadapter_AbstractEngine.h foundation_pEp_jniadapter_Engine.h foundation_pEp_jniadapter_Message.h foundation_pEp_jniadapter__Blob.h
$(BLUBB): foundation_pEp_jniadapter_%.h: foundation/pEp/jniadapter/%.java
ifdef OLD_JAVA
$(JP)/javah $(subst /,.,$(subst .java,,$<))
else
$(JP)/$(JAVAC_CMD) -h . $<
endif
foundation_pEp_jniadapter_AbstractEngine.o: %.o: %.cc %.h throw_pEp_exception.hh jniutils.hh
$(CXX) $(CXXFLAGS) -c $< -o $@
foundation_pEp_jniadapter_Engine.o foundation_pEp_jniadapter_Message.o foundation_pEp_jniadapter__Blob.o : %.o: %.cc %.h
$(CXX) $(CXXFLAGS) -c $< -o $@
# ------------- YML2 CodeGen --------------
codegen:
$(MAKE) -C codegen
# ------------- Housekeeping ---------------
create-dirs:
$(MAKE) -C codegen create-dirs
mkdir -p $(JAVA_BUILD_ROOT)/$(JAVA_PKG_BASENAME)
mkdir -p $(JAVA_BUILD_ROOT)/$(JAVA_PKG_BASENAME)/exceptions
mkdir -p $(OBJ_DIR)
mkdir -p $(DIST_DIR)
mkdir -p $(JAVA_PKG_ROOT)/exceptions
#rm -rf is too dangerous for vars
remove-dirs:
$(MAKE) -C codegen remove-dirs
rm -rf ../build
rm -rf ../dist
clean: remove-dirs
$(MAKE) -C codegen clean
rm -f $(GENERATED_JAVA)
rm -f $(GENERATED_CC)
rm -f $(GENERATED_HH)
rm -f $(JNI_GENERATED_HH)
rm -f $(DEPENDS)
rm -f $(OBJECTS)
install: $(LIB_JAVA) $(LIB_CXX_STATIC) $(LIB_CXX_DYN)
mkdir -p $(PREFIX)/lib
cp -v $(LIB_JAVA) $(PREFIX)/lib/
cp -v $(LIB_CXX_STATIC) $(PREFIX)/lib/
cp -v $(LIB_CXX_DYN) $(PREFIX)/lib/
uninstall:
cd $(PREFIX)/lib && rm -vf $(LIB_JAVA_NAME)
cd $(PREFIX)/lib && rm -vf $(LIB_CXX_STATIC_NAME)
cd $(PREFIX)/lib && rm -vf $(LIB_CXX_DYN_NAME)
$(LIBRARY): foundation_pEp_jniadapter_AbstractEngine.o foundation_pEp_jniadapter_Engine.o foundation_pEp_jniadapter_Message.o throw_pEp_exception.o jniutils.o basic_api.o foundation_pEp_jniadapter__Blob.o
ar -r $@ *.o
$(SHARED): $(LIBRARY)
$(CXX) *.o $(LDFLAGS) $(LDLIBS) -o $@
status_list.yml2: pEp.yml2
bash ../utils/extract_pEp_status_codes_from_engine.sh "$(PEP_HEADER)" $@
passphrase_status_list.yml2: status_list.yml2
grep passphrase $< > $@
foundation/pEp/jniadapter/pEpException.java: pEp.yml2 gen_java_exceptions.ysl2 pEp.yml2
$(YML2_PROC) -y gen_java_exceptions.ysl2 $< -o $@
foundation/pEp/jniadapter/Message.java: pEp.yml2 gen_java_Message.ysl2 types_java.ysl2
$(YML2_PROC) -y gen_java_Message.ysl2 $<
foundation/pEp/jniadapter/Engine.java: pEp.yml2 gen_java_Engine.ysl2 types_java.ysl2
$(YML2_PROC) -y gen_java_Engine.ysl2 $<
foundation_pEp_jniadapter_Message.cc: pEp.yml2 gen_cpp_Message.ysl2 types_c.ysl2
$(YML2_PROC) -y gen_cpp_Message.ysl2 $<
foundation_pEp_jniadapter_Engine.cc: pEp.yml2 gen_cpp_Engine.ysl2 types_c.ysl2
$(YML2_PROC) -y gen_cpp_Engine.ysl2 $<
throw_pEp_exception.cc throw_pEp_exception.hh: pEp.yml2 gen_throw_pEp_exception.ysl2 textutils.ysl2
$(YML2_PROC) -y gen_throw_pEp_exception.ysl2 $< -o throw_pEp_exception.cc
throw_pEp_exception.o: throw_pEp_exception.cc throw_pEp_exception.hh
basic_api.o: basic_api.cc jniutils.hh throw_pEp_exception.hh
.PHONY: clean
clean:
rm -f $(JAR) $(LIBRARY) $(SHARED)
rm -f *.so
rm -f *.dylib
rm -f *.o
rm -f *.class
rm -f *.xml *.xsl
rm -f foundation_pEp_jniadapter_*.h
rm -f foundation/pEp/jniadapter/*.class
rm -f foundation/pEp/jniadapter/pEp*.java
rm -f foundation/pEp/jniadapter/Engine.java
rm -f foundation/pEp/jniadapter/Message.java
rm -f foundation/pEp/jniadapter/Color.java
rm -f foundation/pEp/jniadapter/DecryptFlags.java
rm -f foundation/pEp/jniadapter/IdentityFlags.java
rm -f foundation/pEp/jniadapter/Rating.java
rm -f foundation/pEp/jniadapter/Status.java
rm -f foundation/pEp/jniadapter/SyncHandshakeResult.java
rm -f foundation/pEp/jniadapter/SyncHandshakeSignal.java
rm -f foundation/pEp/jniadapter/CipherSuite.java
rm -f foundation/pEp/jniadapter/PassphraseType.java
rm -f throw_pEp_exception.*
rm -f foundation_pEp_jniadapter_Message.cc foundation_pEp_jniadapter_Engine.cc
rm -f status_list.yml2
rm -f passphrase_status_list.yml2

55
src/codegen/Makefile

@ -0,0 +1,55 @@
# Copyright 2018, pEp Foundation
# This file is part of pEp JNI Adapter
# This file may be used under the terms of the GNU General Public License version 3
# see LICENSE.txt
include ../../Makefile.conf
MARKER_DIR=../../build/marker/
PEP_HEADER:=$(shell $(CXX) $(CXXFLAGS) -E -M ../cxx/get_header.cc | grep -oe '[^[:space:]]*pEpEngine\.h' | head -1)
# Every ysl2 file that needs to be "compiled" separately, needs to generate a "marker" file
# The marker serves as the make target.
# If the marker file is older than its corresponding ysl2 file, or not exsiting, the ysl2 file will be "compiled"
# Naming:
# For a ysl2 file called "gen_example_stuff.ysl2", a marker file called "gen_example_stuff.marker" is expected.
YML2_MARKERS= \
$(MARKER_DIR)/gen_java_Engine.marker \
$(MARKER_DIR)/gen_java_Message.marker \
$(MARKER_DIR)/gen_cpp_Engine.marker \
$(MARKER_DIR)/gen_cpp_Message.marker \
$(MARKER_DIR)/gen_throw_pEp_exception.marker
# All code genration will be done upon change of these files
YML2_INCLUDES= \
textutils.ysl2 \
types_c.ysl2 \
types_java.ysl2
.PHONY: all codegen gen-status-codes create-dirs remove-dirs clean
all: codegen
# ------------- YML2 CodeGen --------------
codegen: create-dirs gen-status-codes $(YML2_MARKERS)
$(YML2_MARKERS): $(MARKER_DIR)/%.marker : %.ysl2 pEp.yml2 $(YML2_INCLUDES)
$(YML2_PROC) -y $< pEp.yml2
gen-status-codes: pEp.yml2
bash ../../utils/gen_status_codes.sh "$(PEP_HEADER)"
# ------------- Housekeeping ---------------
create-dirs:
mkdir -p $(MARKER_DIR)
#rm -rf is too dangerous for vars
remove-dirs:
rm -rf ../../build/marker
clean: remove-dirs
rm -f status_list.yml2
rm -f passphrase_status_list.yml2

80
src/gen_cpp_Engine.ysl2 → src/codegen/gen_cpp_Engine.ysl2

@ -5,10 +5,14 @@ tstylesheet {
include ./types_c.ysl2
include ./types_java.ysl2
template "/namespace[@name='pEp']" apply "interface", 0;
template "/namespace[@name='pEp']" {
apply "interface", 0;
document("../../build/marker/gen_cpp_Engine.marker", "text") > ""
}
template "interface" document("foundation_pEp_jniadapter_{@name}.cc", "text")
template "interface" document("../cxx/foundation_pEp_jniadapter_{@name}.cc", "text")
||
#include <cassert>
#include <pEp/blacklist.h>
#include <pEp/openpgp_compat.h>
#include <pEp/key_reset.h>
@ -47,10 +51,8 @@ tstylesheet {
}
||
JNIEXPORT «$CretType» JNICALL «$mangled»(
JNIEnv *env,
jobject obj`apply "parm[in|inout]", mode=sig`
)
JNIEXPORT «$CretType» JNICALL «$mangled»(JNIEnv *env,
jobject obj`apply "parm[in|inout]", mode=sig`)
{
std::mutex *mutex_local = nullptr;
{
@ -70,34 +72,7 @@ tstylesheet {
choose {
when "@cached = 'true'" {
||
pEpLog("cached passphrase mode");
bool retryAgain = false;
int maxRetries = 3;
int retryCount = 0;
PEP_STATUS status;
do {
// the actual target function
pEpLog("calling passphrase_cache.api(::«@name»())");
status = passphrase_cache.api(::«@name»,session()`apply "parm", mode=call`);
pEpLog("PEP_STATUS:" << status);
if(status == PEP_PASSPHRASE_REQUIRED || status == PEP_WRONG_PASSPHRASE || status == PEP_PASSPHRASE_FOR_NEW_KEYS_REQUIRED) {
pEpLog("none of the cached passphrases worked");
if(retryCount < maxRetries) {
// call the app
char* _passphrase = passphraseRequiredCallback(status);
pEpLog("callback returned, config_passphrase() with new passphrase");
PEP_STATUS status = ::config_passphrase(session(),passphrase_cache.add(_passphrase));
retryAgain = true;
retryCount++;
} else {
pEpLog("max retries reached:" << maxRetries);
retryAgain = false;
}
} else {
retryAgain = false;
}
} while (retryAgain);
PEP_STATUS status = passphraseWrap(::«@name», session()`apply "parm", mode=call`);
||
} otherwise {
||
@ -106,13 +81,11 @@ tstylesheet {
}
}
||
if ((status > PEP_STATUS_OK && status < PEP_UNENCRYPTED) |`> |`
status < PEP_STATUS_OK |`> |`
status >= PEP_TRUSTWORD_NOT_FOUND) {
if ((status > PEP_STATUS_OK && status < PEP_UNENCRYPTED) |`> |` status < PEP_STATUS_OK |`> |` status >= PEP_TRUSTWORD_NOT_FOUND) {
throw_pEp_Exception(env, status);
return «$CretDefault»;
}
||
apply "parm[returns|creates]", mode=return;
@ -211,9 +184,9 @@ tstylesheet {
}
||
«$jnitype» «$name»_ = NULL;
if (_«$name»)
if (_«$name») {
«$name»_ = «$from_type»(env, _«$name»);
}
||
}
when "ancestor::namespace/child::enum[@name=$type]" {
@ -223,14 +196,12 @@ tstylesheet {
{
jclass clazz_«$ljtype» = findClass(env, "foundation/pEp/jniadapter/«$jtype»");
assert(clazz_«$ljtype»);
jmethodID method_values = env->GetStaticMethodID(clazz_«$ljtype», "values",
"()[Lfoundation/pEp/jniadapter/«$jtype»;");
jmethodID method_values = env->GetStaticMethodID(clazz_«$ljtype», "values", "()[Lfoundation/pEp/jniadapter/«$jtype»;");
assert(method_values);
jfieldID field_value = env->GetFieldID(clazz_«$ljtype», "value", "I");
assert(field_value);
jobjectArray values = (jobjectArray) env->CallStaticObjectMethod(clazz_«$ljtype»,
method_values);
jobjectArray values = static_cast<jobjectArray>(env->CallStaticObjectMethod(clazz_«$ljtype», method_values));
assert(values);
if (env->ExceptionCheck()) {
return nullptr; // handle exception in Java
@ -241,7 +212,7 @@ tstylesheet {
jobject element = env->GetObjectArrayElement(values, i);
assert(element);
jint value = env->GetIntField(element, field_value);
if (value == (jint) _«$name») {
if (value == static_cast<jint>(_«$name»)) {
«$name»_ = element;
break;
}
@ -258,7 +229,7 @@ tstylesheet {
assert(clazz_«$name»_);
jmethodID constructor_«$name»_ = env->GetMethodID(clazz_«$name»_, "<init>", "(J)V");
assert(constructor_«$name»_);
«$name»_ = env->NewObject(clazz_«$name»_, constructor_«$name»_, (jlong) _«$name»);
«$name»_ = env->NewObject(clazz_«$name»_, constructor_«$name»_, reinterpret_cast<jlong>(_«$name»));
}
||
@ -274,15 +245,15 @@ tstylesheet {
choose {
when "$type = 'message'"
| message *_«$name» = (message *) callLongMethod(env, «$name», "getHandle");
| message *_«$name» = reinterpret_cast<message *>(callLongMethod(env, «$name», "getHandle"));
when "$type='EncFormat' or $type='SyncHandshakeResult' or $type='CipherSuite'"
| √$type _«$name» = to_«$type»(env, «$name»);
when "$type='bool'"
| bool _«$name» = (bool) «$name»;
| bool _«$name» = «$name»;
when "$type='int'"
| int _«$name» = (int) «$name»;
| int _«$name» = «$name»;
when "$type='uint'"
| auto _«$name» = (unsigned int) «$name»;
| unsigned int _«$name» = «$name»;
when "$type='string'"
| const char *_«$name» = to_string(env, «$name»);
otherwise {
@ -336,14 +307,7 @@ tstylesheet {
}
function "mangle" {
const "convert", "count(parm/stringlist|parm/string|parm/identity|parm/identitylist) > 0";
choose {
when "$convert"
> «concat('Java_foundation_pEp_jniadapter_', ../@name, '__1', str:replace(@name, '_', '_1'))»
otherwise
> «concat('Java_foundation_pEp_jniadapter_', ../@name, '_', str:replace(@name, '_', '_1'))»
}
> «concat('Java_foundation_pEp_jniadapter_', ../@name, '__1', str:replace(@name, '_', '_1'))»
}
template "parm", mode=sig {

84
src/gen_cpp_Message.ysl2 → src/codegen/gen_cpp_Message.ysl2

@ -5,12 +5,15 @@ tstylesheet {
include ./textutils.ysl2
include ./types_c.ysl2
template "/namespace[@name='pEp']" apply "struct", 0;
template "/namespace[@name='pEp']" {
apply "struct", 0;
document("../../build/marker/gen_cpp_Message.marker", "text") > ""
}
template "struct" {
const "jname" call "CamelCase" with "text", "@name";
document("foundation_pEp_jniadapter_{$jname}.cc", "text") {
document("../cxx/foundation_pEp_jniadapter_{$jname}.cc", "text") {
||
#include <cassert>
#include <pEp/mime.h>
@ -22,70 +25,79 @@ tstylesheet {
using namespace std;
namespace pEp {
namespace JNIAdapter {
static ::«@name» *«@name»_ptr(JNIEnv *env, jobject me) {
jfieldID handle;
try {
handle = getFieldID(env, "foundation/pEp/jniadapter/«$jname»", "handle", "J");
}
catch (std::exception& ex) {
assert(0);
return NULL;
}
namespace JNIAdapter {
static ::«@name» *«@name»_ptr(JNIEnv *env, jobject me) {
jfieldID handle;
try {
handle = getFieldID(env, "foundation/pEp/jniadapter/«$jname»", "handle", "J");
} catch (std::exception& ex) {
assert(0);
return NULL;
}
return reinterpret_cast<::«@name» *>(env->GetLongField(me, handle));
}
return (::«@name» *) (intptr_t) (int64_t) env->GetLongField(me, handle);
}
};
};
};
extern "C" {
using namespace pEp::JNIAdapter;
JNIEXPORT jlong JNICALL Java_foundation_pEp_jniadapter_«$jname»_init(JNIEnv *env, jobject obj)
JNIEXPORT jlong JNICALL Java_foundation_pEp_jniadapter_«$jname»_init(JNIEnv *env,
jobject obj)
{
pEpLog("called");
::«@name» * _obj = ::new_«@name»(PEP_dir_incoming);
if (!_obj) {
outOfMemory(env);
return (jlong) 0;
return 0;
}
return (jlong) (int64_t) (intptr_t) _obj;
return reinterpret_cast<jlong>(_obj);
}
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_«$jname»_release(JNIEnv *env, jobject obj, jlong value)
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_«$jname»_release(JNIEnv *env,
jobject obj,
jlong value)
{
pEpLog("called");
if (value) {
::«@name» *_obj = (::«@name» *) (intptr_t) (int64_t) value;
::«@name» *_obj = reinterpret_cast<::«@name» *>(value);
::free_«@name»(_obj);
}
}
JNIEXPORT jlong JNICALL Java_foundation_pEp_jniadapter_«$jname»__1«$jname»(JNIEnv *env, jobject msg, jbyteArray mime_text)
JNIEXPORT jlong JNICALL Java_foundation_pEp_jniadapter_«$jname»__1«$jname»(JNIEnv *env,
jobject msg,
jbyteArray mime_text)
{
pEpLog("called");
char *_mime_text = to_string(env, mime_text);
size_t _size = (size_t) env->GetArrayLength(mime_text);
size_t _size = env->GetArrayLength(mime_text);
::«@name» *_msg = nullptr;
PEP_STATUS status = mime_decode_«@name»(_mime_text, _size, &_msg, NULL);
if (status)
if (status) {
throw_pEp_Exception(env, status);
return (jlong) (int64_t) (intptr_t) _msg;
}
return reinterpret_cast<jlong>(_msg);
}
JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter_«$jname»__1encodeMIME(JNIEnv *env, jobject msg)
JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter_«$jname»__1encodeMIME(JNIEnv *env,
jobject msg)
{
pEpLog("called");
«@name» *_obj = «@name»_ptr(env, msg);
char *mime_text = nullptr;
PEP_STATUS status = ::mime_encode_«@name»(_obj, false, &mime_text, false);
if (status)
if (status) {
throw_pEp_Exception(env, status);
}
jbyteArray result = from_string(env, mime_text);
free(mime_text);
return result;
}
@ -131,28 +143,32 @@ tstylesheet {
with "name", "concat('set', $jname)";
}
||
JNIEXPORT `call "jni_type" with "type", "name(.)"` JNICALL «$getname»(JNIEnv *env, jobject obj)
JNIEXPORT `call "jni_type" with "type", "name(.)"` JNICALL «$getname»(JNIEnv *env,
jobject obj)
{
pEpLog("called");
«$name» *_obj = «$name»_ptr(env, obj);
||
choose {
when "../enum[@name=$type]"
|> return (jint) _obj->«$cname»;
|> return _obj->«$cname»;
otherwise
|> return from_«$type»(env, _obj->«$cname»);
}
||
}
JNIEXPORT void JNICALL «$setname»(JNIEnv *env, jobject obj, `call "jni_type" with "type", "name(.)"` value)
JNIEXPORT void JNICALL «$setname»(JNIEnv *env,
jobject obj,
`call "jni_type" with "type", "name(.)"`
value)
{
pEpLog("called");
«$name» *_obj = «$name»_ptr(env, obj);
||
choose {
when "../enum[@name=$type]"
|> _obj->«$cname» = («$ctype») (int) value;
|> _obj->«$cname» = static_cast<«$ctype»>(value);
otherwise {
choose {
when "$type = 'string'" {
@ -168,7 +184,7 @@ tstylesheet {
|> free_«$free»(_obj->«$cname»);
}
}
|> if(value){
|> if(value) {
choose {
when "$type = 'string'" {
|>> _obj->«$cname» = to_«$type»(env, value);
@ -177,9 +193,9 @@ tstylesheet {
|>> _obj->«$cname» = to_«$type»(env, value);
}
}
|> }else{
|> } else {
|> _obj->«$cname» = NULL;
|> }
|> }
}
}
||

186
src/gen_java_Engine.ysl2 → src/codegen/gen_java_Engine.ysl2

@ -4,24 +4,41 @@ tstylesheet {
include ./textutils.ysl2
include ./types_java.ysl2
template "/namespace[@name='pEp']" apply "interface", 0;
template "/namespace[@name='pEp']" {
apply "interface", 0;
document("../../build/marker/gen_java_Engine.marker", "text") > ""
}
template "interface" {
const "cname" call "toJava" with "type", "@name";
document("foundation/pEp/jniadapter/{$cname}.java", "text")
document("../java/foundation/pEp/jniadapter/{$cname}.java", "text")
||
package foundation.pEp.jniadapter;
import foundation.pEp.jniadapter.interfaces.*;
import foundation.pEp.jniadapter.exceptions.*;
import java.util.ArrayList;
import java.util.Vector;
final public class «$cname» extends AbstractEngine {
final public class «$cname» extends AbstractEngine implements EngineInterface {
public «$cname»() throws pEpException { }
`` apply "method", mode=plain
`` apply "method"
`` apply "basic"
}
||
document("../java/foundation/pEp/jniadapter/interfaces/{$cname}Interface.java", "text")
||
package foundation.pEp.jniadapter.interfaces;
import foundation.pEp.jniadapter.*;
import java.util.ArrayList;
import java.util.Vector;
public interface «$cname»Interface extends AbstractEngineInterface {
`` apply "method", mode=java_interface
`` apply "basic", mode=java_interface
}
||
}
@ -29,48 +46,49 @@ tstylesheet {
const "itype" call "toIntermediate" with "type", "@type";
const "jtype" call "toJava" with "type", "@type";
choose {
when "name(parm/*[1])='bytearray|identitylist'"
||
public native «$itype» «@name»(`apply "parm/*", mode=basic_iparm`);
||
otherwise {
||
private native «$itype» _«@name»(`apply "parm/*", mode=basic_iparm`);
||
public «$jtype» «@name»(`apply "parm/*", mode=basic_parm`) {
// CodeGen "basic"
public «$jtype» «@name»(`apply "parm/*", mode=basic_parm`) {
||
apply "parm/*", mode=basic_parm_set;
choose {
when "@type = 'void'"
|> _«@name»(`apply "parm/*", mode=basic_parm_name`);
when "@type = 'identity'"
|> return new Identity(_«@name»(`apply "parm/*", mode=basic_parm_name`));
when "@type = 'bool'"
|> return new Boolean(_«@name»(`apply "parm/*", mode=basic_parm_name`));
when "@type = 'identitylist'" {
||
apply "parm/*", mode=basic_parm_set;
choose {
when "@type = 'void'"
|> _«@name»(`apply "parm/*", mode=basic_parm_name`);
when "@type = 'identity'"
|> return new Identity(_«@name»(`apply "parm/*", mode=basic_parm_name`));
when "@type = 'bool'"
|> return new Boolean(_«@name»(`apply "parm/*", mode=basic_parm_name`));
when "@type = 'identitylist'" {
||
Vector<_Identity> glist = _«@name»(`apply "parm/*", mode=basic_parm_name`);
Vector<Identity> ret = new Vector<Identity>();
if(glist != null) {
for (_Identity i : glist) {
ret.add(new Identity(i));
}
Vector<_Identity> glist = _«@name»(`apply "parm/*", mode=basic_parm_name`);
Vector<Identity> ret = new Vector<Identity>();
if(glist != null) {
for (_Identity i : glist) {
ret.add(new Identity(i));
}
return ret;
||
} otherwise
|> return AbstractEngine.toUTF16(_«@name»(`apply "parm/*", mode=basic_parm_name`));
}
||
}
}
return ret;
||
}
} when "@type = 'bytearray'"
|> return _«@name»(`apply "parm/*", mode=basic_parm_name`);
otherwise
|> return Utils.toUTF16(_«@name»(`apply "parm/*", mode=basic_parm_name`));
}
||
}
private native «$itype» _«@name»(`apply "parm/*", mode=basic_iparm`);
||
}
template "basic" mode=java_interface {
const "jtype" call "toJava" with "type", "@type";
||
public «$jtype» «@name»(`apply "parm/*", mode=basic_parm`);
||
}
template "*", mode=basic_parm_name choose {
when "position() mod 2" {
if "position() = 1 and name(.)='int'"
@ -125,7 +143,7 @@ tstylesheet {
if "not(position() mod 2)" choose {
when "$ptype = 'string'"
| «$pitype» _«$pname» = AbstractEngine.toUTF8(«$pname»);
| «$pitype» _«$pname» = Utils.toUTF8(«$pname»);
when "$ptype = 'bool'"
| «$pitype» _«$pname» = «$pname».booleanValue();
when "$ptype = 'bytearray'"
@ -161,59 +179,47 @@ tstylesheet {
}
}
template "method", mode=plain {
const "convert", "count(parm/stringlist|parm/stringpairlist|parm/string|parm/identity|parm/identitylist) > 0";
template "method" {
const "singlereturn", "count(parm/creates|parm/returns|parm/inout[../int]) = 1";
const "multireturn", "count(parm/creates|parm/returns|parm/inout[../int]) > 1";
||
//CodeGen "method"
||
if "$multireturn" {
if "$convert"
||
//CodeGen "mutlireturn" - class for return type
private class _«@name»_Return {
`` apply "parm[creates|returns|inout[../int]]", 1, mode=intermediate with "public", 1;
}
||
||
public class «@name»_Return {
`` apply "parm[creates|returns|inout[../int]]", 1, mode=java with "public", 1;
}
||
}
if "$convert"
||
private native `call "returnInter"` _«@name»(
`` apply "parm[in|inout]", 2, mode=intermediate
) throws pEpException;
||
||
public `if "not($convert)" > native ``call "returnJava"` «@name»(
public `call "returnJava"` «@name»(
`` apply "parm[in|inout]", 2, mode=java
) throws pEpException`if "not($convert)" > ;`
) throws pEpException
{
||
if "$convert" {
| {
apply "parm", mode=convertIn;
if "$singlereturn" choose {
// TODO factorize type conversion with multireturn and gen_java_message.java
apply "parm", mode=convertIn;
if "$singlereturn" {
choose {
when "count(parm[returns][stringlist|string|sstring]) > 0"
|> return AbstractEngine.toUTF16(_«@name»(`apply "parm[in]", mode=call;`));
|> return Utils.toUTF16(_«@name»(`apply "parm[in]", mode=call;`));
when "count(parm[returns]/stringpairlist) > 0"
||
ArrayList<Pair<byte[], byte[]>> glist = _«@name»(`apply "parm[in]", mode=call;`);
if(glist != null){
ArrayList<Pair<String, String>> list = new ArrayList<Pair<String, String>>();
for (Pair<byte[],byte[]> i : glist)
list.add(new Pair<String, String>(AbstractEngine.toUTF16(i.first), AbstractEngine.toUTF16(i.second)));
for (Pair<byte[],byte[]> i : glist) {
list.add(new Pair<String, String>(Utils.toUTF16(i.first), Utils.toUTF16(i.second)));
}
return list;
}
return null;
@ -221,40 +227,53 @@ tstylesheet {
when "count(parm[returns]/identity) > 0"
|> return new Identity(_«@name»(`apply "parm[in]", mode=call;`));
when "count(parm[returns]/identitylist) > 0"
||
Vector<_Identity> glist = _«@name»(`apply "parm[in]", mode=call;`);
if(glist != null){
Vector<Identity> list = new Vector<Identity>();
for (_Identity i : glist)
for (_Identity i : glist) {
list.add(new Identity(i));
}
return list;
}
return null;
||
otherwise
|> return _«@name»(`apply "parm[in]", mode=call;`);
}
}
if "$multireturn"
if "$multireturn" {
||
_«@name»_Return _result = _«@name»(`apply "parm[in|inout]", mode=call;`);
«@name»_Return result = new «@name»_Return();
`` apply "parm[creates|returns|inout[../int]]", mode=convertOut;
return result;
||
}
if "not($singlereturn) and not($multireturn)"
if "not($singlereturn) and not($multireturn)" {
||
_«@name»(`apply "parm[in]", mode=call;`);
return;
||
||
}
||
}
||
}
private native `call "returnInter"` _«@name»(
`` apply "parm[in|inout]", 2, mode=intermediate
) throws pEpException;
||
}
template "method", mode=java_interface {
||
public `call "returnJava"` «@name»(
`` apply "parm[in|inout]", 2, mode=java
);
||
}
@ -302,7 +321,7 @@ tstylesheet {
if "$dir = 'in' or $dir = 'inout'" choose {
when "$type = 'string' or $type = 'stringlist'"
| ¡$type _«$name» = AbstractEngine.toUTF8(«$name»);
| ¡$type _«$name» = Utils.toUTF8(«$name»);
when "$type = 'identity'"
||
_Identity _«$name» = null;
@ -313,8 +332,9 @@ tstylesheet {
when "$type = 'identitylist'"
||
Vector<_Identity> _«$name» = new Vector<_Identity>();
for (Identity i : «$name»)
for (Identity i : «$name») {
_«$name».add(new _Identity(i));
}
||
}
}
@ -326,7 +346,7 @@ tstylesheet {
if "$dir != 'in'" choose {
when "$type = 'string' or $type = 'stringlist'"
| result.«$name» = AbstractEngine.toUTF16(_result.«$name»);
| result.«$name» = Utils.toUTF16(_result.«$name»);
when "$type = 'identity'"
| result.«$name» = Identity(«$name»);
otherwise

368
src/codegen/gen_java_Message.ysl2

@ -0,0 +1,368 @@
include yslt.yml2
tstylesheet {
include ./textutils.ysl2
include ./types_java.ysl2
template "/namespace[@name='pEp']" {
apply "struct|enum|exception", 0;
document "../java/foundation/pEp/jniadapter/exceptions/pEpException.java", "text" {
||
package foundation.pEp.jniadapter.exceptions;
public class pEpException extends RuntimeException {
public pEpException(String message) {
super(message);
}
}
||
}
document("../../build/marker/gen_java_Message.marker", "text") > ""
}
template "struct" {
const "cname" call "toJava" with "type", "@name";
document("../java/foundation/pEp/jniadapter/{$cname}.java", "text")
||
package foundation.pEp.jniadapter;
import foundation.pEp.jniadapter.interfaces.*;
import foundation.pEp.jniadapter.exceptions.*;
import java.util.ArrayList;
import java.util.Vector;
import java.util.Date;
import java.util.HashMap;
import java.io.Serializable;
public class «$cname» implements MessageInterface, AutoCloseable, Serializable {
private static final long serialVersionUID = 2119420428331150924L;
private long handle;
native long init();
native void release(long handle);
public «$cname»() {
handle = init();
}
private native long _«$cname»(
byte[] mime_text
) throws pEpException;
public «$cname»(String mime_text) {
byte[] _mime_text = Utils.toUTF8(mime_text);
handle = _«$cname»(_mime_text);
}
private native byte[] _encodeMIME() throws pEpException;
public String encodeMIME() {
return Utils.toUTF16(_encodeMIME());
}
private «$cname»(long h) {
handle = h;
}
public final void close() {
release(handle);
}
final protected long getHandle() {
return handle;
}
`` apply "enum", mode=inner
`` apply "*[name(.)!='enum']", mode=entry
}
||
document("../java/foundation/pEp/jniadapter/interfaces/{$cname}Interface.java", "text")
||
package foundation.pEp.jniadapter.interfaces;
import foundation.pEp.jniadapter.*;
import foundation.pEp.jniadapter.Message.*;
import java.util.Date;
import java.util.Vector;
import java.util.ArrayList;
public interface «$cname»Interface {
public String encodeMIME();
`` apply "*[name(.)!='enum']", mode=interface
}
||
}
template "enum" {
const "jname" call "toJava" with "type", "@name";
document("../java/foundation/pEp/jniadapter/{$jname}.java", "text")
||
// CodeGen template enum
package foundation.pEp.jniadapter;
import java.util.HashMap;
`` apply ".", 0, mode=inner
||
}
template "enum", mode=inner {
const "jname" call "CamelCase" with "text", "@name";
||
// CodeGen template enum, mode=inner
public enum «$jname» {
`` apply "enumitem"
;
public final int value;
private static HashMap<Integer, «$jname»> intMap;
private «$jname»(int value) {
this.value = value;
}
public static «$jname» getByInt(int value){
if (intMap == null) {
intMap = new HashMap<Integer, «$jname»>();
for («$jname» s : «$jname».values()) {
intMap.put(s.value, s);
}
}
if (intMap.containsKey(value)) {
return intMap.get(value);
}
return null;
}
||
choose {
when "@has_int_str_val = 'true'" {
||
public String getInternalStringValue() {
return "Unimplemented";
}
||
}
}
||
}
||
}
function "exception" {
param "name";
document "../java/foundation/pEp/jniadapter/exceptions/{$name}.java", "text" {
| package foundation.pEp.jniadapter.exceptions;
|
| public class «$name» extends pEpException {
| public «$name»(String message) {
| super(message);
| }
| }
}
}
template "exception" for "*[text()!=0]" call "exception"
with "name" call "CamelCase" with "text", "name(.)";
template "*", mode=entry {
const "ctype", "name(.)";
const "type" call "toJava" with "type", "name(.)";
const "itype" call "toIntermediate" with "type", "name(.)";
const "name" call "toJava" with "type", "name(*[position()=1])";
||
// CodeGen template * mode=entry
||
choose {
when "$ctype = 'identity'" {
||
// Property type: Identity. [java: «$type», intermediate: «$itype», ctype: «$ctype»]
public «$type» get«$name»() {
«$itype» res = _get«$name»();
if (res != null) {
return new «$type»(_get«$name»());
} else {
return null;
}
}
private native «$itype» _get«$name»();
public void set«$name»(«$type» value) {
if (value != null) {
_set«$name»(new «$itype»(value));
} else {
_set«$name»(null);
}
}
private native void _set«$name»(«$itype» value);
||
}
when "$ctype = 'identitylist' or $ctype = 'bloblist' or $ctype = 'stringlist' or $ctype = 'stringpairlist'" {
const "ename", "substring-after(substring($type,1,string-length($type)-1), '<')";
const "iename" choose {
when "$ctype = 'stringlist'" > byte[]
when "$ctype = 'stringpairlist'" > Pair<byte[],byte[]>
otherwise > _«$ename»
}
const "convget" choose {
when "$ctype = 'stringlist'" > Utils.toUTF16(i)
when "$ctype = 'stringpairlist'" > new Pair<String, String>(Utils.toUTF16(i.first), Utils.toUTF16(i.second))
otherwise > new «$ename»(i)
}
const "convset" choose {
when "$ctype = 'stringlist'" > Utils.toUTF8(i)
when "$ctype = 'stringpairlist'" > new Pair<byte[],byte[]>(Utils.toUTF8(i.first), Utils.toUTF8(i.second))
otherwise > new _«$ename»(i)
}
||
// Property type: list type. [java: «$type», intermediate: «$itype», ctype: «$ctype»]
public «$type» get«$name»() {
«$itype» glist = _get«$name»();
if (glist != null) {
«$type» list = new «$type»();
for («$iename» i : glist) {
list.add(«$convget»);
}
return list;
}
return null;
}
private native «$itype» _get«$name»();
public void set«$name»(«$type» value) {
if (value != null) {
«$itype» list = new «$itype»();
for («$ename» i : value) {
list.add(«$convset»);
}
_set«$name»(list);
} else {
_set«$name»(null);
}
}
private native void _set«$name»(«$itype» value);
||
}
when "$itype != $type" {
||
// Property type: differs from intermediate. [java: «$type», intermediate: «$itype», ctype: «$ctype»]
public «$type» get«$name»() {
«$itype» res = _get«$name»();
if (res != null) {
return Utils.toUTF16(res);
} else {
return null;
}
}
private native «$itype» _get«$name»();
public void set«$name»(«$type» value) {
if (value != null) {
_set«$name»(Utils.toUTF8(value));
} else {
_set«$name»(new byte[0]);
}
}
private native void _set«$name»(«$itype» value);
||
}
when "../enum[@name=$ctype]" {
||
// Property type: enum type. [java: «$type», intermediate: «$itype», ctype: «$ctype»]
public «$type» get«$name»() {
return «$type».getByInt(_get«$name»());
}
private native int _get«$name»();
public void set«$name»(«$type» value) {
if(value != null)
_set«$name»(value.value);
else
_set«$name»(0);
}
private native void _set«$name»(int value);
||
}
otherwise {
||
// Property type: no intermediate type [java: «$type», intermediate: «$itype», ctype: «$ctype»]
public «$type» get«$name»() {
return get«$name»();
}
private native «$type» _get«$name»();
public void set«$name»(«$type» value) {
_set«$name»(value);
}
private native void _set«$name»(«$type» value);
||
}
}
}
template "*", mode=interface {
const "type" call "toJava" with "type", "name(.)";
const "name" call "toJava" with "type", "name(*[position()=1])";
||
public «$type» get«$name»();
public void set«$name»(«$type» value);
||
}
template "enumitem" {
const "name_hyphenized" call "hyphenize" with "text", "@name";
const "javaname" call "toJava" with "type", "$name_hyphenized";
const "enum_index", ".";
||
«$javaname» («$enum_index») {
public String toString() {
||
choose {
when "@toString" {
||
return "«@toString»";
||
} otherwise {
||
return "«$javaname»";
||
}
}
||
}
||
choose {
when "@int_str_val" {
||
public String getInternalStringValue() {
return "«@int_str_val»";
}
||
}
}
| }`if "position()!=last()" > , `
}
}

65
src/codegen/gen_throw_pEp_exception.ysl2

@ -0,0 +1,65 @@
include yslt.yml2
tstylesheet {
include ./textutils.ysl2
template "/" {
apply "namespace", 0;
document "../cxx/throw_pEp_exception.hh", "text"
||
#pragma once
#include <jni.h>
namespace pEp {
namespace JNIAdapter {
jint throw_pEp_Exception(JNIEnv *env, PEP_STATUS status);
};
};
||
document("../../build/marker/gen_throw_pEp_exception.marker", "text") > ""
}
template "namespace"
document("../cxx/throw_pEp_exception.cc", "text")
||
#include <assert.h>
#include <pEp/pEpEngine.h>
#include "throw_pEp_exception.hh"
namespace pEp {
namespace JNIAdapter {
jint throw_pEp_Exception(JNIEnv *env, PEP_STATUS status)
{
jclass ex;
const char *ex_name;
switch (status) {
`` apply "exception/*[text()!=0]", 4, mode=case
default:
assert(0);
ex_name = "Exception";
}
ex = env->FindClass(ex_name);
assert(ex);
if (ex == NULL) {
ex = env->FindClass("java/lang/NoClassDefFoundError");
assert(ex);
}
return env->ThrowNew(ex, ex_name);
}
};
};
||
template "*", mode=case {
| case `call "UCASE" with "text", "name(.)"`:
| ex_name = "foundation/pEp/jniadapter/exceptions/`call "CamelCase" with "text", "name(.)"`";
| break;
}
}

178
src/pEp.yml2 → src/codegen/pEp.yml2

@ -1,5 +1,6 @@
decl namespace @name;
decl enum @name;
decl enumitem @name;
decl interface @name;
decl exception @name;
decl method @name;
@ -16,77 +17,74 @@ namespace pEp {
};
enum Color {
PEP_color_no_color > 0
PEP_color_yellow > 1
PEP_color_green > 2
PEP_color_red > -1
enumitem PEP_color_no_color toString="None" > 0
enumitem PEP_color_yellow toString="Yellow" > 1
enumitem PEP_color_green toString="Green" > 2
enumitem PEP_color_red toString="Red" > -1
};
enum Rating {
pEp_rating_undefined > 0
pEp_rating_cannot_decrypt > 1
pEp_rating_have_no_key > 2
pEp_rating_unencrypted > 3
pEp_rating_unencrypted_for_some > 4
pEp_rating_unreliable > 5
pEp_rating_reliable > 6
pEp_rating_trusted > 7
pEp_rating_trusted_and_anonymized > 8
pEp_rating_fully_anonymous > 9
pEp_rating_mistrust > -1
pEp_rating_b0rken > -2
pEp_rating_under_attack > -3
enum has_int_str_val=true Rating {
enumitem pEp_rating_undefined int_str_val=undefined > 0
enumitem pEp_rating_cannot_decrypt int_str_val=cannot_decrypt > 1
enumitem pEp_rating_have_no_key int_str_val=have_no_key > 2
enumitem pEp_rating_unencrypted int_str_val=unencrypted > 3
enumitem pEp_rating_unencrypted_for_some int_str_val=unencrypted_for_some > 4
enumitem pEp_rating_unreliable int_str_val=unreliable > 5
enumitem pEp_rating_reliable int_str_val=reliable > 6
enumitem pEp_rating_trusted int_str_val=trusted > 7
enumitem pEp_rating_trusted_and_anonymized int_str_val=trusted_and_anonymized > 8
enumitem pEp_rating_fully_anonymous int_str_val=fully_anonymous > 9
enumitem pEp_rating_mistrust int_str_val=mistrust > -1
enumitem pEp_rating_b0rken int_str_val=b0rken > -2
enumitem pEp_rating_under_attack int_str_val=under_attack > -3
};
enum DecryptFlags {
pEp_decrypt_flag_own_private_key > 1
pEp_decrypt_flag_consumed > 2
pEp_decrypt_flag_ignored > 4
pEp_decrypt_flag_src_modified > 8
pEp_decrypt_flag_untrusted_server > 0x100
pEp_decrypt_flag_dont_trigger_sync > 0x200
enumitem pEp_decrypt_flag_own_private_key > 1
enumitem pEp_decrypt_flag_consumed > 2
enumitem pEp_decrypt_flag_ignored > 4
enumitem pEp_decrypt_flag_src_modified > 8
enumitem pEp_decrypt_flag_untrusted_server > 0x100
enumitem pEp_decrypt_flag_dont_trigger_sync > 0x200
};
enum IdentityFlags {
pEp_idf_not_for_sync > 1
pEp_idf_list > 2
pEp_idf_devicegroup > 256
enumitem pEp_idf_not_for_sync > 1
enumitem pEp_idf_list > 2
enumitem pEp_idf_devicegroup > 256
};
enum SyncHandshakeResult {
sync_handshake_cancel > -1
sync_handshake_accepted > 0
sync_handshake_rejected > 1
enumitem sync_handshake_cancel > -1
enumitem sync_handshake_accepted > 0
enumitem sync_handshake_rejected > 1
};
enum SyncHandshakeSignal {
sync_notify_undefined > 0
sync_notify_init_add_our_device > 1
sync_notify_init_add_other_device > 2
sync_notify_init_form_group > 3
// sync_notify_init_move_our_device > 4
sync_notify_timeout > 5
sync_notify_accepted_device_added > 6
sync_notify_accepted_group_created > 7
sync_notify_accepted_device_accepted > 8
// sync_notify_overtaken > 9
// sync_notify_forming_group > 10
sync_passphrase_required > 128
sync_notify_sole > 254
sync_notify_in_group > 255
enumitem sync_notify_undefined > 0
enumitem sync_notify_init_add_our_device > 1
enumitem sync_notify_init_add_other_device > 2
enumitem sync_notify_init_form_group > 3
enumitem sync_notify_timeout > 5
enumitem sync_notify_accepted_device_added > 6
enumitem sync_notify_accepted_group_created > 7
enumitem sync_notify_accepted_device_accepted > 8
enumitem sync_passphrase_required > 128
enumitem sync_notify_sole > 254
enumitem sync_notify_in_group > 255
};
enum CipherSuite {
pEp_cipher_suite_default > 0
pEp_cipher_suite_cv25519 > 1
pEp_cipher_suite_p256 > 2
pEp_cipher_suite_p384 > 3
pEp_cipher_suite_p521 > 4
pEp_cipher_suite_rsa2k > 5
pEp_cipher_suite_rsa3k > 6
pEp_cipher_suite_rsa4k > 7
pEp_cipher_suite_rsa8k > 8
enumitem pEp_cipher_suite_default > 0
enumitem pEp_cipher_suite_cv25519 > 1
enumitem pEp_cipher_suite_p256 > 2
enumitem pEp_cipher_suite_p384 > 3
enumitem pEp_cipher_suite_p521 > 4
enumitem pEp_cipher_suite_rsa2k > 5
enumitem pEp_cipher_suite_rsa3k > 6
enumitem pEp_cipher_suite_rsa4k > 7
enumitem pEp_cipher_suite_rsa8k > 8
};
interface Engine {
@ -248,6 +246,9 @@ namespace pEp {
in CipherSuite suite
);
method enter_device_group(
in identitylist identities const
);
// "basic" methods are generated on the java side, but
// on the C++ side, manually implemented in basic_api.cc
@ -271,52 +272,53 @@ namespace pEp {
basic string getMachineDirectory();
basic void config_passphrase(string passphrase);
basic void config_passphrase_for_new_keys(bool enable, string passphrase);
basic bytearray export_key(string fpr);
};
struct message {
enum TextFormat {
plain > 0
html > 1
other > 255
enumitem plain > 0
enumitem html > 1
enumitem other > 255
}
enum direction {
incoming > 0
outgoing > 1
enumitem incoming > 0
enumitem outgoing > 1
}
enum EncFormat {
none > 0
pieces > 1
inline > 1
SMIME > 2
PGPMIME > 3
PEP > 4
PGP_MIME_Outlook1 > 5
PEP_enc_inline_EA > 6
PEP_enc_auto > 255
enumitem none > 0
enumitem pieces > 1
enumitem inline > 1
enumitem SMIME > 2
enumitem PGPMIME > 3
enumitem PEP > 4
enumitem PGP_MIME_Outlook1 > 5
enumitem PEP_enc_inline_EA > 6
enumitem PEP_enc_auto > 255
}
direction dir;
string id;
string shortmsg;
string longmsg;
string longmsg_formatted;
bloblist attachments;
timestamp sent;
timestamp recv;
identity from;
identitylist to;
identity recv_by;
identitylist cc;
identitylist bcc;
identitylist reply_to;
stringlist in_reply_to;
stringlist references;
stringlist keywords;
string comments;
stringpairlist opt_fields;
EncFormat enc_format;
direction dir;
string id;
string shortmsg;
string longmsg;
string longmsg_formatted;
bloblist attachments;
timestamp sent;
timestamp recv;
identity from;
identitylist to;
identity recv_by;
identitylist cc;
identitylist bcc;
identitylist reply_to;
stringlist in_reply_to;
stringlist references;
stringlist keywords;
string comments;
stringpairlist opt_fields;
EncFormat enc_format;
};
};

6
src/textutils.ysl2 → src/codegen/textutils.ysl2

@ -10,6 +10,12 @@ function "lcase" {
value "translate($text, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ-', 'abcdefghijklmnopqrstuvwxyz_')";
}
function "hyphenize" {
param "text";
value "translate($text, '_', '-')";
}
function "CamelCase" {
param "text";
const "tokens", "str:tokenize($text, '-')";

0
src/types_c.ysl2 → src/codegen/types_c.ysl2

0
src/types_java.ysl2 → src/codegen/types_java.ysl2

200
src/basic_api.cc → src/cxx/basic_api.cc

@ -12,15 +12,14 @@
#include "passphrase_callback.hh"
extern "C" {
using namespace pEp::JNIAdapter;
using pEp::Adapter::session;
using pEp::passphrase_cache;
JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter_Engine__1trustwords(
JNIEnv *env,
using namespace pEp::JNIAdapter;
using pEp::Adapter::session;
using pEp::passphrase_cache;
JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter_Engine__1trustwords(JNIEnv *env,
jobject obj,
jobject ident
)
jobject ident)
{
std::mutex *mutex_local = nullptr;
{
@ -37,10 +36,11 @@ JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter_Engine__1trustwords(
PEP_STATUS status = PEP_STATUS_OK;
if (_ident->fpr == NULL || _ident->fpr[0] == 0) {
if (_ident->me)
if (_ident->me) {
status = passphraseWrap(::myself, session(), _ident);
else
} else {
status = passphraseWrap(::update_identity, session(), _ident);
}
}
if (status != PEP_STATUS_OK) {
@ -54,13 +54,13 @@ JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter_Engine__1trustwords(
}
const char *lang;
if (_ident->lang[0])
if (_ident->lang[0]) {
lang = _ident->lang;
else
} else {
lang = "en";
}
status = passphraseWrap(::trustwords,
session(), (const char *) _ident->fpr, lang, &words, &wsize, 10);
status = passphraseWrap(::trustwords, session(), static_cast<const char *>(_ident->fpr), lang, &words, &wsize, 10);
if (status != PEP_STATUS_OK) {
throw_pEp_Exception(env, status);
@ -70,11 +70,9 @@ JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter_Engine__1trustwords(
return from_string(env, words);
}
JNIEXPORT jobject JNICALL Java_foundation_pEp_jniadapter_Engine__1myself(
JNIEnv *env,
JNIEXPORT jobject JNICALL Java_foundation_pEp_jniadapter_Engine__1myself(JNIEnv *env,
jobject obj,
jobject ident
)
jobject ident)
{
std::mutex *mutex_local = nullptr;
{
@ -96,11 +94,9 @@ JNIEXPORT jobject JNICALL Java_foundation_pEp_jniadapter_Engine__1myself(
return from_identity(env, _ident);
}
JNIEXPORT jobject JNICALL Java_foundation_pEp_jniadapter_Engine__1updateIdentity(
JNIEnv *env,
JNIEXPORT jobject JNICALL Java_foundation_pEp_jniadapter_Engine__1updateIdentity(JNIEnv *env,
jobject obj,
jobject ident
)
jobject ident)
{
std::mutex *mutex_local = nullptr;
{
@ -111,18 +107,15 @@ JNIEXPORT jobject JNICALL Java_foundation_pEp_jniadapter_Engine__1updateIdentity
std::lock_guard<std::mutex> l(*mutex_local);
pEp_identity *_ident = to_identity(env, ident);
passphraseWrap(::update_identity, session(), _ident);
return from_identity(env, _ident);
}
JNIEXPORT jobject JNICALL Java_foundation_pEp_jniadapter_Engine__1setOwnKey(
JNIEnv *env,
JNIEXPORT jobject JNICALL Java_foundation_pEp_jniadapter_Engine__1setOwnKey(JNIEnv *env,
jobject obj,
jobject ident,
jbyteArray fpr
)
jbyteArray fpr)
{
std::mutex *mutex_local = nullptr;
{
@ -146,11 +139,9 @@ JNIEXPORT jobject JNICALL Java_foundation_pEp_jniadapter_Engine__1setOwnKey(
return from_identity(env, _ident);
}
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1keyMistrusted(
JNIEnv *env,
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1keyMistrusted(JNIEnv *env,
jobject obj,
jobject ident
)
jobject ident)
{
std::mutex *mutex_local = nullptr;
{
@ -184,11 +175,9 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1keyMistrusted(
passphraseWrap(::key_mistrusted, session(), _ident);
}
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1keyResetTrust(
JNIEnv *env,
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1keyResetTrust(JNIEnv *env,
jobject obj,
jobject ident
)
jobject ident)
{
std::mutex *mutex_local = nullptr;
{
@ -203,10 +192,11 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1keyResetTrust(
PEP_STATUS status = PEP_STATUS_OK;
if (_ident->fpr == NULL || _ident->fpr[0] == 0) {
if (_ident->me)
if (_ident->me) {
status = passphraseWrap(::myself, session(), _ident);
else
} else {
status = passphraseWrap(::update_identity, session(), _ident);
}
}
if (status != PEP_STATUS_OK) {
@ -222,11 +212,9 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1keyResetTrust(
passphraseWrap(::key_reset_trust, session(), _ident);
}
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1trustPersonalKey(
JNIEnv *env,
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1trustPersonalKey(JNIEnv *env,
jobject obj,
jobject ident
)
jobject ident)
{
std::mutex *mutex_local = nullptr;
{
@ -241,10 +229,11 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1trustPersonalKey(
PEP_STATUS status = PEP_STATUS_OK;
if (_ident->fpr == NULL || _ident->fpr[0] == 0) {
if (_ident->me)
if (_ident->me) {
status = passphraseWrap(::myself, session(), _ident);
else
} else {
status = passphraseWrap(::update_identity, session(), _ident);
}
}
if (status != PEP_STATUS_OK) {
@ -260,11 +249,9 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1trustPersonalKey(
passphraseWrap(::trust_personal_key, session(), _ident);
}
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1trustOwnKey(
JNIEnv *env,
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1trustOwnKey(JNIEnv *env,
jobject obj,
jobject ident
)
jobject ident)
{
std::mutex *mutex_local = nullptr;
{
@ -284,11 +271,9 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1trustOwnKey(
passphraseWrap(::trust_own_key, session(), _ident);
}
JNIEXPORT jobject JNICALL Java_foundation_pEp_jniadapter_Engine__1importKey(
JNIEnv *env,
JNIEXPORT jobject JNICALL Java_foundation_pEp_jniadapter_Engine__1importKey(JNIEnv *env,
jobject obj,
jbyteArray key
)
jbyteArray key)
{
std::mutex *mutex_local = nullptr;
{
@ -298,17 +283,17 @@ JNIEXPORT jobject JNICALL Java_foundation_pEp_jniadapter_Engine__1importKey(
}
std::lock_guard<std::mutex> l(*mutex_local);
size_t _size = (size_t) env->GetArrayLength(key);
const char *_key = (char *) env->GetByteArrayElements(key, NULL);
size_t _size = static_cast<size_t>(env->GetArrayLength(key));
jbyte* _key = env->GetByteArrayElements(key, NULL);
if(_key == NULL){
if(_key == NULL) {
throw_pEp_Exception(env, PEP_OUT_OF_MEMORY);
return NULL;
}
identity_list *_identities;
PEP_STATUS status = passphraseWrap(::import_key, session(), _key, _size, &_identities);
PEP_STATUS status = passphraseWrap(::import_key, session(), reinterpret_cast<const char*>(_key), _size, &_identities);
if (status != PEP_STATUS_OK && status != PEP_KEY_IMPORTED) {
throw_pEp_Exception(env, status);
return NULL;
@ -319,16 +304,14 @@ JNIEXPORT jobject JNICALL Java_foundation_pEp_jniadapter_Engine__1importKey(
identities_ = from_identitylist(env, _identities);
}
env->ReleaseByteArrayElements(key, (jbyte *) _key, JNI_ABORT);
env->ReleaseByteArrayElements(key, _key, JNI_ABORT);
return identities_;
}
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1config_1passive_1mode(
JNIEnv *env,
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1config_1passive_1mode(JNIEnv *env,
jobject obj,
jboolean enable
)
jboolean enable)
{
std::mutex *mutex_local = nullptr;
{
@ -338,15 +321,13 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1config_1passive_1
}
std::lock_guard<std::mutex> l(*mutex_local);
::config_passive_mode(session(), (bool)enable);
::config_passive_mode(session(), static_cast<bool>(enable));
}
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1config_1unencrypted_1subject(
JNIEnv *env,
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1config_1unencrypted_1subject(JNIEnv *env,
jobject obj,
jboolean enable
)
jboolean enable)
{
std::mutex *mutex_local = nullptr;
{
@ -356,11 +337,10 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1config_1unencrypt
}
std::lock_guard<std::mutex> l(*mutex_local);
::config_unencrypted_subject(session(), (bool)enable);
::config_unencrypted_subject(session(), static_cast<bool>(enable));
}
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1blacklist_1add(
JNIEnv *env,
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1blacklist_1add(JNIEnv *env,
jobject obj,
jbyteArray fpr
)
@ -385,14 +365,11 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1blacklist_1add(
throw_pEp_Exception(env, status);
return;
}
}
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1blacklist_1delete(
JNIEnv *env,
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1blacklist_1delete(JNIEnv *env,
jobject obj,
jbyteArray fpr
)
jbyteArray fpr)
{
std::mutex *mutex_local = nullptr;
{
@ -417,11 +394,9 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1blacklist_1delete
}
JNIEXPORT jboolean JNICALL Java_foundation_pEp_jniadapter_Engine__1blacklist_1is_1listed(
JNIEnv *env,
JNIEXPORT jboolean JNICALL Java_foundation_pEp_jniadapter_Engine__1blacklist_1is_1listed(JNIEnv *env,
jobject obj,
jbyteArray fpr
)
jbyteArray fpr)
{
std::mutex *mutex_local = nullptr;
{
@ -448,12 +423,10 @@ JNIEXPORT jboolean JNICALL Java_foundation_pEp_jniadapter_Engine__1blacklist_1is
return (jboolean)_listed;
}
JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter_Engine__1getCrashdumpLog(
JNIEnv *env,
JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter_Engine__1getCrashdumpLog(JNIEnv *env,
jobject obj,
jint dummy,
jint maxlines
)
jint maxlines)
{
std::mutex *mutex_local = nullptr;
{
@ -463,7 +436,7 @@ JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter_Engine__1getCrashdum
}
std::lock_guard<std::mutex> l(*mutex_local);
int _maxlines = (int) maxlines;
int _maxlines = static_cast<int>(maxlines);
char *_logdata;
PEP_STATUS status = passphraseWrap(::get_crashdump_log, session(), _maxlines, &_logdata);
@ -477,40 +450,24 @@ JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter_Engine__1getCrashdum
return from_string(env, _logdata);
}
JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter_Engine__1getUserDirectory(
JNIEnv *env,
jobject obj
)
JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter_Engine__1getUserDirectory(JNIEnv *env,
jobject obj)
{
pEpLog("called");
return from_string(env, ::per_user_directory());
}
JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter_Engine__1getMachineDirectory(
JNIEnv *env,
jobject obj
)
JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter_Engine__1getMachineDirectory(JNIEnv *env,
jobject obj)
{
pEpLog("called");
return from_string(env, ::per_machine_directory());
}
//void logPassphraseCache() {
// try {
//// while(true) {
// pEpLog("Cache: '" << cache.latest_passphrase() << "'");
//// }
// } catch(pEp::PassphraseCache::Empty e) {
// pEpLog(e.what());
// } catch(pEp::PassphraseCache::Exhausted ex) {
// pEpLog(ex.what());
// }
//}
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1config_1passphrase
(JNIEnv * env,
jobject obj,
jbyteArray passphrase)
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1config_1passphrase(JNIEnv * env,
jobject obj,
jbyteArray passphrase)
{
std::mutex *mutex_local = nullptr;
{
@ -530,12 +487,10 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1config_1passphras
}
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1config_1passphrase_1for_1new_1keys(
JNIEnv *env,
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1config_1passphrase_1for_1new_1keys(JNIEnv *env,
jobject obj,
jboolean enable,
jbyteArray passphrase
)
jbyteArray passphrase)
{
std::mutex *mutex_local = nullptr;
{
@ -545,7 +500,7 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1config_1passphras
}
std::lock_guard<std::mutex> l(*mutex_local);
bool _enable = (bool) enable;
bool _enable = static_cast<bool>(enable);
const char *_passphrase = to_string(env, passphrase);
PEP_STATUS status = ::config_passphrase_for_new_keys(session(),_enable,passphrase_cache.add_stored(_passphrase));
@ -555,8 +510,33 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine__1config_1passphras
throw_pEp_Exception(env, status);
return ;
}
}
JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter_Engine__1export_1key (JNIEnv *env,
jobject obj,
jbyteArray fpr)
{
std::mutex *mutex_local = nullptr;
{
std::lock_guard<std::mutex> l(global_mutex);
pEpLog("called with lock_guard");
mutex_local = get_engine_java_object_mutex(env, obj);
}
std::lock_guard<std::mutex> l(*mutex_local);
const char *_fpr = to_string(env, fpr);
char *buff = nullptr;
size_t size = 0;
PEP_STATUS status = passphraseWrap(::export_key, session(), _fpr, &buff, &size);
if (status != PEP_STATUS_OK) {
throw_pEp_Exception(env, status);
return NULL;
}
return from_string(env, buff);
}
} // extern "C"

207
src/foundation_pEp_jniadapter_AbstractEngine.cc → src/cxx/foundation_pEp_jniadapter_AbstractEngine.cc

@ -3,7 +3,6 @@
#include <pEp/keymanagement.h>
#include <pEp/message_api.h>
#include <pEp/sync_api.h>
#include <pEp/Adapter.hh>
#include <pEp/pEpLog.hh>
#include <pEp/passphrase_cache.hh>
#include <pEp/callback_dispatcher.hh>
@ -16,9 +15,7 @@ using namespace pEp::JNIAdapter;
using namespace utility; // for libpEpAdapter locked queue impl. TODO:rename
bool first = true;
JavaVM *jvm= nullptr;
std::mutex mutex_obj;
jfieldID signal_field_value = nullptr;
@ -43,12 +40,12 @@ jclass passphraseTypeClass = nullptr;
namespace JNISync {
JNIEnv* env() {
JNIEnv *thread_env = nullptr;
int status = jvm->GetEnv((void**)&thread_env, JNI_VERSION_1_6);
int status = jvm->GetEnv(reinterpret_cast<void**>(&thread_env), JNI_VERSION_1_6);
if (status < 0) {
#ifdef ANDROID
status = jvm->AttachCurrentThread(&thread_env, nullptr);
#else
status = jvm->AttachCurrentThread((void **) &thread_env, nullptr);
status = jvm->AttachCurrentThread(reinterpret_cast<void**>(&thread_env), nullptr);
#endif
}
assert(status >= 0);
@ -68,45 +65,60 @@ namespace JNISync {
void jni_init() {
JNIEnv *_env = JNISync::env();
messageClass = reinterpret_cast<jclass>(
_env->NewGlobalRef(findClass(_env, "foundation/pEp/jniadapter/Message")));
identityClass = reinterpret_cast<jclass>(
_env->NewGlobalRef(findClass(_env, "foundation/pEp/jniadapter/_Identity")));
signalClass = reinterpret_cast<jclass>(
_env->NewGlobalRef(findClass(_env, "foundation/pEp/jniadapter/SyncHandshakeSignal")));
passphraseTypeClass = reinterpret_cast<jclass>(
_env->NewGlobalRef(findClass(_env, "foundation/pEp/jniadapter/PassphraseType")));
engineClass = reinterpret_cast<jclass>(_env->NewGlobalRef(findClass(_env, "foundation/pEp/jniadapter/Engine")));
messageConstructorMethodID = _env->GetMethodID(messageClass, "<init>", "(J)V");
JNIEnv * _env = JNISync::env();
messageClass = static_cast<jclass>(_env->NewGlobalRef(findClass(_env, "foundation/pEp/jniadapter/Message")));
identityClass = static_cast<jclass>(_env->NewGlobalRef(findClass(_env, "foundation/pEp/jniadapter/_Identity")));
signalClass = static_cast<jclass>(_env->NewGlobalRef(findClass(_env, "foundation/pEp/jniadapter/SyncHandshakeSignal")));
passphraseTypeClass = static_cast<jclass>(_env->NewGlobalRef(findClass(_env, "foundation/pEp/jniadapter/PassphraseType")));
engineClass = static_cast<jclass>(_env->NewGlobalRef(findClass(_env, "foundation/pEp/jniadapter/Engine")));
messageConstructorMethodID = _env->GetMethodID(
messageClass,
"<init>",
"(J)V");
messageToSendMethodID = _env->GetMethodID(
engineClass,
"messageToSendCallFromC",
"(Lfoundation/pEp/jniadapter/Message;)I");
engineClass,
"messageToSendCallFromC",
"(Lfoundation/pEp/jniadapter/Message;)I");
needsFastPollMethodID = _env->GetMethodID(
engineClass,
"needsFastPollCallFromC",
"(Z)I");
engineClass,
"needsFastPollCallFromC",
"(Z)I");
notifyHandShakeMethodID = _env->GetMethodID(
engineClass,
"notifyHandshakeCallFromC",
"(Lfoundation/pEp/jniadapter/_Identity;Lfoundation/pEp/jniadapter/_Identity;Lfoundation/pEp/jniadapter/SyncHandshakeSignal;)I");
engineClass,
"notifyHandshakeCallFromC",
"(Lfoundation/pEp/jniadapter/_Identity;Lfoundation/pEp/jniadapter/_Identity;Lfoundation/pEp/jniadapter/SyncHandshakeSignal;)I");
passphraseRequiredMethodID = _env->GetMethodID(
engineClass,
"passphraseRequiredFromC",
"(Lfoundation/pEp/jniadapter/PassphraseType;)[B");
sync_handshake_signal_values = JNISync::env()->GetStaticMethodID(signalClass, "values",
"()[Lfoundation/pEp/jniadapter/SyncHandshakeSignal;");
passphrase_status_values = JNISync::env()->GetStaticMethodID(passphraseTypeClass, "values",
"()[Lfoundation/pEp/jniadapter/PassphraseType;");
signal_field_value = JNISync::env()->GetFieldID(signalClass, "value", "I");
passphrase_type_field_value = JNISync::env()->GetFieldID(passphraseTypeClass, "value", "I");
engineClass,
"passphraseRequiredFromC",
"(Lfoundation/pEp/jniadapter/PassphraseType;)[B");
sync_handshake_signal_values = JNISync::env()->GetStaticMethodID(
signalClass,
"values",
"()[Lfoundation/pEp/jniadapter/SyncHandshakeSignal;");
passphrase_status_values = JNISync::env()->GetStaticMethodID(
passphraseTypeClass,
"values",
"()[Lfoundation/pEp/jniadapter/PassphraseType;");
signal_field_value = JNISync::env()->GetFieldID(
signalClass,
"value",
"I");
passphrase_type_field_value = JNISync::env()->GetFieldID(passphraseTypeClass, "value", "I");
}
char* JNIAdapter::passphraseRequiredCallback(const PEP_STATUS status) {
char* JNIAdapter::passphraseRequiredCallback(
const PEP_STATUS status)
{
pEpLog("called");
jobject status_ = nullptr;
{
@ -114,8 +126,7 @@ char* JNIAdapter::passphraseRequiredCallback(const PEP_STATUS status) {
assert(passphrase_status_values);
assert(passphrase_type_field_value);
jobjectArray values = (jobjectArray) JNISync::env()->CallStaticObjectMethod(passphraseTypeClass,
passphrase_status_values);
jobjectArray values = static_cast<jobjectArray>(JNISync::env()->CallStaticObjectMethod(passphraseTypeClass, passphrase_status_values));
if (JNISync::env()->ExceptionCheck()) {
JNISync::env()->ExceptionClear();
@ -127,7 +138,7 @@ char* JNIAdapter::passphraseRequiredCallback(const PEP_STATUS status) {
jobject element = JNISync::env()->GetObjectArrayElement(values, i);
assert(element);
jint value = JNISync::env()->GetIntField(element, passphrase_type_field_value);
if (value == (jint) status) {
if (value == static_cast<jint>(status)) {
status_ = element;
break;
}
@ -142,7 +153,7 @@ char* JNIAdapter::passphraseRequiredCallback(const PEP_STATUS status) {
JNISync::env()->ExceptionClear();
}
jbyteArray ppJBA = reinterpret_cast<jbyteArray>(ppJO);
jbyteArray ppJBA = static_cast<jbyteArray>(ppJO);
char* passphrase_ = to_string( JNISync::env(), ppJBA);
return passphrase_;
@ -150,24 +161,26 @@ char* JNIAdapter::passphraseRequiredCallback(const PEP_STATUS status) {
PEP_STATUS messageToSend(message *msg)
{
std::lock_guard<std::mutex> l(mutex_obj);
std::lock_guard <std::mutex> l(mutex_obj);
pEpLog("called");
// Passphrase
// When a protocol implementation of the p≡p engine using messageToSend() cannot sign or encrypt with an
// empty passphrase and not with the configured passphrase it is calling messageToSend() with a NULL instead
// of a struct _message object.
if (Adapter::on_sync_thread() && !msg)
if (Adapter::on_sync_thread() && !msg) {
return pEp::PassphraseCache::config_next_passphrase();
}
// reset passphrase iterator
if (Adapter::on_sync_thread())
if (Adapter::on_sync_thread()) {
pEp::PassphraseCache::config_next_passphrase(true);
}
jobject msg_ = nullptr;
assert(messageClass && messageConstructorMethodID && objj && messageToSendMethodID);
msg_ = JNISync::env()->NewObject(messageClass, messageConstructorMethodID, (jlong) msg);
msg_ = JNISync::env()->NewObject(messageClass, messageConstructorMethodID, reinterpret_cast<jlong>(msg));
PEP_STATUS status = (PEP_STATUS) JNISync::env()->CallIntMethod(objj, messageToSendMethodID, msg_);
if (JNISync::env()->ExceptionCheck()) {
@ -176,11 +189,12 @@ PEP_STATUS messageToSend(message *msg)
JNISync::env()->ExceptionClear();
}
return status;
}
PEP_STATUS notifyHandshake(pEp_identity *me, pEp_identity *partner, sync_handshake_signal signal)
PEP_STATUS notifyHandshake(pEp_identity *me,
pEp_identity *partner,
sync_handshake_signal signal)
{
std::lock_guard<std::mutex> l(mutex_obj);
pEpLog("called");
@ -197,8 +211,7 @@ PEP_STATUS notifyHandshake(pEp_identity *me, pEp_identity *partner, sync_handsha
assert(sync_handshake_signal_values);
assert(signal_field_value);
jobjectArray values = (jobjectArray) JNISync::env()->CallStaticObjectMethod(signalClass,
sync_handshake_signal_values);
jobjectArray values = static_cast<jobjectArray>(JNISync::env()->CallStaticObjectMethod(signalClass, sync_handshake_signal_values));
if (JNISync::env()->ExceptionCheck()) {
JNISync::env()->ExceptionClear();
return PEP_UNKNOWN_ERROR;
@ -209,7 +222,7 @@ PEP_STATUS notifyHandshake(pEp_identity *me, pEp_identity *partner, sync_handsha
jobject element = JNISync::env()->GetObjectArrayElement(values, i);
assert(element);
jint value = JNISync::env()->GetIntField(element, signal_field_value);
if (value == (jint) signal) {
if (value == static_cast<jint>(signal)) {
signal_ = element;
break;
}
@ -232,10 +245,8 @@ PEP_STATUS notifyHandshake(pEp_identity *me, pEp_identity *partner, sync_handsha
extern "C" {
using namespace pEp;
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_init(
JNIEnv *env,
jobject obj
)
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_init(JNIEnv *env,
jobject obj)
{
std::lock_guard<std::mutex> l(global_mutex); // global mutex for write access to <unordered_map>
pEpLog("called");
@ -254,10 +265,8 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_init(
Adapter::session();
}
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_release(
JNIEnv *env,
jobject obj
)
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_release(JNIEnv *env,
jobject obj)
{
std::lock_guard<std::mutex> l(global_mutex); // global mutex for write access to <unordered_map>
pEpLog("called");
@ -281,10 +290,8 @@ JNIEXPORT jboolean JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_getDebu
return static_cast<jboolean>(Adapter::pEpLog::get_enabled());
}
JNIEXPORT jstring JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_getVersion(
JNIEnv *env,
jobject obj
)
JNIEXPORT jstring JNICALL Java_foundation_pEp_jniadapter_AbstractEngine__1getVersion(JNIEnv *env,
jobject obj)
{
std::mutex *mutex_local = nullptr;
{
@ -297,10 +304,8 @@ JNIEXPORT jstring JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_getVersi
return env->NewStringUTF(::get_engine_version());
}
JNIEXPORT jstring JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_getProtocolVersion(
JNIEnv *env,
jobject obj
)
JNIEXPORT jstring JNICALL Java_foundation_pEp_jniadapter_AbstractEngine__1getProtocolVersion(JNIEnv *env,
jobject obj)
{
std::mutex *mutex_local = nullptr;
{
@ -313,9 +318,10 @@ JNIEXPORT jstring JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_getProto
return env->NewStringUTF(::get_protocol_version());
}
int examine_identity(pEp_identity *ident, void *arg)
int examine_identity(pEp_identity *ident,
void *arg)
{
locked_queue< pEp_identity * > *queue = (locked_queue< pEp_identity * > *) arg;
locked_queue < pEp_identity * > *queue = static_cast<locked_queue < pEp_identity * > * > (arg);
queue->push_back(identity_dup(ident));
return 0;
}
@ -323,10 +329,11 @@ int examine_identity(pEp_identity *ident, void *arg)
pEp_identity *retrieve_next_identity(void *arg)
{
pEpLog("called");
locked_queue< pEp_identity * > *queue = (locked_queue< pEp_identity * > *) arg;
locked_queue < pEp_identity * > *queue = static_cast<locked_queue < pEp_identity * > * > (arg);
while (!queue->size())
while (!queue->size()) {
usleep(100000);
}
pEp_identity *ident = queue->front();
queue->pop_front();
@ -336,7 +343,7 @@ pEp_identity *retrieve_next_identity(void *arg)
static void *keyserver_thread_routine(void *arg)
{
PEP_STATUS status = do_keymanagement(retrieve_next_identity, arg);
locked_queue< pEp_identity * > *queue = (locked_queue< pEp_identity * > *) arg;
locked_queue < pEp_identity * > *queue = static_cast<locked_queue < pEp_identity * > * > (arg);
while (queue->size()) {
pEp_identity *ident = queue->front();
@ -345,13 +352,11 @@ static void *keyserver_thread_routine(void *arg)
}
delete queue;
return (void *) status;
return reinterpret_cast<void *>(status);
}
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_startKeyserverLookup(
JNIEnv *env,
jobject obj
)
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine__1startKeyserverLookup(JNIEnv *env,
jobject obj)
{
std::mutex *mutex_local = nullptr;
{
@ -376,26 +381,24 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_startKeyser
return;
}
thread = (pthread_t *) env->GetLongField(obj, thread_handle);
thread = reinterpret_cast<pthread_t*>(env->GetLongField(obj, thread_handle));
if (thread)
return;
thread = (pthread_t *) calloc(1, sizeof(pthread_t));
thread = static_cast<pthread_t*>(calloc(1, sizeof(pthread_t)));
assert(thread);
env->SetLongField(obj, thread_handle, (jlong) thread);
env->SetLongField(obj, thread_handle, reinterpret_cast<jlong>(thread));
queue = new locked_queue< pEp_identity * >();
env->SetLongField(obj, queue_handle, (jlong) queue);
env->SetLongField(obj, queue_handle, reinterpret_cast<jlong>(queue));
register_examine_function(Adapter::session(), examine_identity, (void *) queue);
register_examine_function(Adapter::session(), examine_identity,static_cast<void*>(queue));
pthread_create(thread, nullptr, keyserver_thread_routine, (void *) queue);
pthread_create(thread, nullptr, keyserver_thread_routine, static_cast<void*>(queue));
}
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_stopKeyserverLookup(
JNIEnv *env,
jobject obj
)
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine__1stopKeyserverLookup(JNIEnv *env,
jobject obj)
{
std::mutex *mutex_local = nullptr;
{
@ -420,14 +423,14 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_stopKeyserv
return;
}
thread = (pthread_t *) env->GetLongField(obj, thread_handle);
thread = reinterpret_cast<pthread_t*>(env->GetLongField(obj, thread_handle));
if (!thread)
return;
queue = (locked_queue< pEp_identity * > *) env->GetLongField(obj, queue_handle);
queue = reinterpret_cast<locked_queue<pEp_identity*>*>(env->GetLongField(obj, queue_handle));
env->SetLongField(obj, queue_handle, (jlong) 0);
env->SetLongField(obj, thread_handle, (jlong) 0);
env->SetLongField(obj, queue_handle, 0);
env->SetLongField(obj, thread_handle, 0);
register_examine_function(Adapter::session(), nullptr, nullptr);
@ -436,10 +439,8 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_stopKeyserv
free(thread);
}
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_startSync(
JNIEnv *env,
jobject obj
)
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine__1startSync(JNIEnv *env,
jobject obj)
{
std::mutex *mutex_local = nullptr;
{
@ -451,17 +452,14 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_startSync(
try {
CallbackDispatcher::start_sync();
// Adapter::startup<JNISync>(messageToSend, notifyHandshake, &o, &JNISync::onSyncStartup, &JNISync::onSyncShutdown);
} catch (RuntimeError& ex) {
throw_pEp_Exception(env, ex.status);
return;
}
}
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_stopSync(
JNIEnv *env,
jobject obj
)
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine__1stopSync(JNIEnv *env,
jobject obj)
{
std::mutex *mutex_local = nullptr;
{
@ -472,13 +470,10 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_stopSync(
std::lock_guard<std::mutex> l(*mutex_local);
CallbackDispatcher::stop_sync();
// Adapter::shutdown();
}
JNIEXPORT jboolean JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_isSyncRunning(
JNIEnv *env,
jobject obj
)
JNIEXPORT jboolean JNICALL Java_foundation_pEp_jniadapter_AbstractEngine__1isSyncRunning(JNIEnv *env,
jobject obj)
{
std::mutex *mutex_local = nullptr;
{
@ -488,7 +483,7 @@ JNIEXPORT jboolean JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_isSyncR
}
std::lock_guard<std::mutex> l(*mutex_local);
return (jboolean) Adapter::is_sync_running();
return static_cast<jboolean>(Adapter::is_sync_running());
}
} // extern "C"

49
src/foundation_pEp_jniadapter__Blob.cc → src/cxx/foundation_pEp_jniadapter__Blob.cc

@ -8,39 +8,43 @@
#include "foundation_pEp_jniadapter__Blob.h"
namespace pEp {
namespace JNIAdapter {
static ::bloblist_t *bloblist_ptr(JNIEnv *env, jobject me) {
jfieldID handle;
namespace JNIAdapter {
try {
handle = getFieldID(env, "foundation/pEp/jniadapter/Blob", "mime_type", "Ljava/lang/String");
}
catch (std::exception& ex) {
assert(0);
return NULL;
}
static ::bloblist_t *bloblist_ptr(JNIEnv *env, jobject me) {
jfieldID handle;
return (::bloblist_t *) (intptr_t) (int64_t) env->GetLongField(me, handle);
}
};
};
try {
handle = getFieldID(env, "foundation/pEp/jniadapter/Blob", "mime_type", "Ljava/lang/String");
} catch (std::exception &ex) {
assert(0);
return NULL;
}
return reinterpret_cast<::bloblist_t *>(env->GetLongField(me, handle));
}
}; //namespace JNIAdapter
}; //namespace pEp
extern "C" {
using namespace std;
using namespace pEp::JNIAdapter;
JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter__1Blob__1dataToXER(JNIEnv *env, jobject obj)
JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter__1Blob__1dataToXER(JNIEnv *env,
jobject obj)
{
pEpLog("called");
bloblist_t *b = to_blob(env, obj);
char *out = nullptr;
// RFC 1049 / RFC 2045 : The type, subtype, and parameter names are not case sensitive.
if(strcasecmp(b->mime_type, "application/pEp.sync") == 0) {
PEP_STATUS status = ::PER_to_XER_Sync_msg(b->value, (size_t) b->size, &out);
if (status)
if (strcasecmp(b->mime_type, "application/pEp.sync") == 0) {
PEP_STATUS status = ::PER_to_XER_Sync_msg(b->value, static_cast<size_t>(b->size), &out);
if (status) {
throw_pEp_Exception(env, status);
}
jbyteArray result = from_string(env, out);
free(out);
@ -48,17 +52,18 @@ JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter__1Blob__1dataToXER(J
}
// RFC 1049 / RFC 2045 : The type, subtype, and parameter names are not case sensitive.
if(strcasecmp(b->mime_type, "application/pEp.keyreset") == 0) {
PEP_STATUS status = ::PER_to_XER_Distribution_msg(b->value, (size_t) b->size, &out);
if (status)
if (strcasecmp(b->mime_type, "application/pEp.keyreset") == 0) {
PEP_STATUS status = ::PER_to_XER_Distribution_msg(b->value, static_cast<size_t>(b->size), &out);
if (status) {
throw_pEp_Exception(env, status);
}
jbyteArray result = from_string(env, out);
free(out);
return result;
}
return from_string(env,b->value);
return from_string(env, b->value);
}
}; // extern "C"

0
src/get_header.cc → src/cxx/get_header.cc

8
src/identity_api.cc → src/cxx/identity_api.cc

@ -3,13 +3,15 @@
#include "jniutils.hh"
extern "C" {
JNIEXPORT jint JNICALL Java_foundation_pEp_jniadapter_Identity__1getRating(JNIEnv *env, jobject thiz, jint comm_type)
JNIEXPORT jint JNICALL Java_foundation_pEp_jniadapter_Identity__1getRating(
JNIEnv *env,
jobject thiz,
jint comm_type)
{
pEpLog("called");
return ::rating_from_comm_type((PEP_comm_type) comm_type);
return ::rating_from_comm_type(static_cast<PEP_comm_type>(comm_type));
}
} // extern "C"

795
src/cxx/jniutils.cc

@ -0,0 +1,795 @@
#include <cassert>
#include "jniutils.hh"
#include <pEp/pEpLog.hh>
#ifndef __LP64__
#include <time64.h>
#define time_t time64_t
#define timegm timegm64
#define gmtime_r gmtime64_r
#else
#include <string.h>
#endif
namespace pEp {
namespace JNIAdapter {
std::mutex global_mutex;
std::unordered_map<long, std::mutex *> engine_objid_mutex;
std::mutex *get_engine_java_object_mutex(JNIEnv *env,
jobject obj)
{
long engine_obj_id = static_cast<long>(callLongMethod(env, obj, "getId"));
assert(engine_obj_id);
pEpLog("for java object id: " << engine_obj_id);
std::mutex *engine_obj_mutex = engine_objid_mutex.at(engine_obj_id);
pEpLog("found mutex: " << engine_obj_mutex << " with native_handle: " << engine_obj_mutex->native_handle());
assert(engine_obj_mutex);
return engine_obj_mutex;
}
void create_engine_java_object_mutex(JNIEnv *env,
jobject obj)
{
long engine_obj_id = static_cast<long>(callLongMethod(env, obj, "getId"));
assert(engine_obj_id);
std::mutex *engine_obj_mutex = new std::mutex();
pEpLog(engine_obj_mutex << " with native_handle: " << engine_obj_mutex->native_handle() << " for java object id: " << engine_obj_id);
assert(engine_obj_mutex);
if (engine_objid_mutex.count(engine_obj_id) > 0) {
pEpLog("Fatal: mutex already existing for object id: " << engine_obj_id);
assert(0);
}
engine_objid_mutex.insert(std::make_pair(engine_obj_id, engine_obj_mutex));
}
void release_engine_java_object_mutex(JNIEnv *env,
jobject obj)
{
long engine_obj_id = static_cast<long>(callLongMethod(env, obj, "getId"));
assert(engine_obj_id);
std::mutex *engine_obj_mutex = engine_objid_mutex.at(engine_obj_id);
pEpLog(engine_obj_mutex << " with native_handle: " << engine_obj_mutex->native_handle() << " for java object id: " << engine_obj_id);
assert(engine_obj_mutex);
engine_objid_mutex.erase(engine_obj_id);
delete engine_obj_mutex;
}
jclass findClass(JNIEnv *env,
const char *classname)
{
jclass clazz = env->FindClass(classname);
if (!clazz) {
fprintf(stderr, "class not found: %s\n", classname);
}
assert(clazz);
if (clazz == NULL) {
jclass ex = env->FindClass("java/lang/NoClassDefFoundError");
assert(ex);
env->ThrowNew(ex, classname);
throw std::bad_cast();
}
return clazz;
}
jfieldID getFieldID(JNIEnv *env,
const char *classname,
const char *fieldname,
const char *signature)
{
jclass clazz = findClass(env, classname);
assert(clazz);
jfieldID field = env->GetFieldID(clazz, fieldname, signature);
assert(field);
if (field == NULL) {
jclass ex = env->FindClass("java/lang/NoSuchFieldError");
assert(ex);
env->ThrowNew(ex, fieldname);
throw std::invalid_argument(std::string(fieldname));
}
env->DeleteLocalRef(clazz);
return field;
}
//TODO: fix/generalize/clean patch added to make keysync work using globalref to class
jfieldID getFieldID(JNIEnv *env,
const char *classname,
const char *fieldname,
const char *signature,
const jclass clazz)
{
jfieldID field = env->GetFieldID(clazz, fieldname, signature);
assert(field);
if (field == NULL) {
jclass ex = env->FindClass("java/lang/NoSuchFieldError");
assert(ex);
env->ThrowNew(ex, fieldname);
throw std::invalid_argument(std::string(fieldname));
}
return field;
}
jint callIntMethod(JNIEnv *env,
jobject obj,
const char *methodname)
{
jclass clazz = env->GetObjectClass(obj);
assert(clazz);
jmethodID method = env->GetMethodID(clazz, methodname, "()I");
if (method == NULL) {
jclass ex = env->FindClass("java/lang/NoSuchMethodError");
assert(ex);
env->ThrowNew(ex, methodname);
throw std::invalid_argument(std::string(methodname));
}
env->DeleteLocalRef(clazz);
jint result = env->CallIntMethod(obj, method);
env->ExceptionCheck(); // handle exception in Java
return result;
}
jlong callLongMethod(JNIEnv *env,
jobject obj,
const char *methodname)
{
jclass clazz = env->GetObjectClass(obj);
assert(clazz);
jmethodID method = env->GetMethodID(clazz, methodname, "()J");
if (method == NULL) {
jclass ex = env->FindClass("java/lang/NoSuchMethodError");
assert(ex);
env->ThrowNew(ex, methodname);
throw std::invalid_argument(std::string(methodname));
}
env->DeleteLocalRef(clazz);
jlong result = env->CallLongMethod(obj, method);
env->ExceptionCheck(); // handle exception in Java
return result;
}
jobject callObjectMethod(JNIEnv *env,
jobject obj,
const char *methodname,
jint index)
{
jclass clazz = env->GetObjectClass(obj);
assert(clazz);
jmethodID method = env->GetMethodID(clazz, methodname, "(I)Ljava/lang/Object;");
if (method == NULL) {
jclass ex = env->FindClass("java/lang/NoSuchMethodError");
assert(ex);
env->ThrowNew(ex, methodname);
throw std::invalid_argument(std::string(methodname));
}
env->DeleteLocalRef(clazz);
jobject result = env->CallObjectMethod(obj, method, index);
env->ExceptionCheck(); // handle exception in Java
return result;
}
jboolean callBooleanMethod(JNIEnv *env,
jobject obj,
const char *methodname,
jobject o)
{
jclass clazz = env->GetObjectClass(obj);
assert(clazz);
jmethodID method = env->GetMethodID(clazz, methodname, "(Ljava/lang/Object;)Z");
if (method == NULL) {
jclass ex = env->FindClass("java/lang/NoSuchMethodError");
assert(ex);
env->ThrowNew(ex, methodname);
throw std::invalid_argument(std::string(methodname));
}
env->DeleteLocalRef(clazz);
jboolean result = env->CallBooleanMethod(obj, method, o);
env->ExceptionCheck(); // handle exception in Java
return result;
}
jint outOfMemory(JNIEnv *env)
{
jclass ex;
const char *ex_name = "java/lang/OutOfMemoryError";
ex = env->FindClass(ex_name);
assert(ex);
return env->ThrowNew(ex, ex_name);
}
jobject from_Integer(JNIEnv *env,
int val)
{
assert(env);
jclass clazz = findClass(env, "java/lang/Integer");
jmethodID constructor = env->GetMethodID(clazz, "<init>", "(I)V");
assert(constructor);
jobject obj = env->NewObject(clazz, constructor, val);
assert(obj);
return obj;
}
int to_Integer(JNIEnv *env,
jobject obj)
{
assert(env && obj);
int _val = callIntMethod(env, obj, "intValue");
return _val;
}
jbyteArray from_string(JNIEnv *env,
const char *str)
{
if (str && str[0]) {
jboolean isCopy;
size_t l = strlen(str);
jbyteArray _str = env->NewByteArray(l);
env->SetByteArrayRegion(_str, 0, l, (jbyte *) str);
return _str;
} else if (str) {
return env->NewByteArray(0);
} else {
return (jbyteArray) NULL;
}
}
char *to_string(JNIEnv *env,
jbyteArray str)
{
if (str == NULL) {
return NULL;
}
size_t l = env->GetArrayLength(str);
char *_str = static_cast<char *>(calloc(1, l + 1));
assert(_str);
env->GetByteArrayRegion(str, 0, l, (jbyte *) _str);
return _str;
}
jobject from_stringlist(JNIEnv *env,
stringlist_t *sl)
{
if (!sl) {
return (jobject) NULL;
}
jclass clazz = findClass(env, "java/util/Vector");
jmethodID constructor = env->GetMethodID(clazz, "<init>", "()V");
assert(constructor);
jobject obj = env->NewObject(clazz, constructor);
assert(obj);
stringlist_t *_sl;
for (_sl = sl; _sl && _sl->value; _sl = _sl->next) {
jobject o = from_string(env, _sl->value);
callBooleanMethod(env, obj, "add", o);
}
env->DeleteLocalRef(clazz);
return obj;
}
stringlist_t *to_stringlist(JNIEnv *env,
jobject obj)
{
if (!obj) {
return NULL;
}
jint size = callIntMethod(env, obj, "size");
if (size == 0) {
return NULL;
}
stringlist_t *sl = new_stringlist(NULL);
stringlist_t *_sl;
jint i;
for (_sl = sl, i = 0; i < (int) size; i++) {
jobject o = callObjectMethod(env, obj, "get", i);
jbyteArray a = static_cast<jbyteArray>(o);
char *str = to_string(env, a);
_sl = stringlist_add(_sl, str);
env->DeleteLocalRef(o);
free(str);
}
return sl;
}
jobject from_stringpairlist(JNIEnv *env,
stringpair_list_t *sl)
{
if (!sl) {
return (jobject) NULL;
}
jclass clazz = findClass(env, "java/util/ArrayList");
jclass clazz_pair = findClass(env, "foundation/pEp/jniadapter/Pair");
jmethodID constructor = env->GetMethodID(clazz, "<init>", "()V");
assert(constructor);
jmethodID constructor_pair = env->GetMethodID(clazz_pair, "<init>", "(Ljava/lang/Object;Ljava/lang/Object;)V");
assert(constructor_pair);
jobject obj = env->NewObject(clazz, constructor);
assert(obj);
stringpair_list_t *_sl;
for (_sl = sl; _sl && _sl->value; _sl = _sl->next) {
assert(_sl->value->key);
assert(_sl->value->value);
jbyteArray first = from_string(env, _sl->value->key);
jbyteArray second = from_string(env, _sl->value->value);
jobject pair = env->NewObject(clazz_pair, constructor_pair, first, second);
callBooleanMethod(env, obj, "add", pair);
env->DeleteLocalRef(first);
env->DeleteLocalRef(second);
env->DeleteLocalRef(pair);
}
env->DeleteLocalRef(clazz);
env->DeleteLocalRef(clazz_pair);
return obj;
}
stringpair_list_t *to_stringpairlist(JNIEnv *env,
jobject obj)
{
if (!obj) {
return NULL;
}
jint size = callIntMethod(env, obj, "size");
if (size == 0) {
return NULL;
}
jfieldID first_id = getFieldID(env, "foundation/pEp/jniadapter/Pair", "first", "Ljava/lang/Object;");
jfieldID second_id = getFieldID(env, "foundation/pEp/jniadapter/Pair", "second", "Ljava/lang/Object;");
stringpair_list_t *sl = new_stringpair_list(NULL);
stringpair_list_t *_sl;
jint i;
for (_sl = sl, i = 0; i < (int) size; i++) {
jobject pair = callObjectMethod(env, obj, "get", i);
jbyteArray first = static_cast<jbyteArray>(env->GetObjectField(pair, first_id));
jbyteArray second = static_cast<jbyteArray>(env->GetObjectField(pair, second_id));
char *first_str = to_string(env, first);
char *second_str = to_string(env, second);
stringpair_t *sp = new_stringpair(first_str, second_str);
env->DeleteLocalRef(pair);
free(first_str);
free(second_str);
_sl = stringpair_list_add(_sl, sp);
}
return sl;
}
jobject from_timestamp(JNIEnv *env,
timestamp *ts)
{
if (!ts) {
return NULL;
}
//LOGD("/* Seconds (0-60) */ FROM :%d", ts->tm_sec);
//LOGD("/* Minutes (0-59) */ :%d", ts->tm_min);
//LOGD("/* Hours (0-23) */ :%d", ts->tm_hour);
//LOGD("/* Day of the month (1-31) */:%d", ts->tm_mday);
//LOGD("/* Month (0-11) */ :%d", ts->tm_mon);
//LOGD("/* Year - 1900 */ :%d", ts->tm_year);
time_t t = timegm(ts) * 1000;
//LOGD( "TimeGM returns : %lld", t);
jclass clazz = findClass(env, "java/util/Date");
jmethodID constructor = env->GetMethodID(clazz, "<init>", "(J)V");
assert(constructor);
jobject result = env->NewObject(clazz, constructor, (jlong) t);
env->DeleteLocalRef(clazz);
return result;
}
timestamp *to_timestamp(JNIEnv *env,
jobject date)
{
if (!date) {
return NULL;
}
jlong t = callLongMethod(env, date, "getTime");
//LOGD( "Set Time to : %lld", t);
timestamp *ts = static_cast<timestamp *>(calloc(1, sizeof(timestamp)));
assert(ts);
if (ts == NULL) {
return NULL;
}
if (t) {
time_t clock = t / 1000;
gmtime_r(&clock, ts);
//LOGD("/* Seconds (0-60) */ TO :%d", ts->tm_sec);
//LOGD("/* Minutes (0-59) */ :%d", ts->tm_min);
//LOGD("/* Hours (0-23) */ :%d", ts->tm_hour);
//LOGD("/* Day of the month (1-31) */:%d", ts->tm_mday);
//LOGD("/* Month (0-11) */ :%d", ts->tm_mon);
//LOGD("/* Year - 1900 */ :%d", ts->tm_year);
}
return ts;
}
static void _setStringField(JNIEnv *env,
const char *classname,
jobject obj,
const char *name,
const char *value)
{
if (value) {
jfieldID fieldID = getFieldID(env, classname, name, "[B");
env->SetObjectField(obj, fieldID, static_cast<jobject>(from_string(env, value)));
}
}
//TODO: fix/generalize/clean patch added to make keysync work using globalref to class
static void _setStringField(JNIEnv *env,
const char *classname,
jobject obj,
const char *name,
const char *value,
const jclass clazz)
{
if (value) {
jfieldID fieldID = getFieldID(env, classname, name, "[B", clazz);
env->SetObjectField(obj, fieldID, static_cast<jobject>(from_string(env, value)));
}
}
jobject from_identity(JNIEnv *env,
pEp_identity *ident)
{
if (!ident) {
return (jobject) NULL;
}
static const char *classname = "foundation/pEp/jniadapter/_Identity";
jclass clazz = findClass(env, classname);
jmethodID constructor = env->GetMethodID(clazz, "<init>", "()V");
assert(constructor);
jobject obj = env->NewObject(clazz, constructor);
env->DeleteLocalRef(clazz);
if (ident) {
_setStringField(env, classname, obj, "address", ident->address);
_setStringField(env, classname, obj, "fpr", ident->fpr);
_setStringField(env, classname, obj, "user_id", ident->user_id);
_setStringField(env, classname, obj, "username", ident->username);
jfieldID comm_type_id = getFieldID(env, classname, "comm_type", "I");
env->SetIntField(obj, comm_type_id, static_cast<jint>(ident->comm_type));
_setStringField(env, classname, obj, "lang", ident->lang);
jfieldID me_id = getFieldID(env, classname, "me", "Z");
env->SetBooleanField(obj, me_id, static_cast<jboolean>(ident->me));
jfieldID flags_id = getFieldID(env, classname, "flags", "I");
env->SetIntField(obj, flags_id, static_cast<jint>(ident->flags));
}
return obj;
}
//TODO: fix/generalize/clean patch added to make keysync work using globalref to class
jobject from_identity(JNIEnv *env,
pEp_identity *ident,
jclass identityClass)
{
if (!ident) {
return (jobject) NULL;
}
static const char *classname = "foundation/pEp/jniadapter/_Identity";
jmethodID constructor = env->GetMethodID(identityClass, "<init>", "()V");
assert(constructor);
jobject obj = env->NewObject(identityClass, constructor);
if (ident) {
_setStringField(env, classname, obj, "address", ident->address, identityClass);
_setStringField(env, classname, obj, "fpr", ident->fpr, identityClass);
_setStringField(env, classname, obj, "user_id", ident->user_id, identityClass);
_setStringField(env, classname, obj, "username", ident->username, identityClass);
jfieldID comm_type_id = getFieldID(env, classname, "comm_type", "I", identityClass);
env->SetIntField(obj, comm_type_id, static_cast<jint>(ident->comm_type));
_setStringField(env, classname, obj, "lang", ident->lang, identityClass);
jfieldID me_id = getFieldID(env, classname, "me", "Z", identityClass);
env->SetBooleanField(obj, me_id, static_cast<jboolean>(ident->me));
jfieldID flags_id = getFieldID(env, classname, "flags", "I", identityClass);
env->SetIntField(obj, flags_id, static_cast<jint>(ident->flags));
}
return obj;
}
char *_getStringField(JNIEnv *env,
const char *classname,
jobject obj,
const char *name)
{
jfieldID fieldID = getFieldID(env, classname, name, "[B");
jobject fobj = env->GetObjectField(obj, fieldID);
char *res = to_string(env, static_cast<jbyteArray>(fobj));
env->DeleteLocalRef(fobj);
return res;
}
pEp_identity *to_identity(JNIEnv *env,
jobject obj)
{
if (!obj) {
return NULL;
}
static const char *classname = "foundation/pEp/jniadapter/_Identity";
pEp_identity *ident = new_identity(NULL, NULL, NULL, NULL);
ident->address = _getStringField(env, classname, obj, "address");
ident->fpr = _getStringField(env, classname, obj, "fpr");
ident->user_id = _getStringField(env, classname, obj, "user_id");
ident->username = _getStringField(env, classname, obj, "username");
jfieldID comm_type_id = getFieldID(env, classname, "comm_type", "I");
ident->comm_type = static_cast<PEP_comm_type>(env->GetIntField(obj, comm_type_id));
char *lang = _getStringField(env, classname, obj, "lang");
if (lang && lang[0]) {
ident->lang[0] = lang[0];
ident->lang[1] = lang[1];
}
free(lang);
jfieldID me_id = getFieldID(env, classname, "me", "Z");
ident->me = static_cast<bool>(env->GetBooleanField(obj, me_id));
jfieldID flags_id = getFieldID(env, classname, "flags", "I");
ident->flags = static_cast<identity_flags_t>(env->GetIntField(obj, flags_id));
return ident;
}
jobject from_identitylist(JNIEnv *env,
identity_list *il)
{
if (!il) {
return (jobject) NULL;
}
jclass clazz = findClass(env, "java/util/Vector");
jmethodID constructor = env->GetMethodID(clazz, "<init>", "()V");
assert(constructor);
jobject obj = env->NewObject(clazz, constructor);
assert(obj);
identity_list *_il;
for (_il = il; _il && _il->ident; _il = _il->next) {
jobject o = from_identity(env, _il->ident);
callBooleanMethod(env, obj, "add", o);
}
env->DeleteLocalRef(clazz);
return obj;
}
identity_list *to_identitylist(JNIEnv *env,
jobject obj)
{
if (!obj) {
return NULL;
}
jint size = callIntMethod(env, obj, "size");
if (size == 0) {
return NULL;
}
identity_list *il = new_identity_list(NULL);
identity_list *_il;
jint i;
for (_il = il, i = 0; i < (int) size; i++) {
jobject o = callObjectMethod(env, obj, "get", i);
pEp_identity *ident = to_identity(env, o);
_il = identity_list_add(_il, ident);
env->DeleteLocalRef(o);
}
return il;
}
jobject _from_blob(JNIEnv *env,
bloblist_t *b)
{
if (!b) {
return (jobject) NULL;
}
static const char *classname = "foundation/pEp/jniadapter/_Blob";
jclass clazz = findClass(env, classname);
jmethodID constructor = env->GetMethodID(clazz, "<init>", "()V");
assert(constructor);
jobject obj = env->NewObject(clazz, constructor);
env->DeleteLocalRef(clazz);
jfieldID fieldID = getFieldID(env, classname, "data", "[B");
jbyteArray _data = env->NewByteArray(static_cast<jsize>(b->size));
env->SetByteArrayRegion(_data, 0, b->size, reinterpret_cast<jbyte *>(b->value));
env->SetObjectField(obj, fieldID, static_cast<jobject>(_data));
_setStringField(env, classname, obj, "mime_type", b->mime_type);
_setStringField(env, classname, obj, "filename", b->filename);
return obj;
}
jobject from_bloblist(JNIEnv *env,
bloblist_t *bl)
{
if (!bl) {
return (jobject) NULL;
}
jclass clazz = findClass(env, "java/util/Vector");
jmethodID constructor = env->GetMethodID(clazz, "<init>", "()V");
assert(constructor);
jobject obj = env->NewObject(clazz, constructor);
assert(obj);
env->DeleteLocalRef(clazz);
bloblist_t *_bl;
for (_bl = bl; _bl && _bl->value; _bl = _bl->next) {
jobject o = _from_blob(env, _bl);
if (o) {
callBooleanMethod(env, obj, "add", o);
}
}
return obj;
}
bloblist_t *to_blob(JNIEnv *env,
jobject obj)
{
if (!obj) {
return NULL;
}
static const char *classname = "foundation/pEp/jniadapter/_Blob";
jclass clazz = findClass(env, classname);
char *mime_type = _getStringField(env, classname, obj, "mime_type");
char *filename = _getStringField(env, classname, obj, "filename");
jfieldID data_id = getFieldID(env, classname, "data", "[B");
jbyteArray _data = static_cast<jbyteArray>(env->GetObjectField(obj, data_id));
size_t size = static_cast<size_t>(env->GetArrayLength(_data));
char *b = static_cast<char *>(malloc(size));
assert(b);
env->GetByteArrayRegion(_data, 0, size, reinterpret_cast<jbyte *>(b));
bloblist_t *bl = new_bloblist(b, size, mime_type, filename);
free(mime_type);
free(filename);
return bl;
}
bloblist_t *to_bloblist(JNIEnv *env,
jobject obj)
{
if (!obj) {
return NULL;
}
jint size = callIntMethod(env, obj, "size");
if (size == 0) {
return NULL;
}
bloblist_t *bl = new_bloblist(NULL, 0, NULL, NULL);
bloblist_t *_bl;
_bl = bl;
jint i;
for (i = 0; i < (int) size; i++) {
jobject o = callObjectMethod(env, obj, "get", i);
bloblist_t *b = to_blob(env, o);
_bl = bloblist_add(_bl, b->value, b->size, b->mime_type, b->filename);
env->DeleteLocalRef(o);
}
return bl;
}
PEP_enc_format to_EncFormat(JNIEnv *env,
jobject obj)
{
static const char *classname = "foundation/pEp/jniadapter/Message$EncFormat";
jclass clazz_enc_format = findClass(env, classname);
jfieldID field_value = env->GetFieldID(clazz_enc_format, "value", "I");
assert(field_value);
env->DeleteLocalRef(clazz_enc_format);
return static_cast<PEP_enc_format>(env->GetIntField(obj, field_value));
}
PEP_CIPHER_SUITE to_CipherSuite(JNIEnv *env,
jobject obj)
{
static const char *classname = "foundation/pEp/jniadapter/CipherSuite";
jclass clazz_enc_format = findClass(env, classname);
jfieldID field_value = env->GetFieldID(clazz_enc_format, "value", "I");
assert(field_value);
env->DeleteLocalRef(clazz_enc_format);
return static_cast<PEP_CIPHER_SUITE>(env->GetIntField(obj, field_value));
}
sync_handshake_result to_SyncHandshakeResult(JNIEnv *env,
jobject obj)
{
static const char *classname = "foundation/pEp/jniadapter/SyncHandshakeResult";
jclass clazz_enc_format = findClass(env, classname);
jfieldID field_value = env->GetFieldID(clazz_enc_format, "value", "I");
assert(field_value);
env->DeleteLocalRef(clazz_enc_format);
return static_cast<sync_handshake_result>(env->GetIntField(obj, field_value));
}
};
};

147
src/cxx/jniutils.hh

@ -0,0 +1,147 @@
#pragma once
#include <unordered_map>
#include <thread>
#include <mutex>
#include <jni.h>
#include <pEp/stringpair.h>
#include <pEp/identity_list.h>
#include <pEp/bloblist.h>
#include <pEp/message.h>
#include <pEp/sync_api.h>
#include <pEp/passphrase_cache.hh>
#if 0 // Enable if log needed
#include <android/log.h>
#define LOG_TAG "pEpJNIAdapter"
#define LOGD(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#else
#define LOGD(...) do{}while(0)
#endif
namespace pEp {
namespace JNIAdapter {
// Global mutex needs to be locked in all constructors which insert their own mutex object
// into the unordered_map (which is thread safe for read, but not for write)
extern std::mutex global_mutex;
// Stores mutex per java object
extern std::unordered_map<long, std::mutex *> engine_objid_mutex;
// needs to be called after create_engine_java_object_mutex()
// and before release_engine_java_object_mutex()
// Thread safe
std::mutex *get_engine_java_object_mutex(JNIEnv *env,
jobject me);
// Needs to be called exactly once per obj, in the constructor of the obj
// You need to lock a global mutex before calling this function (write to unordered_map)
void create_engine_java_object_mutex(JNIEnv *env,
jobject me);
// Needs to be called exactly once per obj, in the destructor of this obj
// You need to lock a global mutex before calling this function (write to unordered_map)
void release_engine_java_object_mutex(JNIEnv *env,
jobject me);
jclass findClass(JNIEnv *env,
const char *classname);
jfieldID getFieldID(JNIEnv *env,
const char *classname,
const char *fieldname,
const char *signature);
jfieldID getFieldID(JNIEnv *env,
const char *classname,
const char *fieldname,
const char *signature,
const jclass clazz);
jint callIntMethod(JNIEnv *env,
jobject obj,
const char *methodname);
jlong callLongMethod(JNIEnv *env,
jobject obj,
const char *methodname);
jobject callObjectMethod(JNIEnv *env,
jobject obj,
const char *methodname,
jint index);
jboolean callBooleanMethod(JNIEnv *env,
jobject obj,
const char *methodname,
jobject o);
jint outOfMemory(JNIEnv *env);
jobject from_Integer(JNIEnv *env,
int val);
int to_Integer(JNIEnv *env,
jobject obj);
jbyteArray from_string(JNIEnv *env,
const char *str);
char *to_string(JNIEnv *env,
jbyteArray str);
jobject from_stringlist(JNIEnv *env,
stringlist_t *sl);
stringlist_t *to_stringlist(JNIEnv *env,
jobject obj);
jobject from_stringpairlist(JNIEnv *env,
stringpair_list_t *sl);
stringpair_list_t *to_stringpairlist(JNIEnv *env,
jobject obj);
jobject from_timestamp(JNIEnv *env,
timestamp *ts);
timestamp *to_timestamp(JNIEnv *env,
jobject date);
jobject from_identity(JNIEnv *env,
pEp_identity *ident);
jobject from_identity(JNIEnv *env,
pEp_identity *ident,
jclass identityClass);
pEp_identity *to_identity(JNIEnv *env,
jobject obj);
jobject from_identitylist(JNIEnv *env,
identity_list *il);
identity_list *to_identitylist(JNIEnv *env,
jobject obj);
jobject from_bloblist(JNIEnv *env,
bloblist_t *bl);
bloblist_t *to_blob(JNIEnv *env,
jobject obj);
bloblist_t *to_bloblist(JNIEnv *env,
jobject obj);
PEP_enc_format to_EncFormat(JNIEnv *env,
jobject obj);
PEP_CIPHER_SUITE to_CipherSuite(JNIEnv *env,
jobject obj);
sync_handshake_result to_SyncHandshakeResult(JNIEnv *env,
jobject obj);
};
};

15
src/cxx/passphrase_callback.hh

@ -0,0 +1,15 @@
#pragma once
#include <pEp/passphrase_cache.hh>
namespace pEp {
namespace JNIAdapter {
char *passphraseRequiredCallback(const PEP_STATUS status);
template<typename... A> PEP_STATUS passphraseWrap(PEP_STATUS f(PEP_SESSION, A...), PEP_SESSION session, A... a);
}
}
#include "passphrase_callback.hxx"

42
src/cxx/passphrase_callback.hxx

@ -0,0 +1,42 @@
#pragma once
#include "passphrase_callback.hh"
namespace pEp {
namespace JNIAdapter {
template<typename... A> PEP_STATUS passphraseWrap(PEP_STATUS f(PEP_SESSION, A...), PEP_SESSION session, A... a) {
pEpLog("cached passphrase mode");
bool retryAgain = false;
int maxRetries = 3;
int retryCount = 0;
PEP_STATUS status;
do {
// the actual target function
pEpLog("calling passphrase_cache.api from basic_api");
status = passphrase_cache.api(f, session, a...);
pEpLog("PEP_STATUS:" << status);
if (status == PEP_PASSPHRASE_REQUIRED ||
status == PEP_WRONG_PASSPHRASE ||
status == PEP_PASSPHRASE_FOR_NEW_KEYS_REQUIRED)
{
pEpLog("none of the cached passphrases worked");
if (retryCount < maxRetries) {
// call the app
char *_passphrase = passphraseRequiredCallback(status);
pEpLog("callback returned, config_passphrase() with new passphrase");
PEP_STATUS status = ::config_passphrase(session, passphrase_cache.add(_passphrase));
retryAgain = true;
retryCount++;
} else {
pEpLog("max retries reached:" << maxRetries);
retryAgain = false;
}
} else {
retryAgain = false;
}
} while (retryAgain);
return status;
}
}
}

28
src/foundation/pEp/jniadapter/Engine.java.target

@ -1,28 +0,0 @@
package foundation.pEp.jniadapter;
import java.util.ArrayList;
import java.util.Vector;
final public class Engine extends AbstractEngine {
public Engine() throws pEpException { }
public native Message encrypt_message(
Message src,
ArrayList<String> extra,
Message.EncFormat enc_format
) throws pEpException;
public class DecryptResult {
public Message dst;
public Color color;
}
public native DecryptResult decrypt_message(
Message src,
ArrayList<String> keylist
) throws pEpException;
public native Color outgoing_message_color(
Message msg
) throws pEpException;
}

218
src/foundation/pEp/jniadapter/Message.java.target

@ -1,218 +0,0 @@
package foundation.pEp.jniadapter;
import java.util.ArrayList;
import java.util.Vector;
import java.util.Date;
import java.util.HashMap;
public class Message implements AutoCloseable {
private final long handle;
native long init();
native void release(long handle);
public Message() {
handle = init();
}
public final void close() {
release(handle);
}
public enum TextFormat {
Plain (0),
Html (1),
Other (255)
;
static class Management {
public static final HashMap<Integer, TextFormat> tag =
new HashMap<Integer, TextFormat>();
}
public final int value;
TextFormat(int value) {
this.value = value;
fill(value);
}
private void fill(int value) {
Management.tag.put(value, this);
}
}
public enum Direction {
Incoming (0),
Outgoing (1)
;
static class Management {
public static final HashMap<Integer, Direction> tag =
new HashMap<Integer, Direction>();
}
public final int value;
Direction(int value) {
this.value = value;
fill(value);
}
private void fill(int value) {
Management.tag.put(value, this);
}
}
public enum EncFormat {
None (0),
Pieces (1),
SMIME (2),
PGPMIME (3),
PEP (4)
;
static class Management {
public static final HashMap<Integer, EncFormat> tag =
new HashMap<Integer, EncFormat>();
}
public final int value;
EncFormat(int value) {
this.value = value;
fill(value);
}
private void fill(int value) {
Management.tag.put(value, this);
}
}
private native int _getDir();
private native void _setDir(int value);
public Direction getDir() {
return Direction.tag.get(_getDir());
}
public void setDir(Direction value) {
_setDir(value.value);
}
private native byte[] _getId();
private native void _setId(byte[] value);
public String getId() {
return AbstractEngine.toUTF16(_getId());
}
public void setId(String value) {
_setId(AbstractEngine.toUTF8(value));
}
private native byte[] _getShortmsg();
private native void _setShortmsg(byte[] value);
public String getShortmsg() {
return AbstractEngine.toUTF16(_getShortmsg());
}
public void setShortmsg(String value) {
_setShortmsg(AbstractEngine.toUTF8(value));
}
private native byte[] _getLongmsg();
private native void _setLongmsg(byte[] value);
public String getLongmsg() {
return AbstractEngine.toUTF16(_getLongmsg());
}
public void setLongmsg(String value) {
_setLongmsg(AbstractEngine.toUTF8(value));
}
private native byte[] _getLongmsgFormatted();
private native void _setLongmsgFormatted(byte[] value);
public String getLongmsgFormatted() {
return AbstractEngine.toUTF16(_getLongmsgFormatted());
}
public void setLongmsgFormatted(String value) {
_setLongmsgFormatted(AbstractEngine.toUTF8(value));
}
public native ArrayList<Blob> getAttachments();
public native void setAttachments(ArrayList<Blob> value);
public native Date getSent();
public native void setSent(Date value);
public native Date getRecv();
public native void setRecv(Date value);
private native AbstractEngine._Identity _getFrom();
private native void _setFrom(AbstractEngine._Identity value);
public Identity getFrom() {
return new _getFrom().getIdentity();
}
public void setFrom(Identity value) {
_setFrom(new AbstractEngine._Identity(value));
}
public native ArrayList<Identity> getTo();
public native void setTo(ArrayList<Identity> value);
public native Identity getRecvBy();
public native void setRecvBy(Identity value);
public native ArrayList<Identity> getCc();
public native void setCc(ArrayList<Identity> value);
public native ArrayList<Identity> getBcc();
public native void setBcc(ArrayList<Identity> value);
public native ArrayList<Identity> getReplyTo();
public native void setReplyTo(ArrayList<Identity> value);
private native ArrayList<byte[]> _getInReplyTo();
private native void _setInReplyTo(ArrayList<byte[]> value);
public ArrayList<String> getInReplyTo() {
return AbstractEngine.toUTF16(_getInReplyTo());
}
public void setInReplyTo(ArrayList<String> value) {
_setInReplyTo(AbstractEngine.toUTF8(value));
}
private native ArrayList<byte[]> _getReferences();
private native void _setReferences(ArrayList<byte[]> value);
public ArrayList<String> getReferences() {
return AbstractEngine.toUTF16(_getReferences());
}
public void setReferences(ArrayList<String> value) {
_setReferences(AbstractEngine.toUTF8(value));
}
private native ArrayList<byte[]> _getKeywords();
private native void _setKeywords(ArrayList<byte[]> value);
public ArrayList<String> getKeywords() {
return AbstractEngine.toUTF16(_getKeywords());
}
public void setKeywords(ArrayList<String> value) {
_setKeywords(AbstractEngine.toUTF8(value));
}
private native byte[] _getComments();
private native void _setComments(byte[] value);
public String getComments() {
return AbstractEngine.toUTF16(_getComments());
}
public void setComments(String value) {
_setComments(AbstractEngine.toUTF8(value));
}
private native Vector<Pair<byte[], byte[]>> _getOptFields();
private native void _setOptFields(Vector<Pair<byte[], byte[]>> value);
public Vector<Pair<String, String>> getOptFields() {
return AbstractEngine.toUTF16(_getOptFields());
}
public void setOptFields(Vector<Pair<String, String>> value) {
_setOptFields(AbstractEngine.toUTF8(value));
}
public native Message.EncFormat getEncFormat();
public native void setEncFormat(Message.EncFormat value);
}

11
src/foundation/pEp/jniadapter/UniquelyIdentifiable.java

@ -1,11 +0,0 @@
package foundation.pEp.jniadapter;
import java.util.concurrent.atomic.AtomicLong;
abstract class UniquelyIdentifiable {
static final AtomicLong NEXT_ID = new AtomicLong(1);
final long id = NEXT_ID.getAndIncrement();
public long getId() {
return id;
}
}

252
src/gen_java_Message.ysl2

@ -1,252 +0,0 @@
include yslt.yml2
tstylesheet {
include ./textutils.ysl2
include ./types_java.ysl2
template "/namespace[@name='pEp']" apply "struct|enum|exception", 0;
template "struct" {
const "cname" call "toJava" with "type", "@name";
document("foundation/pEp/jniadapter/{$cname}.java", "text")
||
package foundation.pEp.jniadapter;
import java.util.ArrayList;
import java.util.Vector;
import java.util.Date;
import java.util.HashMap;
import java.io.Serializable;
public class «$cname» implements AutoCloseable, Serializable {
private static final long serialVersionUID = 2119420428331150924L;
private long handle;
native long init();
native void release(long handle);
public «$cname»() {
handle = init();
}
private native long _«$cname»(
byte[] mime_text
) throws pEpException;
public «$cname»(String mime_text) {
byte[] _mime_text = AbstractEngine.toUTF8(mime_text);
handle = _«$cname»(_mime_text);
}
public native byte[] _encodeMIME() throws pEpException;
public String encodeMIME() {
return AbstractEngine.toUTF16(_encodeMIME());
}
private «$cname»(long h) {
handle = h;
}
public final void close() {
release(handle);
}
final protected long getHandle() {
return handle;
}
`` apply "enum", mode=inner
`` apply "*[name(.)!='enum']", mode=entry
}
||
}
template "enum|exception" {
const "jname" call "toJava" with "type", "@name";
document("foundation/pEp/jniadapter/{$jname}.java", "text")
||
package foundation.pEp.jniadapter;
import java.util.HashMap;
`` apply ".", 0, mode=inner
||
}
template "enum|exception", mode=inner {
const "jname" call "CamelCase" with "text", "@name";
||
public enum «$jname» {
`` apply "*", mode=value
;
public final int value;
private static HashMap<Integer, «$jname»> intMap;
private «$jname»(int value) {
this.value = value;
}
public static «$jname» getByInt(int value){
if (intMap == null) {
intMap = new HashMap<Integer, «$jname»>();
for («$jname» s : «$jname».values()) {
intMap.put(s.value, s);
}
}
if (intMap.containsKey(value)) {
return intMap.get(value);
}
return null;
}
}
||
}
template "*", mode=entry {
const "ctype", "name(.)";
const "type" call "toJava" with "type", "name(.)";
const "itype" call "toIntermediate" with "type", "name(.)";
const "name" call "toJava" with "type", "name(*[position()=1])";
choose {
when "$ctype = 'identity'"
||
private native «$itype» _get«$name»();
private native void _set«$name»(«$itype» value);
public «$type» get«$name»() {
«$itype» res = _get«$name»();
if(res != null){
return new «$type»(_get«$name»());
}else{
return null;
}
}
public void set«$name»(«$type» value) {
if(value != null)
_set«$name»(new «$itype»(value));
else
_set«$name»(null);
}
||
when "$ctype = 'identitylist' or $ctype = 'bloblist' or $ctype = 'stringlist' or $ctype = 'stringpairlist'"
{
const "ename", "substring-after(substring($type,1,string-length($type)-1), '<')";
const "iename" choose {
when "$ctype = 'stringlist'" > byte[]
when "$ctype = 'stringpairlist'" > Pair<byte[],byte[]>
otherwise > _«$ename»
}
const "convget" choose {
when "$ctype = 'stringlist'" > AbstractEngine.toUTF16(i)
when "$ctype = 'stringpairlist'" > new Pair<String, String>(AbstractEngine.toUTF16(i.first), AbstractEngine.toUTF16(i.second))
otherwise > new «$ename»(i)
}
const "convset" choose {
when "$ctype = 'stringlist'" > AbstractEngine.toUTF8(i)
when "$ctype = 'stringpairlist'" > new Pair<byte[],byte[]>(AbstractEngine.toUTF8(i.first), AbstractEngine.toUTF8(i.second))
otherwise > new _«$ename»(i)
}
||
private native «$itype» _get«$name»();
private native void _set«$name»(«$itype» value);
public «$type» get«$name»() {
«$itype» glist = _get«$name»();
if(glist != null){
«$type» list = new «$type»();
for («$iename» i : glist)
list.add(«$convget»);
return list;
}
return null;
}
public void set«$name»(«$type» value) {
if(value != null){
«$itype» list = new «$itype»();
for («$ename» i : value)
list.add(«$convset»);
_set«$name»(list);
}else{
_set«$name»(null);
}
}
||
}
when "$itype != $type"
||
private native «$itype» _get«$name»();
private native void _set«$name»(«$itype» value);
public «$type» get«$name»() {
«$itype» res = _get«$name»();
if(res != null)
return AbstractEngine.toUTF16(res);
else
return null;
}
public void set«$name»(«$type» value) {
if(value != null)
_set«$name»(AbstractEngine.toUTF8(value));
else
_set«$name»(new byte[0]);
}
||
when "$itype != $type"
||
private native «$itype» _get«$name»();
private native void _set«$name»(«$itype» value);
public «$type» get«$name»() {
«$itype» res = _get«$name»();
if(res != null)
return AbstractEngine.toUTF16(res);
else
return null;
}
public void set«$name»(«$type» value) {
if(value != null)
_set«$name»(AbstractEngine.toUTF8(value));
else
_set«$name»(null);
}
||
when "../enum[@name=$ctype]"
||
private native int _get«$name»();
public «$itype» get«$name»() {
return «$itype».getByInt(_get«$name»());
}
private native void _set«$name»(int value);
public void set«$name»(«$itype» value) {
if(value != null)
_set«$name»(value.value);
else
_set«$name»(0);
}
||
otherwise
||
public native «$itype» get«$name»();
public native void set«$name»(«$itype» value);
||
}
}
template "*", mode=value {
const "name" call "toJava" with "type", "name(.)";
| «$name» («.»)`if "position()!=last()" > , `
}
}

35
src/gen_java_exceptions.ysl2

@ -1,35 +0,0 @@
include yslt.yml2
tstylesheet {
include ./textutils.ysl2
template "/" {
| package foundation.pEp.jniadapter;
|
| public class pEpException extends RuntimeException {
| public pEpException(String message) {
| super(message);
| }
| }
apply "namespace/exception[@name='Status']", 0;
}
function "exception" {
param "name";
document "foundation/pEp/jniadapter/{$name}.java", "text" {
| package foundation.pEp.jniadapter;
|
| public class «$name» extends pEpException {
| public «$name»(String message) {
| super(message);
| }
| }
}
}
template "exception" for "*[text()!=0]" call "exception"
with "name" call "CamelCase" with "text", "name(.)";
}

64
src/gen_throw_pEp_exception.ysl2

@ -1,64 +0,0 @@
include yslt.yml2
tstylesheet {
include ./textutils.ysl2
template "/" {
apply "namespace", 0;
document "throw_pEp_exception.hh", "text"
||
#pragma once
#include <jni.h>
namespace pEp {
namespace JNIAdapter {
jint throw_pEp_Exception(JNIEnv *env, PEP_STATUS status);
};
};
||
}
template "namespace"
||
#include <assert.h>
#include <pEp/pEpEngine.h>
#include "throw_pEp_exception.hh"
namespace pEp {
namespace JNIAdapter {
jint throw_pEp_Exception(JNIEnv *env, PEP_STATUS status)
{
jclass ex;
const char *ex_name;
switch (status) {
`` apply "exception/*[text()!=0]", 4, mode=case
default:
assert(0);
ex_name = "Exception";
}
ex = env->FindClass(ex_name);
assert(ex);
if (ex == NULL) {
ex = env->FindClass("java/lang/NoClassDefFoundError");
assert(ex);
}
return env->ThrowNew(ex, ex_name);
}
};
};
||
template "*", mode=case {
| case `call "UCASE" with "text", "name(.)"`:
| ex_name = "foundation/pEp/jniadapter/`call "CamelCase" with "text", "name(.)"`";
| break;
}
}

149
src/foundation/pEp/jniadapter/AbstractEngine.java → src/java/foundation/pEp/jniadapter/AbstractEngine.java

@ -4,11 +4,11 @@ import java.util.ArrayList;
import java.util.Vector;
import foundation.pEp.jniadapter.Sync.DefaultCallback;
import foundation.pEp.jniadapter.interfaces.*;
import foundation.pEp.jniadapter.exceptions.*;
import java.io.UnsupportedEncodingException;
import java.text.Normalizer;
abstract class AbstractEngine extends UniquelyIdentifiable implements AutoCloseable {
abstract class AbstractEngine extends UniquelyIdentifiable implements AbstractEngineInterface {
static {
System.loadLibrary("pEpJNI");
}
@ -23,6 +23,9 @@ abstract class AbstractEngine extends UniquelyIdentifiable implements AutoClosea
private native void init();
private native void release();
private long keyserverThread;
private long keyserverQueue;
public AbstractEngine() throws pEpException {
synchronized (AbstractEngine.class) {
init();
@ -35,128 +38,52 @@ abstract class AbstractEngine extends UniquelyIdentifiable implements AutoClosea
}
}
// libpEpAdapter based logging using pEpEngine logging API
public native static void setDebugLogEnabled(boolean enabled);
public native static boolean getDebugLogEnabled();
public native String getVersion();
public native String getProtocolVersion();
private long keyserverThread;
private long keyserverQueue;
public native void startKeyserverLookup();
public native void stopKeyserverLookup();
public native void startSync();
public native void stopSync();
public native boolean isSyncRunning();
public static byte[] toUTF8(String str) {
if (str == null)
return null;
try {
String _str = Normalizer.normalize(str, Normalizer.Form.NFC);
byte _buf[] = _str.getBytes("UTF-8");
byte _cpy[] = new byte[_buf.length];
System.arraycopy(_buf,0,_cpy,0,_buf.length);
return _cpy;
}
catch (UnsupportedEncodingException e) {
assert false;
return new byte[0];
}
public String getVersion() {
return _getVersion();
}
public static Vector<byte[]> toUTF8(Vector<String> list) {
if (list == null)
return null;
Vector<byte[]> result = new Vector<byte[]>(list.size());
private native String _getVersion();
for (int i=0; i<list.size(); i++)
result.add(toUTF8(list.get(i)));
return result;
public String getProtocolVersion() {
return _getProtocolVersion();
}
public static Pair<byte[], byte[]> toUTF8(Pair<String, String> pair) {
if (pair == null)
return null;
Pair<byte[], byte[]> result = new Pair<byte[], byte[]>();
private native String _getProtocolVersion();
result.first = toUTF8(pair.first);
result.second = toUTF8(pair.second);
return result;
public void startKeyserverLookup() {
_startKeyserverLookup();
}
public static ArrayList<Pair<byte[], byte[]>> toUTF8(ArrayList<Pair<String, String>> list) {
if (list == null)
return null;
private native void _startKeyserverLookup();
ArrayList<Pair<byte[], byte[]>> result = new ArrayList<Pair<byte[], byte[]>>(list.size());
for (int i=0; i<list.size(); i++)
result.set(i, toUTF8(list.get(i)));
return result;
public void stopKeyserverLookup() {
_startKeyserverLookup();
}
public static String toUTF16(byte[] utf8) {
if (utf8 == null)
return null;
private native void _stopKeyserverLookup();
try {
byte newUtf8[] = new byte[utf8.length];
System.arraycopy(utf8,0,newUtf8,0,utf8.length);
return new String(newUtf8, "UTF-8");
}
catch (UnsupportedEncodingException e) {
assert false;
return new String();
}
public void startSync() {
_startSync();
}
public static Vector<String> toUTF16(Vector<byte[]> list) {
if (list == null)
return null;
private native void _startSync();
Vector<String> result = new Vector<String>(list.size());
for (int i=0; i<list.size(); i++)
result.add(toUTF16(list.get(i)));
return result;
public void stopSync() {
_stopSync();
}
public static Pair<String, String> toUTF16(Pair<byte[], byte[]> pair) {
if (pair == null)
return null;
Pair<String, String> result = new Pair<String,String>();
result.first = toUTF16(pair.first);
result.second = toUTF16(pair.second);
private native void _stopSync();
return result;
public boolean isSyncRunning() {
return _isSyncRunning();
}
public static ArrayList<Pair<String, String>> toUTF16(ArrayList<Pair<byte[], byte[]>> list) {
if (list == null)
return null;
ArrayList<Pair<String, String>> result = new ArrayList<Pair<String, String>>(list.size());
for (int i=0; i<list.size(); i++)
result.set(i, toUTF16(list.get(i)));
return result;
}
private native boolean _isSyncRunning();
// Callbacks
public void setMessageToSendCallback(Sync.MessageToSendCallback messageToSendCallback) {
this.messageToSendCallback = messageToSendCallback;
}
@ -175,7 +102,7 @@ abstract class AbstractEngine extends UniquelyIdentifiable implements AutoClosea
this.passphraseRequiredCallback = passphraseRequiredCallback;
}
public int needsFastPollCallFromC(boolean fast_poll_needed) {
private int needsFastPollCallFromC(boolean fast_poll_needed) {
if (needsFastPollCallback != null) {
needsFastPollCallback.needsFastPollCallFromC(fast_poll_needed);
} else {
@ -184,7 +111,7 @@ abstract class AbstractEngine extends UniquelyIdentifiable implements AutoClosea
return 0;
}
public int notifyHandshakeCallFromC(_Identity _myself, _Identity _partner, SyncHandshakeSignal _signal) {
private int notifyHandshakeCallFromC(_Identity _myself, _Identity _partner, SyncHandshakeSignal _signal) {
Identity myself = new Identity(_myself);
Identity partner = (_partner != null) ? new Identity(_partner) : null;
@ -197,7 +124,7 @@ abstract class AbstractEngine extends UniquelyIdentifiable implements AutoClosea
return 0;
}
public byte[] passphraseRequiredFromC(final PassphraseType passphraseType) {
private byte[] passphraseRequiredFromC(final PassphraseType passphraseType) {
String ret = "";
if (passphraseRequiredCallback != null) {
System.out.println("calling passphraseRequiredCallback on engine ObjID:" + getId());
@ -210,10 +137,10 @@ abstract class AbstractEngine extends UniquelyIdentifiable implements AutoClosea
// this repeats MaxRetries times (currentluy hardcoded to 3)
// Then the orig call will return with the PEP_STATUS (most likely PEP_PASSPHRASE_REQUIRED)
}
return toUTF8(ret);
return Utils.toUTF8(ret);
}
public int messageToSendCallFromC (Message message) {
private int messageToSendCallFromC (Message message) {
System.out.println("pEpSync" + "messageToSendCallFromC: " + messageToSendCallback );
if (messageToSendCallback != null) {
messageToSendCallback.messageToSend(message);
@ -232,11 +159,11 @@ abstract class AbstractEngine extends UniquelyIdentifiable implements AutoClosea
ArrayList<Pair<String, String>> opts = new ArrayList<>();
Pair<String, String> xpEp = new Pair<>();
xpEp.first = "X-pEp-Version";
xpEp.second = this.getProtocolVersion();;
xpEp.second = this.getProtocolVersion();
opts.add(xpEp);
msg.setOptFields(opts);
if(encFormat == Message.EncFormat.PEP) {
if (encFormat == Message.EncFormat.PEP) {
// For EncFormat.PEP
// The pgpText goes into the attachment index 1
msg.setShortmsg("p≡p");
@ -257,14 +184,12 @@ abstract class AbstractEngine extends UniquelyIdentifiable implements AutoClosea
attachments.add(att0);
attachments.add(att1);
msg.setAttachments(attachments);
}
else if (encFormat == Message.EncFormat.PEPEncInlineEA) {
} else if (encFormat == Message.EncFormat.PEPEncInlineEA) {
// For EncFormat.PEPEncInlineEA
// The pgpText goes into the longMessage
msg.setShortmsg("");
msg.setLongmsg(pgpText);
}
else {
} else {
throw new pEpCannotEncode("Message.Encformat not supported: " + encFormat.toString());
}

20
src/foundation/pEp/jniadapter/Blob.java → src/java/foundation/pEp/jniadapter/Blob.java

@ -1,8 +1,9 @@
package foundation.pEp.jniadapter;
import foundation.pEp.jniadapter.interfaces.*;
import java.io.Serializable;
public class Blob implements Serializable {
public class Blob implements BlobInterface, Serializable {
public byte[] data;
public String mime_type;
public String filename;
@ -11,10 +12,18 @@ public class Blob implements Serializable {
mime_type = "application/octet-stream";
}
/** Human readable string representation of Blob.
Blob(_Blob b) {
data = b.data;
mime_type = Utils.toUTF16(b.mime_type);
filename = Utils.toUTF16(b.filename);
}
/**
* Human readable string representation of Blob.
* The data field is ASN.1 XER decoded for mime_types:
* "application/pEp.sync"
* "application/pEp.keyreset"
*
* @return String Blob as String
*/
public String toString() {
@ -22,15 +31,10 @@ public class Blob implements Serializable {
String ret = "";
ret += "mime_type: \"" + mime_type + "\"\n";
ret += "filename: \"" + filename + "\"\n";
ret += "data plain: \"" + AbstractEngine.toUTF16(data) + "\"\n";
ret += "data plain: \"" + Utils.toUTF16(data) + "\"\n";
ret += "data decoded: \"" + _b.dataToXER() + "\"\n";
return ret;
}
Blob(_Blob b) {
data = b.data;
mime_type = AbstractEngine.toUTF16(b.mime_type);
filename = AbstractEngine.toUTF16(b.filename);
}
}

0
src/foundation/pEp/jniadapter/CommType.java → src/java/foundation/pEp/jniadapter/CommType.java

38
src/foundation/pEp/jniadapter/Identity.java → src/java/foundation/pEp/jniadapter/Identity.java

@ -1,8 +1,10 @@
package foundation.pEp.jniadapter;
import foundation.pEp.jniadapter.interfaces.*;
import java.io.Serializable;
import java.util.List;
public class Identity implements Serializable{
public class Identity implements IdentityInterface, Serializable {
public String address;
public String fpr;
public String user_id;
@ -23,28 +25,38 @@ public class Identity implements Serializable{
}
public Identity(_Identity i) {
address = AbstractEngine.toUTF16(i.address);
fpr = AbstractEngine.toUTF16(i.fpr);
user_id = AbstractEngine.toUTF16(i.user_id);
username = AbstractEngine.toUTF16(i.username);
address = Utils.toUTF16(i.address);
fpr = Utils.toUTF16(i.fpr);
user_id = Utils.toUTF16(i.user_id);
username = Utils.toUTF16(i.username);
comm_type = CommType.Management.tag.get(i.comm_type);
lang = AbstractEngine.toUTF16(i.lang);
lang = Utils.toUTF16(i.lang);
me = i.me;
flags = i.flags;
}
@Override
public String toString() {
return address + "::" + username + "\n" +
user_id + "::" + fpr;
public Rating getRating() {
return Rating.getByInt(_getRating(comm_type.value));
}
// Native
private native int _getRating(int commType);
public Rating getRating() {
return Rating.getByInt(_getRating(comm_type.value));
public static String toXKeyList(List<Identity> ids) {
String ret = "";
if(ids.size() > 0) {
for (Identity id : ids) {
ret += id.fpr;
ret += ",";
}
ret = ret.substring(0, ret.length() - 1);
}
return ret;
}
@Override
public String toString() {
return address + "::" + username + "\n" +
user_id + "::" + fpr;
}
}

6
src/foundation/pEp/jniadapter/Pair.java → src/java/foundation/pEp/jniadapter/Pair.java

@ -10,5 +10,11 @@ public class Pair<F, S> {
first = f;
second = s;
}
public String toString() {
String ret="";
ret += "'" + first.toString() + "' : '" + second.toString() + "'";
return ret;
}
}

11
src/foundation/pEp/jniadapter/Sync.java → src/java/foundation/pEp/jniadapter/Sync.java

@ -1,12 +1,8 @@
package foundation.pEp.jniadapter;
import foundation.pEp.jniadapter.Identity;
import foundation.pEp.jniadapter.Message;
import foundation.pEp.jniadapter.pEpException;
public interface Sync {
interface NeedsFastPollCallback {
void needsFastPollCallFromC(Boolean fast_poll_needed);
}
@ -23,8 +19,7 @@ public interface Sync {
String passphraseRequired(final PassphraseType pEpStatus);
}
public class DefaultCallback
implements Sync.MessageToSendCallback, Sync.NotifyHandshakeCallback, Sync.NeedsFastPollCallback {
public class DefaultCallback implements Sync.MessageToSendCallback, Sync.NotifyHandshakeCallback, Sync.NeedsFastPollCallback {
@Override
public void needsFastPollCallFromC(Boolean fast_poll_needed) {
System.out.println("Need fast Poll");
@ -34,7 +29,7 @@ public interface Sync {
public void messageToSend(Message message) {
System.out.println("messageToSend Defualt Callback");
}
@Override
public void notifyHandshake(Identity myself, Identity partner, SyncHandshakeSignal signal) {
System.out.println("notifyHandshake Default Callback");

12
src/java/foundation/pEp/jniadapter/UniquelyIdentifiable.java

@ -0,0 +1,12 @@
package foundation.pEp.jniadapter;
import java.util.concurrent.atomic.AtomicLong;
// Abstract here so you can only inherit from, but not instantiate
abstract public class UniquelyIdentifiable {
private static final AtomicLong NEXT_ID = new AtomicLong(1);
private final long id = NEXT_ID.getAndIncrement();
protected long getId() {
return id;
}
}

115
src/java/foundation/pEp/jniadapter/Utils.java

@ -0,0 +1,115 @@
package foundation.pEp.jniadapter;
import java.io.UnsupportedEncodingException;
import java.text.Normalizer;
import java.util.ArrayList;
import java.util.Vector;
public class Utils {
private Utils() { }
public static byte[] toUTF8(String str) {
if (str == null)
return null;
try {
String _str = Normalizer.normalize(str, Normalizer.Form.NFC);
byte _buf[] = _str.getBytes("UTF-8");
byte _cpy[] = new byte[_buf.length];
System.arraycopy(_buf,0,_cpy,0,_buf.length);
return _cpy;
}
catch (UnsupportedEncodingException e) {
assert false;
return new byte[0];
}
}
public static Vector<byte[]> toUTF8(Vector<String> list) {
if (list == null)
return null;
Vector<byte[]> result = new Vector<byte[]>(list.size());
for (int i=0; i<list.size(); i++)
result.add(toUTF8(list.get(i)));
return result;
}
public static Pair<byte[], byte[]> toUTF8(Pair<String, String> pair) {
if (pair == null)
return null;
Pair<byte[], byte[]> result = new Pair<byte[], byte[]>();
result.first = toUTF8(pair.first);
result.second = toUTF8(pair.second);
return result;
}
public static ArrayList<Pair<byte[], byte[]>> toUTF8(ArrayList<Pair<String, String>> list) {
if (list == null)
return null;
ArrayList<Pair<byte[], byte[]>> result = new ArrayList<Pair<byte[], byte[]>>(list.size());
for (int i=0; i<list.size(); i++)
result.set(i, toUTF8(list.get(i)));
return result;
}
public static String toUTF16(byte[] utf8) {
if (utf8 == null)
return null;
try {
byte newUtf8[] = new byte[utf8.length];
System.arraycopy(utf8,0,newUtf8,0,utf8.length);
return new String(newUtf8, "UTF-8");
}
catch (UnsupportedEncodingException e) {
assert false;
return new String();
}
}
public static Vector<String> toUTF16(Vector<byte[]> list) {
if (list == null)
return null;
Vector<String> result = new Vector<String>(list.size());
for (int i=0; i<list.size(); i++)
result.add(toUTF16(list.get(i)));
return result;
}
public static Pair<String, String> toUTF16(Pair<byte[], byte[]> pair) {
if (pair == null)
return null;
Pair<String, String> result = new Pair<String,String>();
result.first = toUTF16(pair.first);
result.second = toUTF16(pair.second);
return result;
}
public static ArrayList<Pair<String, String>> toUTF16(ArrayList<Pair<byte[], byte[]>> list) {
if (list == null)
return null;
ArrayList<Pair<String, String>> result = new ArrayList<Pair<String, String>>(list.size());
for (int i=0; i<list.size(); i++)
result.set(i, toUTF16(list.get(i)));
return result;
}
}

8
src/foundation/pEp/jniadapter/_Blob.java → src/java/foundation/pEp/jniadapter/_Blob.java

@ -1,5 +1,7 @@
package foundation.pEp.jniadapter;
import foundation.pEp.jniadapter.exceptions.*;
public class _Blob {
public byte[] data;
public byte[] mime_type;
@ -9,13 +11,13 @@ public class _Blob {
private native byte[] _dataToXER() throws pEpException;;
public String dataToXER() {
return AbstractEngine.toUTF16(_dataToXER());
return Utils.toUTF16(_dataToXER());
}
_Blob(Blob b) {
data = b.data;
mime_type = AbstractEngine.toUTF8(b.mime_type);
filename = AbstractEngine.toUTF8(b.filename);
mime_type = Utils.toUTF8(b.mime_type);
filename = Utils.toUTF8(b.filename);
}
}

10
src/foundation/pEp/jniadapter/_Identity.java → src/java/foundation/pEp/jniadapter/_Identity.java

@ -19,12 +19,12 @@ public class _Identity {
}
public _Identity(Identity i) {
address = AbstractEngine.toUTF8(i.address);
fpr = AbstractEngine.toUTF8(i.fpr);
user_id = AbstractEngine.toUTF8(i.user_id);
username = AbstractEngine.toUTF8(i.username);
address = Utils.toUTF8(i.address);
fpr = Utils.toUTF8(i.fpr);
user_id = Utils.toUTF8(i.user_id);
username = Utils.toUTF8(i.username);
comm_type = i.comm_type.value;
lang = AbstractEngine.toUTF8(i.lang);
lang = Utils.toUTF8(i.lang);
me = i.me;
flags = i.flags;
}

7
src/java/foundation/pEp/jniadapter/decrypt_message_Return.java

@ -0,0 +1,7 @@
package foundation.pEp.jniadapter;
public class decrypt_message_Return {
public Message dst;
public Rating rating;
public int flags;
}

30
src/java/foundation/pEp/jniadapter/interfaces/AbstractEngineInterface.java

@ -0,0 +1,30 @@
package foundation.pEp.jniadapter.interfaces;
import foundation.pEp.jniadapter.Message;
import foundation.pEp.jniadapter.Sync;
public interface AbstractEngineInterface extends AutoCloseable {
public String getVersion();
public String getProtocolVersion();
public void startKeyserverLookup();
public void stopKeyserverLookup();
public void startSync();
public void stopSync();
public boolean isSyncRunning();
public void setMessageToSendCallback(Sync.MessageToSendCallback messageToSendCallback);
public void setNotifyHandshakeCallback(Sync.NotifyHandshakeCallback notifyHandshakeCallback);
public void setNeedsFastPollCallback(Sync.NeedsFastPollCallback needsFastPollCallback);
public void setPassphraseRequiredCallback(Sync.PassphraseRequiredCallback passphraseRequiredCallback);
public Message incomingMessageFromPGPText(String pgpText, Message.EncFormat encFormat);
}

5
src/java/foundation/pEp/jniadapter/interfaces/BlobInterface.java

@ -0,0 +1,5 @@
package foundation.pEp.jniadapter.interfaces;
public interface BlobInterface {
}

7
src/java/foundation/pEp/jniadapter/interfaces/IdentityInterface.java

@ -0,0 +1,7 @@
package foundation.pEp.jniadapter.interfaces;
import foundation.pEp.jniadapter.Rating;
public interface IdentityInterface {
public Rating getRating();
}

772
src/jniutils.cc

@ -1,772 +0,0 @@
#include <cassert>
#include "jniutils.hh"
#include <pEp/pEpLog.hh>
#ifndef __LP64__
#include <time64.h>
#define time_t time64_t
#define timegm timegm64
#define gmtime_r gmtime64_r
#else
#include <string.h>
#endif
namespace pEp {
namespace JNIAdapter {
std::mutex global_mutex;
std::unordered_map<long, std::mutex*> engine_objid_mutex;
std::mutex* get_engine_java_object_mutex(
JNIEnv *env,
jobject obj
)
{
long engine_obj_id = (long)callLongMethod(env, obj, "getId");
assert(engine_obj_id);
pEpLog("for java object id: " << engine_obj_id);
std::mutex *engine_obj_mutex = engine_objid_mutex.at(engine_obj_id);
pEpLog("found mutex: " << engine_obj_mutex << " with native_handle: " << engine_obj_mutex->native_handle());
assert(engine_obj_mutex);
return engine_obj_mutex;
}
void create_engine_java_object_mutex(
JNIEnv *env,
jobject obj
)
{
long engine_obj_id = (long)callLongMethod(env, obj, "getId");
assert(engine_obj_id);
std::mutex *engine_obj_mutex = new std::mutex();
pEpLog(engine_obj_mutex << " with native_handle: " << engine_obj_mutex->native_handle() << " for java object id: " << engine_obj_id);
assert(engine_obj_mutex);
if(engine_objid_mutex.count(engine_obj_id) > 0) {
pEpLog("Fatal: mutex already existing for object id: " << engine_obj_id);
assert(0);
}
engine_objid_mutex.insert(std::make_pair(engine_obj_id, engine_obj_mutex ));
}
void release_engine_java_object_mutex(
JNIEnv *env,
jobject obj
)
{
long engine_obj_id = (long)callLongMethod(env, obj, "getId");
assert(engine_obj_id);
std::mutex *engine_obj_mutex = engine_objid_mutex.at(engine_obj_id);
pEpLog(engine_obj_mutex << " with native_handle: " << engine_obj_mutex->native_handle() << " for java object id: " << engine_obj_id);
assert(engine_obj_mutex);
engine_objid_mutex.erase(engine_obj_id);
delete engine_obj_mutex;
}
jclass findClass(JNIEnv *env, const char *classname)
{
jclass clazz = env->FindClass(classname);
if (!clazz)
fprintf(stderr, "class not found: %s\n", classname);
assert(clazz);
if (clazz == NULL) {
jclass ex = env->FindClass("java/lang/NoClassDefFoundError");
assert(ex);
env->ThrowNew(ex, classname);
throw std::bad_cast();
}
return clazz;
}
jfieldID getFieldID(
JNIEnv *env,
const char *classname,
const char *fieldname,
const char *signature
)
{
jclass clazz = findClass(env, classname);
assert(clazz);
jfieldID field = env->GetFieldID(clazz, fieldname, signature);
assert(field);
if (field == NULL) {
jclass ex = env->FindClass("java/lang/NoSuchFieldError");
assert(ex);
env->ThrowNew(ex, fieldname);
throw std::invalid_argument(std::string(fieldname));
}
env->DeleteLocalRef(clazz);
return field;
}
//TODO: fix/generalize/clean patch added to make keysync work using globalref to class
jfieldID getFieldID(
JNIEnv *env,
const char *classname,
const char *fieldname,
const char *signature,
const jclass clazz
)
{
jfieldID field = env->GetFieldID(clazz, fieldname, signature);
assert(field);
if (field == NULL) {
jclass ex = env->FindClass("java/lang/NoSuchFieldError");
assert(ex);
env->ThrowNew(ex, fieldname);
throw std::invalid_argument(std::string(fieldname));
}
return field;
}
jint callIntMethod(
JNIEnv *env,
jobject obj,
const char *methodname
)
{
jclass clazz = env->GetObjectClass(obj);
assert(clazz);
jmethodID method = env->GetMethodID(clazz, methodname, "()I");
if (method == NULL) {
jclass ex = env->FindClass("java/lang/NoSuchMethodError");
assert(ex);
env->ThrowNew(ex, methodname);
throw std::invalid_argument(std::string(methodname));
}
env->DeleteLocalRef(clazz);
jint result = env->CallIntMethod(obj, method);
env->ExceptionCheck(); // handle exception in Java
return result;
}
jlong callLongMethod(
JNIEnv *env,
jobject obj,
const char *methodname
)
{
jclass clazz = env->GetObjectClass(obj);
assert(clazz);
jmethodID method = env->GetMethodID(clazz, methodname, "()J");
if (method == NULL) {
jclass ex = env->FindClass("java/lang/NoSuchMethodError");
assert(ex);
env->ThrowNew(ex, methodname);
throw std::invalid_argument(std::string(methodname));
}
env->DeleteLocalRef(clazz);
jlong result = env->CallLongMethod(obj, method);
env->ExceptionCheck(); // handle exception in Java
return result;
}
jobject callObjectMethod(
JNIEnv *env,
jobject obj,
const char *methodname,
jint index
)
{
jclass clazz = env->GetObjectClass(obj);
assert(clazz);
jmethodID method = env->GetMethodID(clazz, methodname,
"(I)Ljava/lang/Object;");
if (method == NULL) {
jclass ex = env->FindClass("java/lang/NoSuchMethodError");
assert(ex);
env->ThrowNew(ex, methodname);
throw std::invalid_argument(std::string(methodname));
}
env->DeleteLocalRef(clazz);
jobject result = env->CallObjectMethod(obj, method, index);
env->ExceptionCheck(); // handle exception in Java
return result;
}
jboolean callBooleanMethod(
JNIEnv *env,
jobject obj,
const char *methodname,
jobject o
)
{
jclass clazz = env->GetObjectClass(obj);
assert(clazz);
jmethodID method = env->GetMethodID(clazz, methodname,
"(Ljava/lang/Object;)Z");
if (method == NULL) {
jclass ex = env->FindClass("java/lang/NoSuchMethodError");
assert(ex);
env->ThrowNew(ex, methodname);
throw std::invalid_argument(std::string(methodname));
}
env->DeleteLocalRef(clazz);
jboolean result = env->CallBooleanMethod(obj, method, o);
env->ExceptionCheck(); // handle exception in Java
return result;
}
jint outOfMemory(JNIEnv *env)
{
jclass ex;
const char *ex_name = "java/lang/OutOfMemoryError";
ex = env->FindClass(ex_name);
assert(ex);
return env->ThrowNew(ex, ex_name);
}
jobject from_Integer(JNIEnv *env, int val)
{
assert(env);
jclass clazz = findClass(env, "java/lang/Integer");
jmethodID constructor = env->GetMethodID(clazz, "<init>", "(I)V");
assert(constructor);
jobject obj = env->NewObject(clazz, constructor, val);
assert(obj);
return obj;
}
int to_Integer(JNIEnv *env, jobject obj)
{
assert(env && obj);
int _val = callIntMethod(env, obj, "intValue");
return _val;
}
jbyteArray from_string(JNIEnv *env, const char *str)
{
if (str && str[0]) {
jboolean isCopy;
size_t l = strlen(str);
jbyteArray _str = env->NewByteArray(l);
env->SetByteArrayRegion(_str, 0, l, (jbyte*)str);
return _str;
}
else if (str) {
return env->NewByteArray(0);
} else {
return (jbyteArray) NULL;
}
}
char *to_string(JNIEnv *env, jbyteArray str)
{
if (str == NULL)
return NULL;
size_t l = env->GetArrayLength(str);
char *_str = (char *) calloc(1,l+1);
assert(_str);
env->GetByteArrayRegion(str, 0, l, (jbyte*)_str);
return _str;
}
jobject from_stringlist(JNIEnv *env, stringlist_t *sl)
{
if (!sl)
return (jobject) NULL;
jclass clazz = findClass(env, "java/util/Vector");
jmethodID constructor = env->GetMethodID(clazz, "<init>", "()V");
assert(constructor);
jobject obj = env->NewObject(clazz, constructor);
assert(obj);
stringlist_t *_sl;
for (_sl = sl; _sl && _sl->value; _sl = _sl->next) {
jobject o = from_string(env, _sl->value);
callBooleanMethod(env, obj, "add", o);
}
env->DeleteLocalRef(clazz);
return obj;
}
stringlist_t *to_stringlist(JNIEnv *env, jobject obj)
{
if (!obj)
return NULL;
jint size = callIntMethod(env, obj, "size");
if (size == 0)
return NULL;
stringlist_t *sl = new_stringlist(NULL);
stringlist_t *_sl;
jint i;
for (_sl = sl, i = 0; i < (int) size; i++) {
jobject o = callObjectMethod(env, obj, "get", i);
jbyteArray a = reinterpret_cast<jbyteArray>(o);
char * str = to_string(env, a);
_sl = stringlist_add(_sl, str);
env->DeleteLocalRef(o);
free(str);
}
return sl;
}
jobject from_stringpairlist(JNIEnv *env, stringpair_list_t *sl)
{
if (!sl)
return (jobject) NULL;
jclass clazz = findClass(env, "java/util/ArrayList");
jclass clazz_pair = findClass(env, "foundation/pEp/jniadapter/Pair");
jmethodID constructor = env->GetMethodID(clazz, "<init>", "()V");
assert(constructor);
jmethodID constructor_pair = env->GetMethodID(clazz_pair, "<init>",
"(Ljava/lang/Object;Ljava/lang/Object;)V");
assert(constructor_pair);
jobject obj = env->NewObject(clazz, constructor);
assert(obj);
stringpair_list_t *_sl;
for (_sl = sl; _sl && _sl->value; _sl = _sl->next) {
assert(_sl->value->key);
assert(_sl->value->value);
jbyteArray first = from_string(env, _sl->value->key);
jbyteArray second = from_string(env, _sl->value->value);
jobject pair = env->NewObject(clazz_pair, constructor_pair,
first, second);
callBooleanMethod(env, obj, "add", pair);
env->DeleteLocalRef(first);
env->DeleteLocalRef(second);
env->DeleteLocalRef(pair);
}
env->DeleteLocalRef(clazz);
env->DeleteLocalRef(clazz_pair);
return obj;
}
stringpair_list_t *to_stringpairlist(JNIEnv *env, jobject obj)
{
if (!obj)
return NULL;
jint size = callIntMethod(env, obj, "size");
if (size == 0)
return NULL;
jfieldID first_id = getFieldID(env, "foundation/pEp/jniadapter/Pair",
"first", "Ljava/lang/Object;");
jfieldID second_id = getFieldID(env, "foundation/pEp/jniadapter/Pair",
"second", "Ljava/lang/Object;");
stringpair_list_t *sl = new_stringpair_list(NULL);
stringpair_list_t *_sl;
jint i;
for (_sl = sl, i = 0; i < (int) size; i++) {
jobject pair = callObjectMethod(env, obj, "get", i);
jbyteArray first =
reinterpret_cast<jbyteArray>(env->GetObjectField(pair,
first_id));
jbyteArray second =
reinterpret_cast<jbyteArray>(env->GetObjectField(pair,
second_id));
char *first_str = to_string(env, first);
char *second_str = to_string(env, second);
stringpair_t *sp = new_stringpair(first_str, second_str);
env->DeleteLocalRef(pair);
free(first_str);
free(second_str);
_sl = stringpair_list_add(_sl, sp);
}
return sl;
}
jobject from_timestamp(JNIEnv *env, timestamp *ts)
{
if (!ts)
return (jobject) NULL;
//LOGD("/* Seconds (0-60) */ FROM :%d", ts->tm_sec);
//LOGD("/* Minutes (0-59) */ :%d", ts->tm_min);
//LOGD("/* Hours (0-23) */ :%d", ts->tm_hour);
//LOGD("/* Day of the month (1-31) */:%d", ts->tm_mday);
//LOGD("/* Month (0-11) */ :%d", ts->tm_mon);
//LOGD("/* Year - 1900 */ :%d", ts->tm_year);
time_t t = timegm(ts)*1000;
//LOGD( "TimeGM returns : %lld", t);
jclass clazz = findClass(env, "java/util/Date");
jmethodID constructor = env->GetMethodID(clazz, "<init>", "(J)V");
assert(constructor);
jobject result = env->NewObject(clazz, constructor, (jlong) t);
env->DeleteLocalRef(clazz);
return result;
}
timestamp *to_timestamp(JNIEnv *env, jobject date)
{
if (!date)
return NULL;
jlong t = callLongMethod(env, date, "getTime");
//LOGD( "Set Time to : %lld", t);
timestamp *ts = (timestamp*)calloc(1, sizeof(timestamp));
assert(ts);
if (ts == NULL)
return NULL;
if (t){
time_t clock = t/1000;
gmtime_r(&clock, ts);
//LOGD("/* Seconds (0-60) */ TO :%d", ts->tm_sec);
//LOGD("/* Minutes (0-59) */ :%d", ts->tm_min);
//LOGD("/* Hours (0-23) */ :%d", ts->tm_hour);
//LOGD("/* Day of the month (1-31) */:%d", ts->tm_mday);
//LOGD("/* Month (0-11) */ :%d", ts->tm_mon);
//LOGD("/* Year - 1900 */ :%d", ts->tm_year);
}
return ts;
}
static void _setStringField(JNIEnv *env, const char *classname,
jobject obj, const char *name, const char *value)
{
if (value) {
jfieldID fieldID = getFieldID(env, classname, name, "[B");
env->SetObjectField(obj, fieldID,
reinterpret_cast<jobject>(from_string(env, value)));
}
}
//TODO: fix/generalize/clean patch added to make keysync work using globalref to class
static void _setStringField(JNIEnv *env, const char *classname,
jobject obj, const char *name, const char *value, const jclass clazz)
{
if (value) {
jfieldID fieldID = getFieldID(env, classname, name, "[B", clazz);
env->SetObjectField(obj, fieldID,
reinterpret_cast<jobject>(from_string(env, value)));
}
}
jobject from_identity(JNIEnv *env, pEp_identity *ident)
{
if (!ident)
return (jobject) NULL;
static const char *classname = "foundation/pEp/jniadapter/_Identity";
jclass clazz = findClass(env, classname);
jmethodID constructor = env->GetMethodID(clazz, "<init>", "()V");
assert(constructor);
jobject obj = env->NewObject(clazz, constructor);
env->DeleteLocalRef(clazz);
if (ident) {
_setStringField(env, classname, obj, "address", ident->address);
_setStringField(env, classname, obj, "fpr", ident->fpr);
_setStringField(env, classname, obj, "user_id", ident->user_id);
_setStringField(env, classname, obj, "username", ident->username);
jfieldID comm_type_id = getFieldID(env, classname, "comm_type", "I");
env->SetIntField(obj, comm_type_id, (jint) (int) ident->comm_type);
_setStringField(env, classname, obj, "lang", ident->lang);
jfieldID me_id = getFieldID(env, classname, "me", "Z");
env->SetBooleanField(obj, me_id, (jboolean) ident->me);
jfieldID flags_id = getFieldID(env, classname, "flags", "I");
env->SetIntField(obj, flags_id, (jint) (int) ident->flags);
}
return obj;
}
//TODO: fix/generalize/clean patch added to make keysync work using globalref to class
jobject from_identity(JNIEnv *env, pEp_identity *ident, jclass identityClass)
{
if (!ident)
return (jobject) NULL;
static const char *classname = "foundation/pEp/jniadapter/_Identity";
jmethodID constructor = env->GetMethodID(identityClass, "<init>", "()V");
assert(constructor);
jobject obj = env->NewObject(identityClass, constructor);
if (ident) {
_setStringField(env, classname, obj, "address", ident->address, identityClass);
_setStringField(env, classname, obj, "fpr", ident->fpr, identityClass);
_setStringField(env, classname, obj, "user_id", ident->user_id, identityClass);
_setStringField(env, classname, obj, "username", ident->username, identityClass);
jfieldID comm_type_id = getFieldID(env, classname, "comm_type", "I", identityClass);
env->SetIntField(obj, comm_type_id, (jint) (int) ident->comm_type);
_setStringField(env, classname, obj, "lang", ident->lang, identityClass);
jfieldID me_id = getFieldID(env, classname, "me", "Z", identityClass);
env->SetBooleanField(obj, me_id, (jboolean) ident->me);
jfieldID flags_id = getFieldID(env, classname, "flags", "I", identityClass);
env->SetIntField(obj, flags_id, (jint) (int) ident->flags);
}
return obj;
}
char *_getStringField(JNIEnv *env, const char *classname, jobject obj,
const char *name)
{
jfieldID fieldID = getFieldID(env, classname, name, "[B");
jobject fobj = env->GetObjectField(obj, fieldID);
char *res = to_string(env, reinterpret_cast<jbyteArray>(fobj));
env->DeleteLocalRef(fobj);
return res;
}
pEp_identity *to_identity(JNIEnv *env, jobject obj)
{
if (!obj)
return NULL;
static const char *classname = "foundation/pEp/jniadapter/_Identity";
pEp_identity *ident = new_identity(NULL, NULL, NULL, NULL);
ident->address = _getStringField(env, classname, obj, "address");
ident->fpr = _getStringField(env, classname, obj, "fpr");
ident->user_id = _getStringField(env, classname, obj, "user_id");
ident->username = _getStringField(env, classname, obj, "username");
jfieldID comm_type_id = getFieldID(env, classname, "comm_type", "I");
ident->comm_type = (PEP_comm_type) (int) env->GetIntField(obj, comm_type_id);
char *lang = _getStringField(env, classname, obj, "lang");
if (lang && lang[0]) {
ident->lang[0] = lang[0];
ident->lang[1] = lang[1];
}
free(lang);
jfieldID me_id = getFieldID(env, classname, "me", "Z");
ident->me = (bool) env->GetBooleanField(obj, me_id);
jfieldID flags_id = getFieldID(env, classname, "flags", "I");
ident->flags = (identity_flags_t) (int) env->GetIntField(obj, flags_id);
return ident;
}
jobject from_identitylist(JNIEnv *env, identity_list *il)
{
if (!il)
return (jobject) NULL;
jclass clazz = findClass(env, "java/util/Vector");
jmethodID constructor = env->GetMethodID(clazz, "<init>", "()V");
assert(constructor);
jobject obj = env->NewObject(clazz, constructor);
assert(obj);
identity_list *_il;
for (_il = il; _il && _il->ident; _il = _il->next) {
jobject o = from_identity(env, _il->ident);
callBooleanMethod(env, obj, "add", o);
}
env->DeleteLocalRef(clazz);
return obj;
}
identity_list *to_identitylist(JNIEnv *env, jobject obj)
{
if (!obj)
return NULL;
jint size = callIntMethod(env, obj, "size");
if (size == 0)
return NULL;
identity_list *il = new_identity_list(NULL);
identity_list *_il;
jint i;
for (_il = il, i = 0; i < (int) size; i++) {
jobject o = callObjectMethod(env, obj, "get", i);
pEp_identity* ident = to_identity(env, o);
_il = identity_list_add(_il, ident);
env->DeleteLocalRef(o);
}
return il;
}
jobject _from_blob(JNIEnv *env, bloblist_t *b)
{
if (!b)
return (jobject) NULL;
static const char *classname = "foundation/pEp/jniadapter/_Blob";
jclass clazz = findClass(env, classname);
jmethodID constructor = env->GetMethodID(clazz, "<init>", "()V");
assert(constructor);
jobject obj = env->NewObject(clazz, constructor);
env->DeleteLocalRef(clazz);
jfieldID fieldID = getFieldID(env, classname, "data", "[B");
jbyteArray _data = env->NewByteArray((jsize) b->size);
env->SetByteArrayRegion(_data, 0, b->size, (jbyte*)b->value);
env->SetObjectField(obj, fieldID, reinterpret_cast<jobject>(_data));
_setStringField(env, classname, obj, "mime_type", b->mime_type);
_setStringField(env, classname, obj, "filename", b->filename);
return obj;
}
jobject from_bloblist(JNIEnv *env, bloblist_t *bl)
{
if (!bl)
return (jobject) NULL;
jclass clazz = findClass(env, "java/util/Vector");
jmethodID constructor = env->GetMethodID(clazz, "<init>", "()V");
assert(constructor);
jobject obj = env->NewObject(clazz, constructor);
assert(obj);
env->DeleteLocalRef(clazz);
bloblist_t *_bl;
for (_bl = bl; _bl && _bl->value; _bl = _bl->next) {
jobject o = _from_blob(env, _bl);
if(o)
callBooleanMethod(env, obj, "add", o);
}
return obj;
}
bloblist_t *to_blob(JNIEnv *env, jobject obj)
{
if (!obj)
return NULL;
static const char *classname = "foundation/pEp/jniadapter/_Blob";
jclass clazz = findClass(env, classname);
char *mime_type = _getStringField(env, classname, obj, "mime_type");
char *filename = _getStringField(env, classname, obj, "filename");
jfieldID data_id = getFieldID(env, classname, "data", "[B");
jbyteArray _data = reinterpret_cast<jbyteArray>(env->GetObjectField(obj, data_id));
size_t size = (size_t) env->GetArrayLength(_data);
char *b = (char *) malloc(size);
assert(b);
env->GetByteArrayRegion(_data, 0, size, (jbyte*)b);
bloblist_t *bl = new_bloblist( b, size, mime_type, filename);
free(mime_type);
free(filename);
return bl;
}
bloblist_t *to_bloblist(JNIEnv *env, jobject obj)
{
if (!obj)
return NULL;
jint size = callIntMethod(env, obj, "size");
if (size == 0)
return NULL;
bloblist_t *bl = new_bloblist(NULL, 0, NULL, NULL);
bloblist_t *_bl;
_bl = bl;
jint i;
for (i = 0; i < (int) size; i++) {
jobject o = callObjectMethod(env, obj, "get", i);
bloblist_t *b = to_blob(env, o);
_bl = bloblist_add(_bl, b->value, b->size, b->mime_type, b->filename);
env->DeleteLocalRef(o);
}
return bl;
}
PEP_enc_format to_EncFormat(JNIEnv *env, jobject obj)
{
static const char *classname = "foundation/pEp/jniadapter/Message$EncFormat";
jclass clazz_enc_format = findClass(env, classname);
jfieldID field_value = env->GetFieldID(clazz_enc_format, "value", "I");
assert(field_value);
env->DeleteLocalRef(clazz_enc_format);
return (PEP_enc_format) env->GetIntField(obj, field_value);
}
PEP_CIPHER_SUITE to_CipherSuite(JNIEnv *env, jobject obj)
{
static const char *classname = "foundation/pEp/jniadapter/CipherSuite";
jclass clazz_enc_format = findClass(env, classname);
jfieldID field_value = env->GetFieldID(clazz_enc_format, "value", "I");
assert(field_value);
env->DeleteLocalRef(clazz_enc_format);
return (PEP_CIPHER_SUITE) env->GetIntField(obj, field_value);
}
sync_handshake_result to_SyncHandshakeResult(JNIEnv *env, jobject obj)
{
static const char *classname = "foundation/pEp/jniadapter/SyncHandshakeResult";
jclass clazz_enc_format = findClass(env, classname);
jfieldID field_value = env->GetFieldID(clazz_enc_format, "value", "I");
assert(field_value);
env->DeleteLocalRef(clazz_enc_format);
return (sync_handshake_result) env->GetIntField(obj, field_value);
}
};
};

130
src/jniutils.hh

@ -1,130 +0,0 @@
#pragma once
#include <unordered_map>
#include <thread>
#include <mutex>
#include <jni.h>
#include <pEp/stringpair.h>
#include <pEp/identity_list.h>
#include <pEp/bloblist.h>
#include <pEp/message.h>
#include <pEp/sync_api.h>
#include <pEp/passphrase_cache.hh>
#if 0 // Enable if log needed
#include <android/log.h>
#define LOG_TAG "pEpJNIAdapter"
#define LOGD(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#else
#define LOGD(...) do{}while(0)
#endif
namespace pEp {
namespace JNIAdapter {
// Global mutex needs to be locked in all constructors which insert their own mutex object
// into the unordered_map (which is thread safe for read, but not for write)
extern std::mutex global_mutex;
// Stores mutex per java object
extern std::unordered_map<long, std::mutex*> engine_objid_mutex;
// needs to be called after create_engine_java_object_mutex()
// and before release_engine_java_object_mutex()
// Thread safe
std::mutex* get_engine_java_object_mutex(
JNIEnv *env,
jobject me
);
// Needs to be called exactly once per obj, in the constructor of the obj
// You need to lock a global mutex before calling this function (write to unordered_map)
void create_engine_java_object_mutex(
JNIEnv *env,
jobject me
);
// Needs to be called exactly once per obj, in the destructor of this obj
// You need to lock a global mutex before calling this function (write to unordered_map)
void release_engine_java_object_mutex(
JNIEnv *env,
jobject me
);
jclass findClass(JNIEnv *env, const char *classname);
jfieldID getFieldID(
JNIEnv *env,
const char *classname,
const char *fieldname,
const char *signature
);
jfieldID getFieldID(
JNIEnv *env,
const char *classname,
const char *fieldname,
const char *signature,
const jclass clazz
);
jint callIntMethod(
JNIEnv *env,
jobject obj,
const char *methodname
);
jlong callLongMethod(
JNIEnv *env,
jobject obj,
const char *methodname
);
jobject callObjectMethod(
JNIEnv *env,
jobject obj,
const char *methodname,
jint index
);
jboolean callBooleanMethod(
JNIEnv *env,
jobject obj,
const char *methodname,
jobject o
);
jint outOfMemory(JNIEnv *env);
jobject from_Integer(JNIEnv *env, int val);
int to_Integer(JNIEnv *env, jobject obj);
jbyteArray from_string(JNIEnv *env, const char *str);
char *to_string(JNIEnv *env, jbyteArray str);
jobject from_stringlist(JNIEnv *env, stringlist_t *sl);
stringlist_t *to_stringlist(JNIEnv *env, jobject obj);
jobject from_stringpairlist(JNIEnv *env, stringpair_list_t *sl);
stringpair_list_t *to_stringpairlist(JNIEnv *env, jobject obj);
jobject from_timestamp(JNIEnv *env, timestamp *ts);
timestamp *to_timestamp(JNIEnv *env, jobject date);
jobject from_identity(JNIEnv *env, pEp_identity *ident);
jobject from_identity(JNIEnv *env, pEp_identity *ident, jclass identityClass);
pEp_identity *to_identity(JNIEnv *env, jobject obj);
jobject from_identitylist(JNIEnv *env, identity_list *il);
identity_list *to_identitylist(JNIEnv *env, jobject obj);
jobject from_bloblist(JNIEnv *env, bloblist_t *bl);
bloblist_t *to_blob(JNIEnv *env, jobject obj);
bloblist_t *to_bloblist(JNIEnv *env, jobject obj);
PEP_enc_format to_EncFormat(JNIEnv *env, jobject obj);
PEP_CIPHER_SUITE to_CipherSuite(JNIEnv *env, jobject obj);
sync_handshake_result to_SyncHandshakeResult(JNIEnv *env, jobject obj);
};
};

14
src/passphrase_callback.hh

@ -1,14 +0,0 @@
#pragma once
#include <pEp/passphrase_cache.hh>
namespace pEp {
namespace JNIAdapter {
char* passphraseRequiredCallback(const PEP_STATUS status);
template<typename... A> PEP_STATUS passphraseWrap(PEP_STATUS f(PEP_SESSION, A...), PEP_SESSION session, A... a);
}
}
#include "passphrase_callback.hxx"

42
src/passphrase_callback.hxx

@ -1,42 +0,0 @@
#pragma once
#include "passphrase_callback.hh"
namespace pEp {
namespace JNIAdapter {
template<typename... A> PEP_STATUS passphraseWrap(PEP_STATUS f(PEP_SESSION, A...), PEP_SESSION session, A... a) {
pEpLog("cached passphrase mode");
bool retryAgain = false;
int maxRetries = 3;
int retryCount = 0;
PEP_STATUS status;
do {
// the actual target function
pEpLog("calling passphrase_cache.api from basic_api");
status = passphrase_cache.api(f, session, a...);
pEpLog("PEP_STATUS:" << status);
if (status == PEP_PASSPHRASE_REQUIRED ||
status == PEP_WRONG_PASSPHRASE ||
status == PEP_PASSPHRASE_FOR_NEW_KEYS_REQUIRED)
{
pEpLog("none of the cached passphrases worked");
if (retryCount < maxRetries) {
// call the app
char *_passphrase = passphraseRequiredCallback(status);
pEpLog("callback returned, config_passphrase() with new passphrase");
PEP_STATUS status = ::config_passphrase(session, passphrase_cache.add(_passphrase));
retryAgain = true;
retryCount++;
} else {
pEpLog("max retries reached:" << maxRetries);
retryAgain = false;
}
} else {
retryAgain = false;
}
} while (retryAgain);
return status;
}
}
}

5
test/java/foundation/pEp/jniadapter/test/Makefile

@ -7,6 +7,7 @@ run: compile
$(MAKE) -C templateAliceBob run
$(MAKE) -C basic run
$(MAKE) -C regression run
$(MAKE) -C speedtest run
$(MAKE) -C jni88 run
$(MAKE) -C jni91 run
$(MAKE) -C jni92 run
@ -17,6 +18,7 @@ run: compile
$(MAKE) -C jni111 run
$(MAKE) -C jni114 run
$(MAKE) -C jni115 run
$(MAKE) -C jni118 run
$(MAKE) -C jni125 run
compile:
@ -24,6 +26,7 @@ compile:
$(MAKE) -C templateAliceBob compile
$(MAKE) -C basic compile
$(MAKE) -C regression compile
$(MAKE) -C speedtest compile
$(MAKE) -C jni88 compile
$(MAKE) -C jni91 compile
$(MAKE) -C jni92 compile
@ -34,6 +37,7 @@ compile:
$(MAKE) -C jni111 compile
$(MAKE) -C jni114 compile
$(MAKE) -C jni115 compile
$(MAKE) -C jni118 compile
$(MAKE) -C jni125 compile
clean:
@ -41,6 +45,7 @@ clean:
$(MAKE) -C templateAliceBob clean
$(MAKE) -C basic clean
$(MAKE) -C regression clean
$(MAKE) -C speedtest clean
$(MAKE) -C jni88 clean
$(MAKE) -C jni91 clean
$(MAKE) -C jni92 clean

6
test/java/foundation/pEp/jniadapter/test/Makefile.conf

@ -1,6 +1,7 @@
JAVA_PKG_BASENAME=foundation.pEp.jniadapter.test
JAVA_PKG_BASEPATH=foundation/pEp/jniadapter/test
REPOROOT=../..
DIST_DIR=$(REPOROOT)/dist
JAVA_CWD=../../../../../
JAVA_RESOURCES_DIR=../resources
@ -14,9 +15,10 @@ PEP_HOME_DIR_BOB=$(JAVA_CWD)$(JAVA_PEP_HOME_DIR_BOB)
PEP_HOME_DIR_CAROL=$(JAVA_CWD)$(JAVA_PEP_HOME_DIR_CAROL)
PEP_HOME_DIR=$(PEP_HOME_DIR_ALICE)
CLASSPATH=.:$(REPOROOT)/src
CLASSPATH=.:$(DIST_DIR)/pEp.jar
LD_LIB_PATH=.:$(DIST_DIR)
JAVA=java -enableassertions -Xcheck:jni -cp $(CLASSPATH) -Djava.library.path=$(CLASSPATH)
JAVA=java -enableassertions -Xcheck:jni -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 -cp $(CLASSPATH) -Djava.library.path=$(LD_LIB_PATH)
PITYTEST_DIR=../../../pitytest

13
test/java/foundation/pEp/jniadapter/test/basic/TestMain.java

@ -1,13 +1,13 @@
package foundation.pEp.jniadapter.test.basic;
import foundation.pEp.jniadapter.Blob;
import foundation.pEp.jniadapter.Engine;
import foundation.pEp.jniadapter.Identity;
import foundation.pEp.jniadapter.Message;
import foundation.pEp.pitytest.TestSuite;
import foundation.pEp.pitytest.TestUnit;
import foundation.pEp.jniadapter.decrypt_message_Return;
import foundation.pEp.jniadapter.test.utils.AdapterBaseTestContext;
import foundation.pEp.jniadapter.test.utils.AdapterTestUtils;
import foundation.pEp.pitytest.TestSuite;
import foundation.pEp.pitytest.TestUnit;
import java.util.Vector;
@ -15,11 +15,16 @@ import static foundation.pEp.pitytest.TestLogger.log;
class BasicTestContext extends AdapterBaseTestContext {
Message enc;
Engine.decrypt_message_Return result;
decrypt_message_Return result;
public BasicTestContext() {
setTestContextName("BasicTestContext");
}
public BasicTestContext init() throws Throwable{
super.init();
return this;
}
}
class TestMain {

4
test/java/foundation/pEp/jniadapter/test/jni100/TestMain.java

@ -3,6 +3,8 @@ import foundation.pEp.pitytest.*;
import foundation.pEp.jniadapter.*;
import foundation.pEp.jniadapter.test.utils.*;
import java.util.Vector;
class TestMain {
public static void main(String[] args) throws Exception {
@ -15,7 +17,7 @@ class TestMain {
ctx.alice = ctx.engine.myself(ctx.alice);
TestLogger.log(AdapterTestUtils.identityToString(ctx.alice, true));
Message msg1 = ctx.engine.encrypt_message(ctx.msgToBob, ctx.vStr, Message.EncFormat.PEP);
Message msg1 = ctx.engine.encrypt_message(ctx.msgToBob, new Vector<String>(), Message.EncFormat.PEP);
ctx.engine.key_reset_all_own_keys();

20
test/java/foundation/pEp/jniadapter/test/jni111/TestAlice.java

@ -1,24 +1,30 @@
package foundation.pEp.jniadapter.test.jni111;
import static foundation.pEp.pitytest.TestLogger.*;
import static foundation.pEp.pitytest.utils.TestUtils.readKey;
import foundation.pEp.jniadapter.*;
import foundation.pEp.pitytest.*;
import foundation.pEp.jniadapter.CommType;
import foundation.pEp.jniadapter.Message;
import foundation.pEp.jniadapter.exceptions.pEpException;
import foundation.pEp.jniadapter.exceptions.pEpPassphraseRequired;
import foundation.pEp.jniadapter.exceptions.pEpWrongPassphrase;
import foundation.pEp.jniadapter.test.utils.AdapterBaseTestContext;
import foundation.pEp.jniadapter.test.utils.AdapterTestUtils;
import foundation.pEp.pitytest.TestSuite;
import foundation.pEp.pitytest.TestUnit;
import foundation.pEp.pitytest.utils.TestUtils;
import foundation.pEp.jniadapter.test.utils.*;
import java.util.Vector;
import static foundation.pEp.pitytest.TestLogger.log;
// https://pep.foundation/jira/browse/JNI-111
class JNI111TestContext extends AdapterBaseTestContext {
@Override
public void init() throws Throwable {
public JNI111TestContext init() throws Throwable {
super.init();
alice = null;
bob = null;
return this;
}
}

1
test/java/foundation/pEp/jniadapter/test/jni114/TestAlice.java

@ -5,6 +5,7 @@ import static foundation.pEp.pitytest.utils.TestUtils.readKey;
import static foundation.pEp.pitytest.utils.TestUtils.sleep;
import foundation.pEp.jniadapter.*;
import foundation.pEp.jniadapter.exceptions.*;
import foundation.pEp.pitytest.*;
import foundation.pEp.pitytest.utils.TestUtils;
import foundation.pEp.jniadapter.test.utils.*;

15
test/java/foundation/pEp/jniadapter/test/jni115/TestAlice.java

@ -1,16 +1,18 @@
package foundation.pEp.jniadapter.test.jni115;
import static foundation.pEp.pitytest.TestLogger.*;
import foundation.pEp.jniadapter.Message;
import foundation.pEp.pitytest.*;
import foundation.pEp.jniadapter.test.utils.AdapterBaseTestContext;
import foundation.pEp.jniadapter.test.utils.AdapterTestUtils;
import foundation.pEp.pitytest.TestSuite;
import foundation.pEp.pitytest.TestUnit;
import foundation.pEp.pitytest.utils.TestUtils;
import foundation.pEp.jniadapter.test.utils.*;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import static foundation.pEp.pitytest.TestLogger.log;
import static foundation.pEp.pitytest.TestLogger.logRaw;
class Jni115TestContext extends AdapterBaseTestContext {
public int messagesToBobCount = 10;
public List<Message> messagesToBobSmall;
@ -19,7 +21,7 @@ class Jni115TestContext extends AdapterBaseTestContext {
public List<Message> messagesToBob;
@Override
public void init() throws Throwable {
public Jni115TestContext init() throws Throwable {
super.init();
messagesToBobSmall = new ArrayList<>();
messagesToBobBig = new ArrayList<>();
@ -52,6 +54,7 @@ class Jni115TestContext extends AdapterBaseTestContext {
messagesToBobHuge.add(tmp);
}
logRaw("\n");
return this;
}
}

37
test/java/foundation/pEp/jniadapter/test/jni117/Makefile

@ -0,0 +1,37 @@
include ../../../../../../../Makefile.conf
include ../Makefile.conf
TEST_UNIT_NAME=jni117
JAVA_CLASSES = \
TestAlice.class \
../utils/AdapterBaseTestContext.class \
../utils/AdapterTestUtils.class \
../utils/TestCallbacks.class
.PHONY: pitytest compile alice test clean
all: alice compile
pitytest:
$(MAKE) -C $(PITYTEST_DIR)
alice: compile clean-pep-home-alice
cd $(JAVA_CWD);pwd;HOME=$(JAVA_PEP_HOME_DIR_ALICE) $(JAVA) $(JAVA_PKG_BASENAME).$(TEST_UNIT_NAME).TestAlice
compile: $(JAVA_CLASSES) pitytest
%.class: %.java
cd $(JAVA_CWD);$(JAVAC_CMD) -cp $(CLASSPATH) $(JAVA_PKG_BASEPATH)/$(TEST_UNIT_NAME)/$<
clean:
rm -f $(JAVA_CLASSES)
rm -f *.class
rm -f *.log
rm -Rf .gnupg
rm -Rf .lldb
clean-pep-home: clean-pep-home-alice
clean-pep-home-alice:
rm -rf $(PEP_HOME_DIR_ALICE)/.pEp

34
test/java/foundation/pEp/jniadapter/test/jni117/TestAlice.java

@ -0,0 +1,34 @@
package foundation.pEp.jniadapter.test.jni117;
import foundation.pEp.jniadapter.test.utils.AdapterBaseTestContext;
import foundation.pEp.pitytest.TestSuite;
import foundation.pEp.pitytest.TestUnit;
import foundation.pEp.pitytest.utils.TestUtils;
import static foundation.pEp.pitytest.TestLogger.log;
// Test for JNI-117 - Key Export
// Tests: For an ad-hoc generated identity "alice" using myself()"
// - export_key is not throwing
// - keydata returned is longer than 100 bytes
// - keydata contains header: "-----BEGIN PGP PBLIC KEY BLOCK-----"
class TestAlice {
public static void main(String[] args) throws Exception {
TestSuite.getDefault().setVerbose(true);
TestSuite.getDefault().setTestColor(TestUtils.TermColor.GREEN);
new TestUnit<AdapterBaseTestContext>("Test Alice",new AdapterBaseTestContext() , ctx -> {
ctx.alice = ctx.engine.myself(ctx.alice);
byte[] keydata = ctx.engine.export_key(ctx.alice.fpr);
String keydataStr = new String(keydata);
log(keydataStr);
assert keydata.length > 100: "returned keydata is too short";
assert keydataStr.contains("-----BEGIN PGP PUBLIC KEY BLOCK-----") : "Keydata doesnt contain: -----BEGIN PGP PBLIC KEY BLOCK-----";
});
TestSuite.getDefault().run();
}
}

37
test/java/foundation/pEp/jniadapter/test/jni118/Makefile

@ -0,0 +1,37 @@
include ../../../../../../../Makefile.conf
include ../Makefile.conf
TEST_UNIT_NAME=jni118
JAVA_CLASSES = \
TestAlice.class \
../utils/AdapterBaseTestContext.class \
../utils/AdapterTestUtils.class \
../utils/TestCallbacks.class
.PHONY: pitytest compile alice test clean
all: alice compile
pitytest:
$(MAKE) -C $(PITYTEST_DIR)
alice: compile clean-pep-home-alice
cd $(JAVA_CWD);pwd;HOME=$(JAVA_PEP_HOME_DIR_ALICE) $(JAVA) $(JAVA_PKG_BASENAME).$(TEST_UNIT_NAME).TestAlice
compile: $(JAVA_CLASSES) pitytest
%.class: %.java
cd $(JAVA_CWD);$(JAVAC_CMD) -cp $(CLASSPATH) $(JAVA_PKG_BASEPATH)/$(TEST_UNIT_NAME)/$<
clean:
rm -f $(JAVA_CLASSES)
rm -f *.class
rm -f *.log
rm -Rf .gnupg
rm -Rf .lldb
clean-pep-home: clean-pep-home-alice
clean-pep-home-alice:
rm -rf $(PEP_HOME_DIR_ALICE)/.pEp

107
test/java/foundation/pEp/jniadapter/test/jni118/TestAlice.java

@ -0,0 +1,107 @@
package foundation.pEp.jniadapter.test.jni118;
import static foundation.pEp.pitytest.TestLogger.*;
import foundation.pEp.jniadapter.*;
import foundation.pEp.pitytest.*;
import foundation.pEp.pitytest.utils.TestUtils;
import foundation.pEp.jniadapter.test.utils.*;
import java.util.ArrayList;
import java.util.Vector;
// re_evaluate_message_rating(Message m)
// needs a msg that holds the OptFields:
// * X-EncStatus - containing the pEpEngine internal string value of the rating
// * X-KeyList - containing the FPR's of all the receivers of the msg
//
// Handling of PEP_Rating
// When app needs to add optional fields like X-EncStatus, the value has to be the string rep for a rating.
// These internal string representations can be obtained with the method:
// * Rating.getInternalStringValue() - returning the pEpEngine internal string value
// For human readable description of all the enums, use:
// * Rating.toString()
//
// A convenience method Message.addRatingToOptFields(Rating r) would be desirable
//
// X-KeyList
// New method to generate X-Keylist formatted FPR list:
// * String Identity.toXKeyList(List<Identity> ids)
//
// A convenience method for adding X-KeyList for a message would be desirable
// * method Message.addIdentitiesToOptFields()
// Test objectives
// re_evaluate_message_rating() equal to decrypt_message_result.rating when Message has correct OptFields
// re_evaluate_message_rating() equal to decrypt_message_result.rating when Message has random rating string on XEncStatus
class JNI1118Context extends AdapterBaseTestContext {
public Message msgToBobEncrypted;
public Message msgToBobDecrypted;
public decrypt_message_Return msgToBobDecryptResult;
@Override
public JNI1118Context init() throws Throwable {
super.init();
alice = engine.myself(alice);
engine.importKey(keyBobPub);
Vector<Identity> msgToBobRcpts = new Vector<>();
msgToBobRcpts.add(bob);
msgToBob.setTo(msgToBobRcpts);
msgToBobEncrypted = engine.encrypt_message(msgToBob, null, Message.EncFormat.PEP);
msgToBobDecrypted = msgToBobEncrypted;
msgToBobDecryptResult = engine.decrypt_message(msgToBobDecrypted, new Vector<String>(), 0);
if (msgToBobEncrypted == null) {
throw new RuntimeException("Context failure, error decrypting message");
}
return this;
}
public void addRatingToOptFields(Message msg, String ratingStr) {
ArrayList<Pair<String, String>> opts = msg.getOptFields();
opts.add(new Pair<String, String>("X-EncStatus",ratingStr));
msg.setOptFields(opts);
}
public void addRcptsToOptFields(Message msg, String fprs) {
ArrayList<Pair<String, String>> opts = msg.getOptFields();
opts.add(new Pair<String, String>("X-KeyList", fprs));
msg.setOptFields(opts);
}
}
class TestAlice {
public static void main(String[] args) throws Throwable {
TestSuite.getDefault().setVerbose(true);
TestSuite.getDefault().setTestColor(TestUtils.TermColor.GREEN);
new TestUnit<JNI1118Context>("re_evaluate_message_rating() equal to decrypt_message_result.rating when Message has correct OptFields", new JNI1118Context(), ctx -> {
ctx.addRatingToOptFields(ctx.msgToBobDecrypted,ctx.msgToBobDecryptResult.rating.getInternalStringValue());
ctx.addRcptsToOptFields(ctx.msgToBobDecrypted,Identity.toXKeyList(ctx.msgToBobDecrypted.getTo()));
log("running re_evaluate_message_rating() on:\n" + AdapterTestUtils.msgToString(ctx.msgToBobDecrypted, false));
Rating rat = ctx.engine.re_evaluate_message_rating(ctx.msgToBobDecrypted);
log("re_evaluate_message_rating() result: " + rat.toString());
assert rat == ctx.msgToBobDecryptResult.rating : "Rating is " + rat.toString() + ",but should be " + ctx.msgToBobDecryptResult.rating.toString();
});
new TestUnit<JNI1118Context>("re_evaluate_message_rating() equal to decrypt_message_result.rating when Message has random rating string on XEncStatus", new JNI1118Context(), ctx -> {
ctx.addRatingToOptFields(ctx.msgToBobDecrypted, TestUtils.randomASCIIString(TestUtils.CharClass.Unbounded, TestUtils.randomInt(0,42)));
ctx.addRcptsToOptFields(ctx.msgToBobDecrypted,Identity.toXKeyList(ctx.msgToBobDecrypted.getTo()));
log("running re_evaluate_message_rating() on:\n" + AdapterTestUtils.msgToString(ctx.msgToBobDecrypted, false));
Rating rat = ctx.engine.re_evaluate_message_rating(ctx.msgToBobDecrypted);
log("re_evaluate_message_rating() result: " + rat.toString());
assert rat == ctx.msgToBobDecryptResult.rating : "Rating is " + rat.toString() + ",but should be " + ctx.msgToBobDecryptResult.rating.toString();
});
TestSuite.getDefault().run();
}
}

37
test/java/foundation/pEp/jniadapter/test/jni119/Makefile

@ -0,0 +1,37 @@
include ../../../../../../../Makefile.conf
include ../Makefile.conf
TEST_UNIT_NAME=jni119
JAVA_CLASSES = \
TestAlice.class \
../utils/AdapterBaseTestContext.class \
../utils/AdapterTestUtils.class \
../utils/TestCallbacks.class
.PHONY: pitytest compile alice test clean
all: alice compile
pitytest:
$(MAKE) -C $(PITYTEST_DIR)
alice: compile clean-pep-home-alice
cd $(JAVA_CWD);pwd;HOME=$(JAVA_PEP_HOME_DIR_ALICE) $(JAVA) $(JAVA_PKG_BASENAME).$(TEST_UNIT_NAME).TestAlice
compile: $(JAVA_CLASSES) pitytest
%.class: %.java
cd $(JAVA_CWD);$(JAVAC_CMD) -cp $(CLASSPATH) $(JAVA_PKG_BASEPATH)/$(TEST_UNIT_NAME)/$<
clean:
rm -f $(JAVA_CLASSES)
rm -f *.class
rm -f *.log
rm -Rf .gnupg
rm -Rf .lldb
clean-pep-home: clean-pep-home-alice
clean-pep-home-alice:
rm -rf $(PEP_HOME_DIR_ALICE)/.pEp

37
test/java/foundation/pEp/jniadapter/test/jni119/TestAlice.java

@ -0,0 +1,37 @@
package foundation.pEp.jniadapter.test.jni119;
import foundation.pEp.jniadapter.Identity;
import foundation.pEp.jniadapter.test.utils.AdapterBaseTestContext;
import foundation.pEp.pitytest.TestSuite;
import foundation.pEp.pitytest.TestUnit;
import foundation.pEp.pitytest.utils.TestUtils;
import java.util.Vector;
class TestAlice {
public static void main(String[] args) throws Throwable {
TestSuite.getDefault().setVerbose(true);
TestSuite.getDefault().setTestColor(TestUtils.TermColor.GREEN);
new TestUnit<AdapterBaseTestContext>("enter_device_group() no exception with no identities", new AdapterBaseTestContext(), ctx -> {
ctx.alice = ctx.engine.myself(ctx.alice);
ctx.engine.enter_device_group(new Vector<Identity>());
});
new TestUnit<AdapterBaseTestContext>("enter_device_group() no exception with 2 identities", new AdapterBaseTestContext(), ctx -> {
ctx.alice = ctx.engine.myself(ctx.alice);
ctx.bob = ctx.engine.myself(ctx.bob);
Vector<Identity> grpIdents = new Vector<Identity>();
grpIdents.add(ctx.alice);
grpIdents.add(ctx.bob);
ctx.engine.enter_device_group(grpIdents);
});
TestSuite.getDefault().run();
}
}

2
test/java/foundation/pEp/jniadapter/test/jni125/Makefile

@ -22,7 +22,7 @@ alice: compile clean-pep-home-alice
compile: $(JAVA_CLASSES) pitytest
%.class: %.java
cd $(JAVA_CWD);javac -cp $(CLASSPATH) $(JAVA_PKG_BASEPATH)/$(TEST_UNIT_NAME)/$<
cd $(JAVA_CWD);$(JAVAC_CMD) -cp $(CLASSPATH) $(JAVA_PKG_BASEPATH)/$(TEST_UNIT_NAME)/$<
clean:
rm -f $(JAVA_CLASSES)

2
test/java/foundation/pEp/jniadapter/test/jni88/TestMain.java

@ -1,5 +1,7 @@
package foundation.pEp.jniadapter.test.jni88;
import foundation.pEp.jniadapter.*;
import foundation.pEp.jniadapter.exceptions.*;
import java.util.Vector;
import java.lang.Thread;

1
test/java/foundation/pEp/jniadapter/test/jni91/TestMain.java

@ -1,5 +1,6 @@
package foundation.pEp.jniadapter.test.jni91;
import foundation.pEp.jniadapter.*;
import foundation.pEp.jniadapter.exceptions.*;
import java.lang.Thread;

5
test/java/foundation/pEp/jniadapter/test/jni92/TestMain.java

@ -1,4 +1,5 @@
package foundation.pEp.jniadapter.test.jni92;
import foundation.pEp.jniadapter.exceptions.*;
import foundation.pEp.jniadapter.test.utils.*;
import foundation.pEp.pitytest.*;
import foundation.pEp.jniadapter.*;
@ -38,7 +39,7 @@ class TestMain {
Engine e;
TestLogger.logH2("Creating new Engine");
e = new Engine();
TestLogger.log("Engine created with java object ID: " + e.getId());
// TestLogger.log("Engine created with java object ID: " + e.getId());
return e;
}
@ -52,7 +53,7 @@ class TestMain {
public static void engineConsumer(Vector<Engine> ev, Consumer<Engine> ec) {
ev.forEach(e -> {
TestLogger.logH2("engineConsumer: on engine java object ID: " + e.getId());
// TestLogger.logH2("engineConsumer: on engine java object ID: " + e.getId());
ec.accept(e);
});
}

10
test/java/foundation/pEp/jniadapter/test/jni98/TestMain.java

@ -1,10 +1,12 @@
package foundation.pEp.jniadapter.test.jni98;
import foundation.pEp.jniadapter.Engine;
import foundation.pEp.jniadapter.*;
import foundation.pEp.jniadapter.Message;
import foundation.pEp.pitytest.TestUnit;
import foundation.pEp.jniadapter.test.utils.AdapterBaseTestContext;
import java.util.Vector;
import static foundation.pEp.pitytest.TestLogger.log;
import static foundation.pEp.pitytest.TestLogger.logH2;
import static foundation.pEp.jniadapter.test.utils.AdapterTestUtils.msgToString;
@ -34,7 +36,7 @@ class TestMain {
log("\n" + msgToString(msg1, false));
// Lets get the pgpText of the msg1, and the EncFormat
String pgpText = Engine.toUTF16(msg1.getAttachments().elementAt(1).data);
String pgpText = Utils.toUTF16(msg1.getAttachments().elementAt(1).data);
Message.EncFormat ef = msg1.getEncFormat();
//TODO: setting encformat to 4 (PEP) but getting back 3 (PGPMIME)
@ -44,8 +46,8 @@ class TestMain {
log("\n" + msgToString(msg2, false));
logH2("Verify msg2");
Engine.decrypt_message_Return result = null;
result = ctx.engine.decrypt_message(msg2, ctx.vStr, 0);
decrypt_message_Return result = null;
result = ctx.engine.decrypt_message(msg2, new Vector<String>(), 0);
log("\n" + msgToString(result.dst, false));
}).run();

226
test/java/foundation/pEp/jniadapter/test/regression/TestMain.java

@ -3,268 +3,300 @@ import foundation.pEp.pitytest.*;
import foundation.pEp.jniadapter.test.utils.*;
import foundation.pEp.jniadapter.*;
class RegTestContext extends AdapterBaseTestContext {
// enhance the context
import java.util.ArrayList;
import java.util.Vector;
import static foundation.pEp.pitytest.TestLogger.log;
class CTXAlice extends AdapterBaseTestContext {
@Override
public CTXAlice init() throws Throwable {
super.init();
alice = engine.myself(alice);
return this;
}
}
class CTXAlice2 extends CTXAlice {
@Override
public void init() throws Throwable {
public CTXAlice2 init() throws Throwable {
super.init();
// init the enhancements
engine.importKey(keyBobSec);
bob = engine.updateIdentity(bob);
return this;
}
}
// Almost exact copy of JNI1118Context, we need a shared context hierarchy
class CTXReEvaluateMessageRating extends AdapterBaseTestContext {
public Message msgToBobEncrypted;
public Message msgToBobDecrypted;
public decrypt_message_Return msgToBobDecryptResult;
@Override
public CTXReEvaluateMessageRating init() throws Throwable {
super.init();
alice = engine.myself(alice);
engine.importKey(keyBobPub);
Vector<Identity> msgToBobRcpts = new Vector<>();
msgToBobRcpts.add(bob);
msgToBob.setTo(msgToBobRcpts);
msgToBobEncrypted = engine.encrypt_message(msgToBob, null, Message.EncFormat.PEP);
msgToBobDecrypted = msgToBobEncrypted;
msgToBobDecryptResult = engine.decrypt_message(msgToBobDecrypted, new Vector<String>(), 0);
if (msgToBobEncrypted == null) {
throw new RuntimeException("Context failure, error decrypting message");
}
addRatingToOptFields(msgToBobDecrypted, msgToBobDecryptResult.rating.getInternalStringValue());
addRcptsToOptFields(msgToBobDecrypted, Identity.toXKeyList(msgToBobDecrypted.getTo()));
return this;
}
public void addRatingToOptFields(Message msg, String ratingStr) {
ArrayList<Pair<String, String>> opts = msg.getOptFields();
opts.add(new Pair<String, String>("X-EncStatus",ratingStr));
msg.setOptFields(opts);
}
public void addRcptsToOptFields(Message msg, String fprs) {
ArrayList<Pair<String, String>> opts = msg.getOptFields();
opts.add(new Pair<String, String>("X-KeyList", fprs));
msg.setOptFields(opts);
}
}
class TestMain {
public static void main(String[] args) {
TestSuite.getDefault().setVerbose(false);
new TestUnit<RegTestContext>("Engine.myself", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.myself", new AdapterBaseTestContext(), ctx -> {
ctx.alice = ctx.engine.myself(ctx.alice);
});
new TestUnit<RegTestContext>("Engine.encrypt_message", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.encrypt_message", new AdapterBaseTestContext(), ctx -> {
ctx.engine.encrypt_message(ctx.msgToBob, null, Message.EncFormat.PEP);
});
new TestUnit<RegTestContext>("Engine.encrypt_message_and_add_priv_key", new RegTestContext(), ctx -> {
ctx.alice = ctx.engine.myself(ctx.alice);
new TestUnit<CTXAlice>("Engine.encrypt_message_and_add_priv_key", new CTXAlice(), ctx -> {
ctx.engine.encrypt_message_and_add_priv_key(ctx.msgToSelf, ctx.alice.fpr);
});
new TestUnit<RegTestContext>("Engine.encrypt_message_for_self", new RegTestContext(), ctx -> {
ctx.alice = ctx.engine.myself(ctx.alice);
new TestUnit<CTXAlice>("Engine.encrypt_message_for_self", new CTXAlice(), ctx -> {
ctx.engine.encrypt_message_for_self(ctx.alice, ctx.msgToSelf, null);
});
new TestUnit<RegTestContext>("Engine.decrypt_message", new RegTestContext(), ctx -> {
ctx.engine.decrypt_message(ctx.msgToSelf, ctx.vStr, 0);
new TestUnit<AdapterBaseTestContext>("Engine.decrypt_message", new AdapterBaseTestContext(), ctx -> {
ctx.engine.decrypt_message(ctx.msgToSelf, new Vector<String>(), 0);
});
//TODO: Coredump
// new TestUnit<RegTestContext>("Engine.re_evaluate_message_rating", new RegTestContext(), ctx -> {
// ctx.alice = ctx.engine.myself(ctx.alice);
// ctx.bob = ctx.engine.myself(ctx.bob);
// Message msg = ctx.engine.encrypt_message(ctx.msgToBob,null, Message.EncFormat.PEP);
// ctx.engine.re_evaluate_message_rating(msg);
// });
new TestUnit<CTXReEvaluateMessageRating>("Engine.re_evaluate_message_rating", new CTXReEvaluateMessageRating(), ctx -> {
ctx.engine.re_evaluate_message_rating(ctx.msgToBobDecrypted);
});
new TestUnit<RegTestContext>("Engine.outgoing_message_rating", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.outgoing_message_rating", new AdapterBaseTestContext(), ctx -> {
ctx.engine.outgoing_message_rating(ctx.msgToBob);
});
new TestUnit<RegTestContext>("Engine.outgoing_message_rating_preview", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.outgoing_message_rating_preview", new AdapterBaseTestContext(), ctx -> {
ctx.engine.outgoing_message_rating_preview(ctx.msgToBob);
});
new TestUnit<RegTestContext>("Engine.get_identity", new RegTestContext(), ctx -> {
ctx.alice = ctx.engine.myself(ctx.alice);
new TestUnit<CTXAlice>("Engine.get_identity", new CTXAlice(), ctx -> {
ctx.engine.get_identity(ctx.alice.address, ctx.alice.user_id);
});
new TestUnit<RegTestContext>("Engine.identity_rating", new RegTestContext(), ctx -> {
ctx.alice = ctx.engine.myself(ctx.alice);
new TestUnit<CTXAlice>("Engine.identity_rating", new CTXAlice(), ctx -> {
ctx.engine.identity_rating(ctx.alice);
});
new TestUnit<RegTestContext>("Engine.blacklist_retrieve", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.blacklist_retrieve", new AdapterBaseTestContext(), ctx -> {
ctx.engine.blacklist_retrieve();
});
//FAIL
new TestUnit<RegTestContext>("Engine.own_message_private_key_details", new RegTestContext(), ctx -> {
ctx.alice = ctx.engine.myself(ctx.alice);
ctx.bob = ctx.engine.myself(ctx.bob);
ctx.engine.encrypt_message(ctx.msgToBob, null, Message.EncFormat.PEP);
ctx.engine.own_message_private_key_details(ctx.msgToBob);
});
// TODO: FAILS
// new TestUnit<CTXAlice2>("Engine.own_message_private_key_details", new CTXAlice2(), ctx -> {
// ctx.engine.own_message_private_key_details(ctx.msgToSelf);
// });
new TestUnit<RegTestContext>("Engine.OpenPGP_list_keyinfo", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.OpenPGP_list_keyinfo", new AdapterBaseTestContext(), ctx -> {
ctx.engine.OpenPGP_list_keyinfo("");
});
new TestUnit<RegTestContext>("Engine.set_identity_flags", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.set_identity_flags", new AdapterBaseTestContext(), ctx -> {
ctx.engine.set_identity_flags(ctx.alice, 0);
});
new TestUnit<RegTestContext>("Engine.unset_identity_flags", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.unset_identity_flags", new AdapterBaseTestContext(), ctx -> {
ctx.engine.unset_identity_flags(ctx.alice, 0);
});
new TestUnit<RegTestContext>("Engine.own_identities_retrieve", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.own_identities_retrieve", new AdapterBaseTestContext(), ctx -> {
ctx.engine.own_identities_retrieve();
});
new TestUnit<RegTestContext>("Engine.get_trustwords", new RegTestContext(), ctx -> {
ctx.alice = ctx.engine.myself(ctx.alice);
ctx.bob = ctx.engine.myself(ctx.bob);
new TestUnit<CTXAlice2>("Engine.get_trustwords", new CTXAlice2(), ctx -> {
ctx.engine.get_trustwords(ctx.alice, ctx.bob, "en", false);
});
new TestUnit<RegTestContext>("Engine.get_trustwords_for_fprs", new RegTestContext(), ctx -> {
ctx.alice = ctx.engine.myself(ctx.alice);
ctx.bob = ctx.engine.myself(ctx.bob);
new TestUnit<CTXAlice2>("Engine.get_trustwords_for_fprs", new CTXAlice2(), ctx -> {
ctx.engine.get_trustwords_for_fprs(ctx.alice.fpr, ctx.bob.fpr, "en", false);
});
new TestUnit<RegTestContext>("Engine.get_message_trustwords", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.get_message_trustwords", new AdapterBaseTestContext(), ctx -> {
ctx.engine.get_message_trustwords(ctx.msgToBob, null, ctx.bob, "en", false);
});
new TestUnit<RegTestContext>("Engine.get_languagelist", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.get_languagelist", new AdapterBaseTestContext(), ctx -> {
ctx.engine.get_languagelist();
});
new TestUnit<RegTestContext>("Engine.key_reset_trust", new RegTestContext(), ctx -> {
ctx.alice = ctx.engine.myself(ctx.alice);
new TestUnit<CTXAlice>("Engine.key_reset_trust", new CTXAlice(), ctx -> {
ctx.engine.key_reset_trust(ctx.alice);
});
new TestUnit<RegTestContext>("Engine.key_reset_identity", new RegTestContext(), ctx -> {
ctx.alice = ctx.engine.myself(ctx.alice);
new TestUnit<CTXAlice>("Engine.key_reset_identity", new CTXAlice(), ctx -> {
ctx.engine.key_reset_identity(ctx.alice, "");
});
new TestUnit<RegTestContext>("Engine.key_reset_user", new RegTestContext(), ctx -> {
ctx.alice = ctx.engine.myself(ctx.alice);
new TestUnit<CTXAlice>("Engine.key_reset_user", new CTXAlice(), ctx -> {
ctx.engine.key_reset_user("fsdjugsh", ctx.alice.fpr);
});
new TestUnit<RegTestContext>("Engine.key_reset_all_own_keys", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.key_reset_all_own_keys", new AdapterBaseTestContext(), ctx -> {
ctx.engine.key_reset_all_own_keys();
});
new TestUnit<RegTestContext>("Engine.deliverHandshakeResult", new RegTestContext(), ctx -> {
ctx.engine.deliverHandshakeResult(SyncHandshakeResult.SyncHandshakeCancel, ctx.vID);
});
// TODO: FAILS
// new TestUnit<AdapterBaseTestContext>("Engine.deliverHandshakeResult", new AdapterBaseTestContext(), ctx -> {
// ctx.engine.deliverHandshakeResult(SyncHandshakeResult.SyncHandshakeCancel, ctx.vID);
// });
//[17:51] < heck> | this one fails since: 4665:f067c9e95455
//[17:52] < heck> | i confirmed it still works in the parent revision 4662:71147c43e31b
//[17:52] < heck> | the error i get is:
//[17:53] < heck> | *** send message KeySync Beacon service KeySync_fsm.c:234
//[17:53] < heck> | Assertion failed: (msg->from && msg->from->fpr), function attach_own_key, file message_api.c, line 1581.
// new TestUnit<RegTestContext>("Engine.leave_device_group", new RegTestContext(), ctx -> {
// TODO: FAILS
// [17:51] < heck> | this one fails since: 4665:f067c9e95455
// [17:52] < heck> | i confirmed it still works in the parent revision 4662:71147c43e31b
// [17:52] < heck> | the error i get is:
// [17:53] < heck> | *** send message KeySync Beacon service KeySync_fsm.c:234
// [17:53] < heck> | Assertion failed: (msg->from && msg->from->fpr), function attach_own_key, file message_api.c, line 1581.
// new TestUnit<AdapterBaseTestContext>("Engine.leave_device_group", new AdapterBaseTestContext(), ctx -> {
// ctx.engine.startSync();
// ctx.engine.leave_device_group();
// });
new TestUnit<RegTestContext>("Engine.enable_identity_for_sync", new RegTestContext(), ctx -> {
ctx.alice = ctx.engine.myself(ctx.alice);
new TestUnit<CTXAlice>("Engine.enable_identity_for_sync", new CTXAlice(), ctx -> {
ctx.engine.enable_identity_for_sync(ctx.alice);
});
new TestUnit<RegTestContext>("Engine.disable_identity_for_sync", new RegTestContext(), ctx -> {
ctx.alice = ctx.engine.myself(ctx.alice);
new TestUnit<CTXAlice>("Engine.disable_identity_for_sync", new CTXAlice(), ctx -> {
ctx.engine.disable_identity_for_sync(ctx.alice);
});
new TestUnit<RegTestContext>("Engine.config_cipher_suite", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.config_cipher_suite", new AdapterBaseTestContext(), ctx -> {
ctx.engine.config_cipher_suite(CipherSuite.pEpCipherSuiteDefault);
});
new TestUnit<RegTestContext>("Engine.trustwords", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.trustwords", new AdapterBaseTestContext(), ctx -> {
ctx.engine.trustwords(ctx.alice);
});
new TestUnit<RegTestContext>("Engine.updateIdentity", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.updateIdentity", new AdapterBaseTestContext(), ctx -> {
ctx.engine.updateIdentity(ctx.alice);
});
new TestUnit<RegTestContext>("Engine.setOwnKey", new RegTestContext(), ctx -> {
ctx.alice = ctx.engine.myself(ctx.alice);
new TestUnit<CTXAlice>("Engine.setOwnKey", new CTXAlice(), ctx -> {
ctx.engine.setOwnKey(ctx.alice, ctx.alice.fpr);
});
new TestUnit<RegTestContext>("Engine.keyMistrusted", new RegTestContext(), ctx -> {
ctx.alice = ctx.engine.myself(ctx.alice);
new TestUnit<CTXAlice>("Engine.keyMistrusted", new CTXAlice(), ctx -> {
ctx.engine.keyMistrusted(ctx.alice);
});
new TestUnit<RegTestContext>("Engine.keyResetTrust", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.keyResetTrust", new AdapterBaseTestContext(), ctx -> {
ctx.engine.keyResetTrust(ctx.alice);
});
new TestUnit<RegTestContext>("Engine.trustPersonalKey", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.trustPersonalKey", new AdapterBaseTestContext(), ctx -> {
ctx.engine.trustPersonalKey(ctx.alice);
});
new TestUnit<RegTestContext>("Engine.trustOwnKey", new RegTestContext(), ctx -> {
ctx.alice = ctx.engine.myself(ctx.alice);
new TestUnit<CTXAlice>("Engine.trustOwnKey", new CTXAlice(), ctx -> {
ctx.engine.trustOwnKey(ctx.alice);
});
new TestUnit<RegTestContext>("Engine.importKey", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.importKey", new AdapterBaseTestContext(), ctx -> {
ctx.engine.importKey(ctx.keyBobPub);
});
new TestUnit<RegTestContext>("Engine.blacklist_add", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.blacklist_add", new AdapterBaseTestContext(), ctx -> {
ctx.engine.blacklist_add("43");
});
new TestUnit<RegTestContext>("Engine.blacklist_delete", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.blacklist_delete", new AdapterBaseTestContext(), ctx -> {
ctx.engine.blacklist_delete("43");
});
new TestUnit<RegTestContext>("Engine.blacklist_is_listed", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.blacklist_is_listed", new AdapterBaseTestContext(), ctx -> {
ctx.engine.blacklist_is_listed("43");
});
new TestUnit<RegTestContext>("Engine.config_passive_mode", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.config_passive_mode", new AdapterBaseTestContext(), ctx -> {
ctx.engine.config_passive_mode(false);
});
new TestUnit<RegTestContext>("Engine.config_unencrypted_subject", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.config_unencrypted_subject", new AdapterBaseTestContext(), ctx -> {
ctx.engine.config_unencrypted_subject(false);
});
new TestUnit<RegTestContext>("Engine.getCrashdumpLog", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.getCrashdumpLog", new AdapterBaseTestContext(), ctx -> {
ctx.engine.getCrashdumpLog(0);
});
new TestUnit<RegTestContext>("Engine.getUserDirectory", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.getUserDirectory", new AdapterBaseTestContext(), ctx -> {
ctx.engine.getUserDirectory();
});
new TestUnit<RegTestContext>("Engine.getMachineDirectory", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.getMachineDirectory", new AdapterBaseTestContext(), ctx -> {
ctx.engine.getMachineDirectory();
});
// AbstractEngine.java
new TestUnit<RegTestContext>("Engine.close", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.close", new AdapterBaseTestContext(), ctx -> {
ctx.engine.close();
});
new TestUnit<RegTestContext>("Engine.getVersion", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.getVersion", new AdapterBaseTestContext(), ctx -> {
ctx.engine.getVersion();
});
new TestUnit<RegTestContext>("Engine.getProtocolVersion", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.getProtocolVersion", new AdapterBaseTestContext(), ctx -> {
ctx.engine.getProtocolVersion();
});
new TestUnit<RegTestContext>("Engine.startKeyserverLookup", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.startKeyserverLookup", new AdapterBaseTestContext(), ctx -> {
ctx.engine.startKeyserverLookup();
});
new TestUnit<RegTestContext>("Engine.startSync", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.startSync", new AdapterBaseTestContext(), ctx -> {
ctx.engine.startSync();
});
new TestUnit<RegTestContext>("Engine.stopSync", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.stopSync", new AdapterBaseTestContext(), ctx -> {
ctx.engine.stopSync();
});
new TestUnit<RegTestContext>("Engine.isSyncRunning", new RegTestContext(), ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.isSyncRunning", new AdapterBaseTestContext(), ctx -> {
ctx.engine.isSyncRunning();
});
new TestUnit<AdapterBaseTestContext>("Engine.config_passphrase",new RegTestContext() , ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.config_passphrase",new AdapterBaseTestContext() , ctx -> {
ctx.engine.config_passphrase("SUPERCOMPLICATEDPASSPHRASE");
});
new TestUnit<AdapterBaseTestContext>("Engine.config_passphrase_for_new_keys",new RegTestContext() , ctx -> {
new TestUnit<AdapterBaseTestContext>("Engine.config_passphrase_for_new_keys",new AdapterBaseTestContext() , ctx -> {
ctx.engine.config_passphrase_for_new_keys(true, "SUPERCOMPLICATEDPASSPHRASE");
});

2
test/java/foundation/pEp/jniadapter/test/speedtest/SpeedTest.java

@ -28,7 +28,7 @@ public class SpeedTest {
try {
Message[] msgs = codec.decode(testDataEnc);
Vector<String> keys = new Vector<String>();
Engine.decrypt_message_Return ret = eng.decrypt_message(msgs[0], keys, 0);
decrypt_message_Return ret = eng.decrypt_message(msgs[0], keys, 0);
String txt = ret.dst.getLongmsg();
} catch (ParseException ex) {
System.err.println("error: parsing test data");

3
test/java/foundation/pEp/jniadapter/test/templateAliceBob/MultiPeerCTX.java

@ -51,7 +51,7 @@ class MultiPeerCTX extends FsMQManagerTestContext {
super(selfAddress);
}
public void init() throws Throwable {
public MultiPeerCTX init() throws Throwable {
super.init();
vID = new Vector<Identity>();
vStr = new Vector<String>();
@ -97,5 +97,6 @@ class MultiPeerCTX extends FsMQManagerTestContext {
log("pEp PER_USER_DIR : " + engine.getUserDirectory());
log("pEp ProtocolVersion: " + engine.getProtocolVersion());
log("pEp Version : " + engine.getVersion());
return this;
}
}

4
test/java/foundation/pEp/jniadapter/test/templateAliceBob/TestAlice.java

@ -2,7 +2,7 @@ package foundation.pEp.jniadapter.test.templateAliceBob;
import static foundation.pEp.pitytest.TestLogger.*;
import foundation.pEp.jniadapter.Engine;
import foundation.pEp.jniadapter.*;
import foundation.pEp.jniadapter.Message;
import foundation.pEp.jniadapter.test.utils.transport.fsmqmanager.FsMQMessage;
import foundation.pEp.pitytest.*;
@ -59,7 +59,7 @@ class TestAlice {
Message msgRx = Utils.deserializepEpMessage(ctx, msgRxSerialized, Message.EncFormat.PEPEncInlineEA);
log("ENCRYPTED IN: \n" + AdapterTestUtils.msgToString(msgRx, false));
Engine.decrypt_message_Return result = ctx.engine.decrypt_message(msgRx, null, 0);
decrypt_message_Return result = ctx.engine.decrypt_message(msgRx, null, 0);
log("DECRYPTED msg: \n" + AdapterTestUtils.msgToString(result.dst, false));
log("DECRYPTED rating:" + result.rating.toString());
log("DECRYPTED flags:" + result.flags);

4
test/java/foundation/pEp/jniadapter/test/templateAliceBob/TestBob.java

@ -2,7 +2,7 @@ package foundation.pEp.jniadapter.test.templateAliceBob;
import static foundation.pEp.pitytest.TestLogger.*;
import foundation.pEp.jniadapter.Engine;
import foundation.pEp.jniadapter.*;
import foundation.pEp.jniadapter.Message;
import foundation.pEp.jniadapter.test.utils.transport.fsmqmanager.FsMQMessage;
import foundation.pEp.pitytest.*;
@ -39,7 +39,7 @@ class TestBob {
Message msgRx = Utils.deserializepEpMessage(ctx, msgRxSerialized, Message.EncFormat.PEPEncInlineEA);
log("ENCRYPTED IN: \n" + AdapterTestUtils.msgToString(msgRx, false));
Engine.decrypt_message_Return result = ctx.engine.decrypt_message(msgRx, null, 0);
decrypt_message_Return result = ctx.engine.decrypt_message(msgRx, null, 0);
log("DECRYPTED msg: \n" + AdapterTestUtils.msgToString(result.dst, false));
log("DECRYPTED rating:" + result.rating.toString());
log("DECRYPTED flags:" + result.flags);

49
test/java/foundation/pEp/jniadapter/test/utils/AdapterBaseTestContext.java

@ -1,12 +1,14 @@
package foundation.pEp.jniadapter.test.utils;
import foundation.pEp.pitytest.*;
import foundation.pEp.jniadapter.*;
import foundation.pEp.jniadapter.Engine;
import foundation.pEp.jniadapter.Identity;
import foundation.pEp.jniadapter.Message;
import foundation.pEp.pitytest.AbstractTestContext;
import foundation.pEp.pitytest.TestLogger;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
//public class ABAliceTestContext extends AdapterBaseTestContext {
@ -59,14 +61,7 @@ public class AdapterBaseTestContext extends AbstractTestContext {
public Message msgToSelf;
public Message msgToBob;
// Misc
public Vector<Identity> vID;
public Vector<String> vStr;
public void init() throws Throwable {
vID = new Vector<Identity>();
vStr = new Vector<String>();
public AdapterBaseTestContext init() throws Throwable {
callbacks = new TestCallbacks();
engine = new Engine();
engine.setMessageToSendCallback(callbacks);
@ -74,7 +69,7 @@ public class AdapterBaseTestContext extends AbstractTestContext {
TestLogger.logH2("Machine directory: ");
TestLogger.log(engine.getMachineDirectory());
TestLogger.logH2("User directory:" );
TestLogger.logH2("User directory:");
TestLogger.log(engine.getUserDirectory());
@ -91,27 +86,29 @@ public class AdapterBaseTestContext extends AbstractTestContext {
msgToSelf = AdapterTestUtils.makeNewTestMessage(alice, alice, Message.Direction.Outgoing);
msgToBob = AdapterTestUtils.makeNewTestMessage(alice, bob, Message.Direction.Outgoing);
vID.add(bob);
vStr.add("StringItem");
Path path;
path = Paths.get(filenameBobPub);
keyBobPub = Files.readAllBytes(path);
try {
keyBobPub = Files.readAllBytes(path);
path = Paths.get(filenameBobSec);
keyBobSec = Files.readAllBytes(path);
path = Paths.get(filenameBobSec);
keyBobSec = Files.readAllBytes(path);
path = Paths.get(filenameAlicePub);
keyAlicePub = Files.readAllBytes(path);
path = Paths.get(filenameAlicePub);
keyAlicePub = Files.readAllBytes(path);
path = Paths.get(filenameAliceSec);
keyAliceSec = Files.readAllBytes(path);
path = Paths.get(filenameAliceSec);
keyAliceSec = Files.readAllBytes(path);
path = Paths.get(filenameAlicePubPassphrase);
keyAlicePubPassphrase = Files.readAllBytes(path);
path = Paths.get(filenameAlicePubPassphrase);
keyAlicePubPassphrase = Files.readAllBytes(path);
path = Paths.get(filenameAliceSecPassphrase);
keyAliceSecPassphrase = Files.readAllBytes(path);
path = Paths.get(filenameAliceSecPassphrase);
keyAliceSecPassphrase = Files.readAllBytes(path);
} catch (Throwable e) {
throw new RuntimeException(e);
}
return this;
}
}

3
test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/ctx/FsMQManagerBaseTestContext.java

@ -23,7 +23,7 @@ public class FsMQManagerBaseTestContext extends AbstractTestContext {
}
@Override
public void init() throws Throwable {
public FsMQManagerBaseTestContext init() throws Throwable {
peerNames = new ArrayList<>();
peerNames.add("Alice");
peerNames.add("Bob");
@ -31,6 +31,7 @@ public class FsMQManagerBaseTestContext extends AbstractTestContext {
createPeerMapAndPeerList();
defineSelfAndUpdatePeers();
messages = FsMQManagerTestUtils.createTestMessages(self.getAddress(), MSG_COUNT);
return this;
}
private void createPeerMapAndPeerList() {

3
test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/ctx/FsMQManagerTestContext.java

@ -10,10 +10,11 @@ public class FsMQManagerTestContext extends FsMQManagerBaseTestContext {
}
@Override
public void init() throws Throwable {
public FsMQManagerTestContext init() throws Throwable {
super.init();
qm = new FsMQManager(self);
qm.identities.addAll(peerList);
return this;
}
}

2
test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/identities/Makefile

@ -22,7 +22,7 @@ run: compile
compile: $(JAVA_CLASSES) pitytest
%.class: %.java
cd $(JAVA_CWD);pwd;javac $(JAVA_PKG_BASEPATH)/$(TEST_UNIT_NAME)/$<
cd $(JAVA_CWD);pwd;$(JAVAC_CMD) $(JAVA_PKG_BASEPATH)/$(TEST_UNIT_NAME)/$<
clean:
rm -f $(JAVA_CLASSES)

3
test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/identities/TestMain.java

@ -31,8 +31,9 @@ class FsMQManagerIdentitiesTestContext extends AbstractTestContext {
List<String> messages;
@Override
public void init() throws Throwable {
public FsMQManagerIdentitiesTestContext init() throws Throwable {
messages = FsMQManagerTestUtils.createTestMessages(ownAddress, MSG_COUNT);
return this;
}
}

2
test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/stateless_ping/Makefile

@ -25,7 +25,7 @@ bob: compile
compile: $(JAVA_CLASSES) pitytest
%.class: %.java
cd $(JAVA_CWD);pwd;javac $(JAVA_PKG_BASEPATH)/$(TEST_UNIT_NAME)/$<
cd $(JAVA_CWD);pwd;$(JAVAC_CMD) $(JAVA_PKG_BASEPATH)/$(TEST_UNIT_NAME)/$<
clean:
rm -f $(JAVA_CLASSES)

2
test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/stateless_rxtx/Makefile

@ -23,7 +23,7 @@ run: compile
compile: $(JAVA_CLASSES) pitytest
%.class: %.java
cd $(JAVA_CWD);pwd;javac $(JAVA_PKG_BASEPATH)/$(TEST_UNIT_NAME)/$<
cd $(JAVA_CWD);pwd;$(JAVAC_CMD) $(JAVA_PKG_BASEPATH)/$(TEST_UNIT_NAME)/$<
clean:
rm -f $(JAVA_CLASSES)

4
test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/stateless_rxtx/TestMain.java

@ -14,13 +14,13 @@ class FsMQManagerBaseTestContext extends AbstractTestContext {
Entity carol;
@Override
public void init() throws Throwable {
public FsMQManagerBaseTestContext init() throws Throwable {
alice = new Entity("Alice");
bob = new Entity("Bob");
carol = new Entity("Carol");
alice.add(bob);
alice.add(carol);
return this;
}
class Entity {

2
test/java/foundation/pEp/jniadapter/test/utils/transport/fsmsgqueue/test/regression/Makefile

@ -22,7 +22,7 @@ run: compile
compile: $(JAVA_CLASSES) pitytest
%.class: %.java
cd $(JAVA_CWD);pwd;javac $(JAVA_PKG_BASEPATH)/$(TEST_UNIT_NAME)/$<
cd $(JAVA_CWD);pwd;$(JAVAC_CMD) $(JAVA_PKG_BASEPATH)/$(TEST_UNIT_NAME)/$<
clean:
rm -f $(JAVA_CLASSES)

4
test/java/foundation/pEp/jniadapter/test/utils/transport/fsmsgqueue/test/regression/TestMain.java

@ -20,9 +20,10 @@ class FsMsgQueueTestContext extends AbstractTestContext {
FsMsgQueue queue;
@Override
public void init() throws Throwable {
public FsMsgQueueTestContext init() throws Throwable {
deleteQDir();
messages = createTestMessages(msgCount);
return this;
}
public void deleteQDir() {
@ -32,6 +33,7 @@ class FsMsgQueueTestContext extends AbstractTestContext {
deleteRecursively(qDir);
if (qDir.exists()) throw new RuntimeException("Cant delete Dir:" + qDirPath);
}
}
public ArrayList<String> createTestMessages(int count) {

2
test/java/foundation/pEp/pitytest/Makefile

@ -14,7 +14,7 @@ all: compile
compile: $(JAVA_CLASSES)
%.class: %.java
cd $(JAVA_CWD);javac -cp $(CLASSPATH) $(JAVA_PKG_BASEPATH)/$(PKGNAME)/$<
cd $(JAVA_CWD);$(JAVAC_CMD) -cp $(CLASSPATH) $(JAVA_PKG_BASEPATH)/$(PKGNAME)/$<
clean:
rm -f $(JAVA_CLASSES)

2
test/java/foundation/pEp/pitytest/Makefile.conf

@ -1,9 +1,11 @@
JAVA_PKG_BASENAME=foundation.pEp
JAVA_PKG_BASEPATH=foundation/pEp
CLASSPATH=.
JAVAC_CMD=javac -encoding UTF-8
JAVA=java -enableassertions
JAVA_CWD=../../../
JAVA_CLASSES_PITYTEST= \
TestSuite.class \
TestUnit.class \

8
test/java/foundation/pEp/pitytest/TestContextInterface.java

@ -1,11 +1,17 @@
package foundation.pEp.pitytest;
public interface TestContextInterface {
void init() throws Throwable;
TestContextInterface init() throws Throwable;
boolean isInitialized();
void setInitialized(boolean initialized);
boolean isUninitializable();
void setUninitializable(boolean uninitializable);
String getTestContextName();
void setTestContextName(String name);
}

2
test/java/foundation/pEp/pitytest/TestSuite.java

@ -75,7 +75,7 @@ public class TestSuite {
}
public void add(TestUnit t) {
tests.add(t);
tests.add(t.copy());
}
public void run() {

49
test/java/foundation/pEp/pitytest/TestUnit.java

@ -44,20 +44,45 @@ public class TestUnit<T extends TestContextInterface> implements Runnable {
add(TestSuite.getDefault());
}
//Shallow Copy
public TestUnit(TestUnit<T> orig) {
testUnitName = orig.testUnitName;
ctx = orig.ctx;
lambda = orig.lambda;
result = orig.result;
state = orig.state;
lastException = orig.lastException;
verboseMode = orig.verboseMode;
testColor = orig.testColor;
logFmtPadding = orig.logFmtPadding;
logFmtMsgLen = orig.logFmtMsgLen;
logFmtTestDuration = orig.logFmtTestDuration;
lineWidthMin = orig.lineWidthMin;
logFmtTestNameLen = orig.logFmtTestNameLen;
logFmtCtxNameLen = orig.logFmtCtxNameLen;
}
//Shallow Copy
public TestUnit<T> copy() {
return new TestUnit<>(this);
}
public boolean isVerboseMode() {
return verboseMode;
}
public void setVerboseMode(boolean verboseMode) {
public TestUnit<T> setVerboseMode(boolean verboseMode) {
this.verboseMode = verboseMode;
return this;
}
public TermColor getTestColor() {
return testColor;
}
public void setTestColor(TermColor testColor) {
public TestUnit<T> setTestColor(TermColor testColor) {
this.testColor = testColor;
return this;
}
public TestState getResult() {
@ -65,7 +90,11 @@ public class TestUnit<T extends TestContextInterface> implements Runnable {
}
public Throwable getLastException() {
return lastException;
Throwable ret = new Throwable("No Exception caught");
if(lastException != null) {
ret = lastException;
}
return ret;
}
public TestUnit<T> add(TestSuite suite) {
@ -82,10 +111,15 @@ public class TestUnit<T extends TestContextInterface> implements Runnable {
return ctx;
}
public TestUnit<T> setContext(T ctx) {
this.ctx = ctx;
return this;
}
public void run() {
TestUtils.standardOutErrEnabled(verboseMode);
if (ctx.isUninitializable()) {
setTestState(TestState.CTX_FAIL);
setTestState(TestState.SKIPPED);
TestUtils.standardOutErrEnabled(true);
} else {
try {
@ -147,18 +181,17 @@ public class TestUnit<T extends TestContextInterface> implements Runnable {
}
case CTX_FAIL: {
setTestResult(TestState.SKIPPED);
// logH1(makeLogString());
break;
}
}
}
private void setTestResult(TestState r) {
assert (r == TestState.SKIPPED || r == TestState.FAILED || r == TestState.SUCCESS || r == TestState.UNEVALUATED ): "PityTest Internal: illegal result value '" + r +"'";
assert (r == TestState.SKIPPED || r == TestState.FAILED || r == TestState.SUCCESS || r == TestState.UNEVALUATED) : "PityTest Internal: illegal result value '" + r + "'";
result = r;
TestUtils.standardOutErrEnabled(true);
logH1(makeLogString());
if (result == TestState.FAILED || result == TestState.CTX_FAIL) {
if (result == TestState.FAILED || state == TestState.CTX_FAIL) {
log("ERROR: " + getLastException().toString());
}
if (verboseMode) logRaw("\n\n");
@ -193,7 +226,7 @@ public class TestUnit<T extends TestContextInterface> implements Runnable {
DecimalFormat f = new DecimalFormat("0.000");
String durationFmtd = f.format(testDuration.toMillis() / 1000.0);
strTestDuration = TestUtils.padOrClipString(" [" + durationFmtd + " sec] ", "=", logFmtTestDuration, TestUtils.Alignment.Right, ".. ");
} else {
} else {
strTestDuration = TestUtils.padOrClipString("", "=", logFmtTestDuration, TestUtils.Alignment.Right, ".. ");
}

2
test/java/foundation/pEp/pitytest/examples/ctxinitfail/Makefile

@ -23,7 +23,7 @@ run: compile
compile: $(JAVA_CLASSES) pitytest
%.class: %.java
cd $(JAVA_CWD);pwd;javac $(JAVA_PKG_BASEPATH)/$(TEST_UNIT_NAME)/$<
cd $(JAVA_CWD);pwd;$(JAVAC_CMD) $(JAVA_PKG_BASEPATH)/$(TEST_UNIT_NAME)/$<
clean:
rm -f $(JAVA_CLASSES)

12
test/java/foundation/pEp/pitytest/examples/ctxinitfail/TestMain.java

@ -1,8 +1,10 @@
package foundation.pEp.pitytest.examples.ctxinitfail;
import static foundation.pEp.pitytest.TestLogger.*;
import foundation.pEp.pitytest.AbstractTestContext;
import foundation.pEp.pitytest.TestSuite;
import foundation.pEp.pitytest.TestUnit;
import foundation.pEp.pitytest.*;
import static foundation.pEp.pitytest.TestLogger.log;
class CtxInitFailContext extends AbstractTestContext {
@ -10,9 +12,13 @@ class CtxInitFailContext extends AbstractTestContext {
int result;
@Override
public void init() throws Throwable {
public CtxInitFailContext init() throws RuntimeException {
name = "PityTest";
log("Hello World from: " + name);
// throw new RuntimeException("regddjkl");
result = 50 / 0;
return this;
}
}

2
test/java/foundation/pEp/pitytest/examples/ctxmembers/Makefile

@ -23,7 +23,7 @@ run: compile
compile: $(JAVA_CLASSES) pitytest
%.class: %.java
cd $(JAVA_CWD);pwd;javac $(JAVA_PKG_BASEPATH)/$(TEST_UNIT_NAME)/$<
cd $(JAVA_CWD);pwd;$(JAVAC_CMD) $(JAVA_PKG_BASEPATH)/$(TEST_UNIT_NAME)/$<
clean:
rm -f $(JAVA_CLASSES)

3
test/java/foundation/pEp/pitytest/examples/ctxmembers/TestMain.java

@ -18,12 +18,13 @@ class CtxMembersTestContext extends AbstractTestContext {
ExampleCtxMember incorrect = new ExampleCtxMember(false); // WRONG
@Override
public void init() throws Throwable {
public CtxMembersTestContext init() throws Throwable {
log("=== OUTPUT FROM TEST CONTEXT INIT BEGIN ===");
log(getTestContextName()+ " - init() called");
correct = new ExampleCtxMember(true);
name = "PityTest";
log("=== OUTPUT FROM TEST CONTEXT INIT END ===");
return this;
}
}

2
test/java/foundation/pEp/pitytest/examples/helloworld/Makefile

@ -23,7 +23,7 @@ run: compile
compile: $(JAVA_CLASSES) pitytest
%.class: %.java
cd $(JAVA_CWD);pwd;javac $(JAVA_PKG_BASEPATH)/$(TEST_UNIT_NAME)/$<
cd $(JAVA_CWD);pwd;$(JAVAC_CMD) $(JAVA_PKG_BASEPATH)/$(TEST_UNIT_NAME)/$<
clean:
rm -f $(JAVA_CLASSES)

3
test/java/foundation/pEp/pitytest/examples/helloworld/TestMain.java

@ -7,8 +7,9 @@ class HelloWorldTestContext extends AbstractTestContext {
String name;
@Override
public void init() throws Throwable {
public HelloWorldTestContext init() throws Throwable {
name = "PityTest";
return this;
}
}

2
test/java/foundation/pEp/pitytest/examples/testsuite/Makefile

@ -23,7 +23,7 @@ run: compile
compile: $(JAVA_CLASSES) pitytest
%.class: %.java
cd $(JAVA_CWD);pwd;javac $(JAVA_PKG_BASEPATH)/$(TEST_UNIT_NAME)/$<
cd $(JAVA_CWD);pwd;$(JAVAC_CMD) $(JAVA_PKG_BASEPATH)/$(TEST_UNIT_NAME)/$<
clean:
rm -f $(JAVA_CLASSES)

3
test/java/foundation/pEp/pitytest/examples/testsuite/TestMain.java

@ -6,8 +6,9 @@ class TestSuiteContext extends AbstractTestContext {
String name;
@Override
public void init() throws Throwable {
public TestSuiteContext init() throws Throwable {
name = "PityTest";
return this;
}
}

6
test/java/foundation/pEp/pitytest/utils/Pair.java

@ -24,5 +24,11 @@ public class Pair<K, V> {
key = f;
value = s;
}
public String toString() {
String ret="";
ret += "'" + key.toString() + "' : '" + value.toString() + "'";
return ret;
}
}

102
test/java/foundation/pEp/pitytest/utils/TestUtils.java

@ -7,10 +7,7 @@ import java.io.PrintStream;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@ -330,5 +327,102 @@ public class TestUtils {
return Math.max(min, Math.min(max, val));
}
/*
Random data generators
*/
public static int randomInt(int min, int max) {
int ret = 0;
int range = max - min;
if (range <= 0) {
range = 1;
}
Random rand = new Random();
ret = rand.nextInt(range) + min;
return ret;
}
public static String randomASCIIString(CharClass charClass, int len) {
byte[] array = new byte[len]; // length is bounded by 7
int rangeMin = 0;
int rangeMax = 0;
switch (charClass) {
case Unbounded: {
rangeMin = 0;
rangeMax = 255;
break;
}
case Alpha: {
rangeMin = 65;
rangeMax = 122;
break;
}
case Numeric: {
rangeMin = 48;
rangeMax = 57;
break;
}
case Alphanumeric: {
rangeMin = 48;
rangeMax = 122;
break;
}
}
new Random().nextBytes(array);
for (int i = 0; i < array.length; i++) {
array[i] = (byte)clip(randomInt(rangeMin, rangeMax),0,255);
}
String generatedString = new String(array, Charset.forName("UTF-8"));
return generatedString;
}
public enum CharClass {
Unbounded(0) {
@Override
public String toString() {
return "Unbounded";
}
},
Alpha(1) {
@Override
public String toString() {
return "Alpha";
}
},
Numeric(2) {
@Override
public String toString() {
return "Numeric";
}
},
Alphanumeric(3) {
@Override
public String toString() {
return "Alphanumeric";
}
};
public final int value;
private static HashMap<Integer, CharClass> intMap;
private CharClass(int value) {
this.value = value;
}
public static CharClass getByInt(int value) {
if (intMap == null) {
intMap = new HashMap<Integer, CharClass>();
for (CharClass s : CharClass.values()) {
intMap.put(s.value, s);
}
}
if (intMap.containsKey(value)) {
return intMap.get(value);
}
return null;
}
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save