diff --git a/.gitignore b/.gitignore index 7dcca69..d3cabd2 100644 --- a/.gitignore +++ b/.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/ diff --git a/Makefile b/Makefile index 27eec57..13c9555 100644 --- a/Makefile +++ b/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 + diff --git a/Makefile.conf b/Makefile.conf index fe07727..adf9ca8 100644 --- a/Makefile.conf +++ b/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 /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 diff --git a/README.md b/README.md index 04197e9..ba4834e 100644 --- a/README.md +++ b/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). diff --git a/android/build.gradle b/android/build.gradle index f1f1d8e..51e71e3 100644 --- a/android/build.gradle +++ b/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) { diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 24a635b..abc0209 100644 --- a/android/jni/Android.mk +++ b/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 diff --git a/android/src/foundation/pEp/jniadapter/AndroidHelper.java b/android/src/foundation/pEp/jniadapter/AndroidHelper.java index 2ac6863..0d079fe 100644 --- a/android/src/foundation/pEp/jniadapter/AndroidHelper.java +++ b/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"); diff --git a/local.conf.example b/local.conf.example index 8de0aa8..6cc3be8 100644 --- a/local.conf.example +++ b/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 diff --git a/src/Makefile b/src/Makefile index a470ee4..94bbae8 100644 --- a/src/Makefile +++ b/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 diff --git a/src/codegen/Makefile b/src/codegen/Makefile new file mode 100644 index 0000000..3f8fd95 --- /dev/null +++ b/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 + diff --git a/src/gen_cpp_Engine.ysl2 b/src/codegen/gen_cpp_Engine.ysl2 similarity index 75% rename from src/gen_cpp_Engine.ysl2 rename to src/codegen/gen_cpp_Engine.ysl2 index d4e2e90..d316923 100644 --- a/src/gen_cpp_Engine.ysl2 +++ b/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 #include #include #include @@ -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(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(_«$name»)) { «$name»_ = element; break; } @@ -258,7 +229,7 @@ tstylesheet { assert(clazz_«$name»_); jmethodID constructor_«$name»_ = env->GetMethodID(clazz_«$name»_, "", "(J)V"); assert(constructor_«$name»_); - «$name»_ = env->NewObject(clazz_«$name»_, constructor_«$name»_, (jlong) _«$name»); + «$name»_ = env->NewObject(clazz_«$name»_, constructor_«$name»_, reinterpret_cast(_«$name»)); } || @@ -274,15 +245,15 @@ tstylesheet { choose { when "$type = 'message'" - | message *_«$name» = (message *) callLongMethod(env, «$name», "getHandle"); + | message *_«$name» = reinterpret_cast(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 { diff --git a/src/gen_cpp_Message.ysl2 b/src/codegen/gen_cpp_Message.ysl2 similarity index 72% rename from src/gen_cpp_Message.ysl2 rename to src/codegen/gen_cpp_Message.ysl2 index a5f4496..13ee28f 100644 --- a/src/gen_cpp_Message.ysl2 +++ b/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 #include @@ -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(_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(_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; - |> } + |> } } } || diff --git a/src/gen_java_Engine.ysl2 b/src/codegen/gen_java_Engine.ysl2 similarity index 70% rename from src/gen_java_Engine.ysl2 rename to src/codegen/gen_java_Engine.ysl2 index b3b07c3..ea9e520 100644 --- a/src/gen_java_Engine.ysl2 +++ b/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 ret = new Vector(); - if(glist != null) { - for (_Identity i : glist) { - ret.add(new Identity(i)); - } + Vector<_Identity> glist = _«@name»(`apply "parm/*", mode=basic_parm_name`); + Vector ret = new Vector(); + 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> glist = _«@name»(`apply "parm[in]", mode=call;`); if(glist != null){ ArrayList> list = new ArrayList>(); - for (Pair i : glist) - list.add(new Pair(AbstractEngine.toUTF16(i.first), AbstractEngine.toUTF16(i.second))); + for (Pair i : glist) { + list.add(new Pair(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 list = new Vector(); - 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 diff --git a/src/codegen/gen_java_Message.ysl2 b/src/codegen/gen_java_Message.ysl2 new file mode 100644 index 0000000..f8e83f1 --- /dev/null +++ b/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 intMap; + + private «$jname»(int value) { + this.value = value; + } + + public static «$jname» getByInt(int value){ + if (intMap == null) { + intMap = new HashMap(); + 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 + otherwise > _«$ename» + } + const "convget" choose { + when "$ctype = 'stringlist'" > Utils.toUTF16(i) + when "$ctype = 'stringpairlist'" > new Pair(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(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()" > , ` + } +} + diff --git a/src/codegen/gen_throw_pEp_exception.ysl2 b/src/codegen/gen_throw_pEp_exception.ysl2 new file mode 100644 index 0000000..42d99ec --- /dev/null +++ b/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 + + 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 + #include + #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; + } +} + diff --git a/src/pEp.yml2 b/src/codegen/pEp.yml2 similarity index 57% rename from src/pEp.yml2 rename to src/codegen/pEp.yml2 index b36b6c3..14ef8b8 100644 --- a/src/pEp.yml2 +++ b/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; }; }; diff --git a/src/textutils.ysl2 b/src/codegen/textutils.ysl2 similarity index 88% rename from src/textutils.ysl2 rename to src/codegen/textutils.ysl2 index a8b7798..a531cd3 100644 --- a/src/textutils.ysl2 +++ b/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, '-')"; diff --git a/src/types_c.ysl2 b/src/codegen/types_c.ysl2 similarity index 100% rename from src/types_c.ysl2 rename to src/codegen/types_c.ysl2 diff --git a/src/types_java.ysl2 b/src/codegen/types_java.ysl2 similarity index 100% rename from src/types_java.ysl2 rename to src/codegen/types_java.ysl2 diff --git a/src/basic_api.cc b/src/cxx/basic_api.cc similarity index 82% rename from src/basic_api.cc rename to src/cxx/basic_api.cc index 3d8d14d..4f9960c 100644 --- a/src/basic_api.cc +++ b/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(_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 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 l(*mutex_local); - size_t _size = (size_t) env->GetArrayLength(key); - const char *_key = (char *) env->GetByteArrayElements(key, NULL); + size_t _size = static_cast(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(_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 l(*mutex_local); - ::config_passive_mode(session(), (bool)enable); + ::config_passive_mode(session(), static_cast(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 l(*mutex_local); - ::config_unencrypted_subject(session(), (bool)enable); + ::config_unencrypted_subject(session(), static_cast(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 l(*mutex_local); - int _maxlines = (int) maxlines; + int _maxlines = static_cast(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 l(*mutex_local); - bool _enable = (bool) enable; + bool _enable = static_cast(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 l(global_mutex); + pEpLog("called with lock_guard"); + mutex_local = get_engine_java_object_mutex(env, obj); + } + std::lock_guard 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" diff --git a/src/foundation_pEp_jniadapter_AbstractEngine.cc b/src/cxx/foundation_pEp_jniadapter_AbstractEngine.cc similarity index 72% rename from src/foundation_pEp_jniadapter_AbstractEngine.cc rename to src/cxx/foundation_pEp_jniadapter_AbstractEngine.cc index f5e729a..e1c8a03 100644 --- a/src/foundation_pEp_jniadapter_AbstractEngine.cc +++ b/src/cxx/foundation_pEp_jniadapter_AbstractEngine.cc @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -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(&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(&thread_env), nullptr); #endif } assert(status >= 0); @@ -68,45 +65,60 @@ namespace JNISync { void jni_init() { - JNIEnv *_env = JNISync::env(); - - messageClass = reinterpret_cast( - _env->NewGlobalRef(findClass(_env, "foundation/pEp/jniadapter/Message"))); - identityClass = reinterpret_cast( - _env->NewGlobalRef(findClass(_env, "foundation/pEp/jniadapter/_Identity"))); - signalClass = reinterpret_cast( - _env->NewGlobalRef(findClass(_env, "foundation/pEp/jniadapter/SyncHandshakeSignal"))); - passphraseTypeClass = reinterpret_cast( - _env->NewGlobalRef(findClass(_env, "foundation/pEp/jniadapter/PassphraseType"))); - engineClass = reinterpret_cast(_env->NewGlobalRef(findClass(_env, "foundation/pEp/jniadapter/Engine"))); - - messageConstructorMethodID = _env->GetMethodID(messageClass, "", "(J)V"); + JNIEnv * _env = JNISync::env(); + + messageClass = static_cast(_env->NewGlobalRef(findClass(_env, "foundation/pEp/jniadapter/Message"))); + identityClass = static_cast(_env->NewGlobalRef(findClass(_env, "foundation/pEp/jniadapter/_Identity"))); + signalClass = static_cast(_env->NewGlobalRef(findClass(_env, "foundation/pEp/jniadapter/SyncHandshakeSignal"))); + passphraseTypeClass = static_cast(_env->NewGlobalRef(findClass(_env, "foundation/pEp/jniadapter/PassphraseType"))); + engineClass = static_cast(_env->NewGlobalRef(findClass(_env, "foundation/pEp/jniadapter/Engine"))); + + messageConstructorMethodID = _env->GetMethodID( + messageClass, + "", + "(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(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(status)) { status_ = element; break; } @@ -142,7 +153,7 @@ char* JNIAdapter::passphraseRequiredCallback(const PEP_STATUS status) { JNISync::env()->ExceptionClear(); } - jbyteArray ppJBA = reinterpret_cast(ppJO); + jbyteArray ppJBA = static_cast(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 l(mutex_obj); + std::lock_guard 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(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 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(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(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 l(global_mutex); // global mutex for write access to 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 l(global_mutex); // global mutex for write access to pEpLog("called"); @@ -281,10 +290,8 @@ JNIEXPORT jboolean JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_getDebu return static_cast(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 * > (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 * > (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 * > (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(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(env->GetLongField(obj, thread_handle)); if (thread) return; - thread = (pthread_t *) calloc(1, sizeof(pthread_t)); + thread = static_cast(calloc(1, sizeof(pthread_t))); assert(thread); - env->SetLongField(obj, thread_handle, (jlong) thread); + env->SetLongField(obj, thread_handle, reinterpret_cast(thread)); queue = new locked_queue< pEp_identity * >(); - env->SetLongField(obj, queue_handle, (jlong) queue); + env->SetLongField(obj, queue_handle, reinterpret_cast(queue)); - register_examine_function(Adapter::session(), examine_identity, (void *) queue); + register_examine_function(Adapter::session(), examine_identity,static_cast(queue)); - pthread_create(thread, nullptr, keyserver_thread_routine, (void *) queue); + pthread_create(thread, nullptr, keyserver_thread_routine, static_cast(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(env->GetLongField(obj, thread_handle)); if (!thread) return; - queue = (locked_queue< pEp_identity * > *) env->GetLongField(obj, queue_handle); + queue = reinterpret_cast*>(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(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 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 l(*mutex_local); - return (jboolean) Adapter::is_sync_running(); + return static_cast(Adapter::is_sync_running()); } } // extern "C" diff --git a/src/foundation_pEp_jniadapter__Blob.cc b/src/cxx/foundation_pEp_jniadapter__Blob.cc similarity index 55% rename from src/foundation_pEp_jniadapter__Blob.cc rename to src/cxx/foundation_pEp_jniadapter__Blob.cc index 8dfbf43..713d2d6 100644 --- a/src/foundation_pEp_jniadapter__Blob.cc +++ b/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(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(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" diff --git a/src/get_header.cc b/src/cxx/get_header.cc similarity index 100% rename from src/get_header.cc rename to src/cxx/get_header.cc diff --git a/src/identity_api.cc b/src/cxx/identity_api.cc similarity index 56% rename from src/identity_api.cc rename to src/cxx/identity_api.cc index eb8521e..c9b850f 100644 --- a/src/identity_api.cc +++ b/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(comm_type)); } } // extern "C" diff --git a/src/cxx/jniutils.cc b/src/cxx/jniutils.cc new file mode 100644 index 0000000..27f2438 --- /dev/null +++ b/src/cxx/jniutils.cc @@ -0,0 +1,795 @@ +#include +#include "jniutils.hh" +#include + +#ifndef __LP64__ + +#include + +#define time_t time64_t +#define timegm timegm64 +#define gmtime_r gmtime64_r +#else +#include +#endif + +namespace pEp { +namespace JNIAdapter { + +std::mutex global_mutex; +std::unordered_map engine_objid_mutex; + +std::mutex *get_engine_java_object_mutex(JNIEnv *env, + jobject obj) +{ + long engine_obj_id = static_cast(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(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(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, "", "(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(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, "", "()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(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, "", "()V"); + assert(constructor); + jmethodID constructor_pair = env->GetMethodID(clazz_pair, "", "(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(env->GetObjectField(pair, first_id)); + jbyteArray second = static_cast(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, "", "(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(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(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(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, "", "()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(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(ident->me)); + + jfieldID flags_id = getFieldID(env, classname, "flags", "I"); + env->SetIntField(obj, flags_id, static_cast(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, "", "()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(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(ident->me)); + + jfieldID flags_id = getFieldID(env, classname, "flags", "I", identityClass); + env->SetIntField(obj, flags_id, static_cast(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(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(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(env->GetBooleanField(obj, me_id)); + + jfieldID flags_id = getFieldID(env, classname, "flags", "I"); + ident->flags = static_cast(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, "", "()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, "", "()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(b->size)); + env->SetByteArrayRegion(_data, 0, b->size, reinterpret_cast(b->value)); + env->SetObjectField(obj, fieldID, static_cast(_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, "", "()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(env->GetObjectField(obj, data_id)); + size_t size = static_cast(env->GetArrayLength(_data)); + char *b = static_cast(malloc(size)); + assert(b); + + env->GetByteArrayRegion(_data, 0, size, reinterpret_cast(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(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(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(env->GetIntField(obj, field_value)); +} +}; +}; + diff --git a/src/cxx/jniutils.hh b/src/cxx/jniutils.hh new file mode 100644 index 0000000..747d55a --- /dev/null +++ b/src/cxx/jniutils.hh @@ -0,0 +1,147 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if 0 // Enable if log needed +#include +#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 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); +}; +}; + diff --git a/src/cxx/passphrase_callback.hh b/src/cxx/passphrase_callback.hh new file mode 100644 index 0000000..9906491 --- /dev/null +++ b/src/cxx/passphrase_callback.hh @@ -0,0 +1,15 @@ +#pragma once + +#include + + +namespace pEp { +namespace JNIAdapter { + +char *passphraseRequiredCallback(const PEP_STATUS status); +template PEP_STATUS passphraseWrap(PEP_STATUS f(PEP_SESSION, A...), PEP_SESSION session, A... a); + +} +} + +#include "passphrase_callback.hxx" \ No newline at end of file diff --git a/src/cxx/passphrase_callback.hxx b/src/cxx/passphrase_callback.hxx new file mode 100644 index 0000000..8cc8417 --- /dev/null +++ b/src/cxx/passphrase_callback.hxx @@ -0,0 +1,42 @@ +#pragma once + +#include "passphrase_callback.hh" + +namespace pEp { +namespace JNIAdapter { + +template 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; +} +} +} \ No newline at end of file diff --git a/src/foundation/pEp/jniadapter/Engine.java.target b/src/foundation/pEp/jniadapter/Engine.java.target deleted file mode 100644 index 7708586..0000000 --- a/src/foundation/pEp/jniadapter/Engine.java.target +++ /dev/null @@ -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 extra, - Message.EncFormat enc_format - ) throws pEpException; - - public class DecryptResult { - public Message dst; - public Color color; - } - - public native DecryptResult decrypt_message( - Message src, - ArrayList keylist - ) throws pEpException; - - public native Color outgoing_message_color( - Message msg - ) throws pEpException; -} diff --git a/src/foundation/pEp/jniadapter/Message.java.target b/src/foundation/pEp/jniadapter/Message.java.target deleted file mode 100644 index 6cdc3e6..0000000 --- a/src/foundation/pEp/jniadapter/Message.java.target +++ /dev/null @@ -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 tag = - new HashMap(); - } - - 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 tag = - new HashMap(); - } - - 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 tag = - new HashMap(); - } - - 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 getAttachments(); - public native void setAttachments(ArrayList 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 getTo(); - public native void setTo(ArrayList value); - - public native Identity getRecvBy(); - public native void setRecvBy(Identity value); - - public native ArrayList getCc(); - public native void setCc(ArrayList value); - - public native ArrayList getBcc(); - public native void setBcc(ArrayList value); - - public native ArrayList getReplyTo(); - public native void setReplyTo(ArrayList value); - - private native ArrayList _getInReplyTo(); - private native void _setInReplyTo(ArrayList value); - public ArrayList getInReplyTo() { - return AbstractEngine.toUTF16(_getInReplyTo()); - } - public void setInReplyTo(ArrayList value) { - _setInReplyTo(AbstractEngine.toUTF8(value)); - } - - private native ArrayList _getReferences(); - private native void _setReferences(ArrayList value); - public ArrayList getReferences() { - return AbstractEngine.toUTF16(_getReferences()); - } - public void setReferences(ArrayList value) { - _setReferences(AbstractEngine.toUTF8(value)); - } - - private native ArrayList _getKeywords(); - private native void _setKeywords(ArrayList value); - public ArrayList getKeywords() { - return AbstractEngine.toUTF16(_getKeywords()); - } - public void setKeywords(ArrayList 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> _getOptFields(); - private native void _setOptFields(Vector> value); - public Vector> getOptFields() { - return AbstractEngine.toUTF16(_getOptFields()); - } - public void setOptFields(Vector> value) { - _setOptFields(AbstractEngine.toUTF8(value)); - } - - public native Message.EncFormat getEncFormat(); - public native void setEncFormat(Message.EncFormat value); - -} diff --git a/src/foundation/pEp/jniadapter/UniquelyIdentifiable.java b/src/foundation/pEp/jniadapter/UniquelyIdentifiable.java deleted file mode 100644 index d599e9c..0000000 --- a/src/foundation/pEp/jniadapter/UniquelyIdentifiable.java +++ /dev/null @@ -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; - } -} diff --git a/src/gen_java_Message.ysl2 b/src/gen_java_Message.ysl2 deleted file mode 100644 index a16658a..0000000 --- a/src/gen_java_Message.ysl2 +++ /dev/null @@ -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 intMap; - - private «$jname»(int value) { - this.value = value; - } - - public static «$jname» getByInt(int value){ - if (intMap == null) { - intMap = new HashMap(); - 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 - otherwise > _«$ename» - } - const "convget" choose { - when "$ctype = 'stringlist'" > AbstractEngine.toUTF16(i) - when "$ctype = 'stringpairlist'" > new Pair(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(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()" > , ` - } -} - diff --git a/src/gen_java_exceptions.ysl2 b/src/gen_java_exceptions.ysl2 deleted file mode 100644 index ecdca21..0000000 --- a/src/gen_java_exceptions.ysl2 +++ /dev/null @@ -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(.)"; -} - diff --git a/src/gen_throw_pEp_exception.ysl2 b/src/gen_throw_pEp_exception.ysl2 deleted file mode 100644 index 3c9d3ad..0000000 --- a/src/gen_throw_pEp_exception.ysl2 +++ /dev/null @@ -1,64 +0,0 @@ -include yslt.yml2 - -tstylesheet { - include ./textutils.ysl2 - - template "/" { - apply "namespace", 0; - document "throw_pEp_exception.hh", "text" - || - #pragma once - - #include - - namespace pEp { - namespace JNIAdapter { - jint throw_pEp_Exception(JNIEnv *env, PEP_STATUS status); - }; - }; - - || - - } - - template "namespace" - || - #include - #include - #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; - } -} - diff --git a/src/foundation/pEp/jniadapter/AbstractEngine.java b/src/java/foundation/pEp/jniadapter/AbstractEngine.java similarity index 56% rename from src/foundation/pEp/jniadapter/AbstractEngine.java rename to src/java/foundation/pEp/jniadapter/AbstractEngine.java index 9a3b466..b7aba8b 100644 --- a/src/foundation/pEp/jniadapter/AbstractEngine.java +++ b/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 toUTF8(Vector list) { - if (list == null) - return null; - - Vector result = new Vector(list.size()); + private native String _getVersion(); - for (int i=0; i toUTF8(Pair pair) { - if (pair == null) - return null; - - Pair result = new Pair(); + private native String _getProtocolVersion(); - result.first = toUTF8(pair.first); - result.second = toUTF8(pair.second); - return result; + public void startKeyserverLookup() { + _startKeyserverLookup(); } - public static ArrayList> toUTF8(ArrayList> list) { - if (list == null) - return null; + private native void _startKeyserverLookup(); - ArrayList> result = new ArrayList>(list.size()); - - for (int i=0; i toUTF16(Vector list) { - if (list == null) - return null; + private native void _startSync(); - Vector result = new Vector(list.size()); - - for (int i=0; i toUTF16(Pair pair) { - if (pair == null) - return null; - - Pair result = new Pair(); - - result.first = toUTF16(pair.first); - result.second = toUTF16(pair.second); + private native void _stopSync(); - return result; + public boolean isSyncRunning() { + return _isSyncRunning(); } - public static ArrayList> toUTF16(ArrayList> list) { - if (list == null) - return null; - - ArrayList> result = new ArrayList>(list.size()); - - for (int i=0; i> opts = new ArrayList<>(); Pair 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()); } diff --git a/src/foundation/pEp/jniadapter/Blob.java b/src/java/foundation/pEp/jniadapter/Blob.java similarity index 68% rename from src/foundation/pEp/jniadapter/Blob.java rename to src/java/foundation/pEp/jniadapter/Blob.java index f246e0c..4fdffa4 100644 --- a/src/foundation/pEp/jniadapter/Blob.java +++ b/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); - } } diff --git a/src/foundation/pEp/jniadapter/CommType.java b/src/java/foundation/pEp/jniadapter/CommType.java similarity index 100% rename from src/foundation/pEp/jniadapter/CommType.java rename to src/java/foundation/pEp/jniadapter/CommType.java diff --git a/src/foundation/pEp/jniadapter/Identity.java b/src/java/foundation/pEp/jniadapter/Identity.java similarity index 58% rename from src/foundation/pEp/jniadapter/Identity.java rename to src/java/foundation/pEp/jniadapter/Identity.java index 756102c..8b69007 100644 --- a/src/foundation/pEp/jniadapter/Identity.java +++ b/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 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; + } } diff --git a/src/foundation/pEp/jniadapter/Pair.java b/src/java/foundation/pEp/jniadapter/Pair.java similarity index 56% rename from src/foundation/pEp/jniadapter/Pair.java rename to src/java/foundation/pEp/jniadapter/Pair.java index 9db1afe..7e9c4d4 100644 --- a/src/foundation/pEp/jniadapter/Pair.java +++ b/src/java/foundation/pEp/jniadapter/Pair.java @@ -10,5 +10,11 @@ public class Pair { first = f; second = s; } + + public String toString() { + String ret=""; + ret += "'" + first.toString() + "' : '" + second.toString() + "'"; + return ret; + } } diff --git a/src/foundation/pEp/jniadapter/Sync.java b/src/java/foundation/pEp/jniadapter/Sync.java similarity index 77% rename from src/foundation/pEp/jniadapter/Sync.java rename to src/java/foundation/pEp/jniadapter/Sync.java index 7593477..21f28e0 100644 --- a/src/foundation/pEp/jniadapter/Sync.java +++ b/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"); diff --git a/src/java/foundation/pEp/jniadapter/UniquelyIdentifiable.java b/src/java/foundation/pEp/jniadapter/UniquelyIdentifiable.java new file mode 100644 index 0000000..39d8004 --- /dev/null +++ b/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; + } +} diff --git a/src/java/foundation/pEp/jniadapter/Utils.java b/src/java/foundation/pEp/jniadapter/Utils.java new file mode 100644 index 0000000..709998f --- /dev/null +++ b/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 toUTF8(Vector list) { + if (list == null) + return null; + + Vector result = new Vector(list.size()); + + for (int i=0; i toUTF8(Pair pair) { + if (pair == null) + return null; + + Pair result = new Pair(); + + result.first = toUTF8(pair.first); + result.second = toUTF8(pair.second); + + return result; + } + + public static ArrayList> toUTF8(ArrayList> list) { + if (list == null) + return null; + + ArrayList> result = new ArrayList>(list.size()); + + for (int i=0; i toUTF16(Vector list) { + if (list == null) + return null; + + Vector result = new Vector(list.size()); + + for (int i=0; i toUTF16(Pair pair) { + if (pair == null) + return null; + + Pair result = new Pair(); + + result.first = toUTF16(pair.first); + result.second = toUTF16(pair.second); + + return result; + } + + public static ArrayList> toUTF16(ArrayList> list) { + if (list == null) + return null; + + ArrayList> result = new ArrayList>(list.size()); + + for (int i=0; i -#include "jniutils.hh" -#include -#ifndef __LP64__ -#include -#define time_t time64_t -#define timegm timegm64 -#define gmtime_r gmtime64_r -#else -#include -#endif - -namespace pEp { - namespace JNIAdapter { - std::mutex global_mutex; - std::unordered_map 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, "", "(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, "", "()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(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, "", "()V"); - assert(constructor); - jmethodID constructor_pair = env->GetMethodID(clazz_pair, "", - "(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(env->GetObjectField(pair, - first_id)); - jbyteArray second = - reinterpret_cast(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, "", "(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(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(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, "", "()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, "", "()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(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, "", "()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, "", "()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(_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, "", "()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(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); - } - }; -}; - diff --git a/src/jniutils.hh b/src/jniutils.hh deleted file mode 100644 index 54fcfb2..0000000 --- a/src/jniutils.hh +++ /dev/null @@ -1,130 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if 0 // Enable if log needed -#include -#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 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); - }; -}; - diff --git a/src/passphrase_callback.hh b/src/passphrase_callback.hh deleted file mode 100644 index e0f9804..0000000 --- a/src/passphrase_callback.hh +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include - - -namespace pEp { - namespace JNIAdapter { - - char* passphraseRequiredCallback(const PEP_STATUS status); - - template PEP_STATUS passphraseWrap(PEP_STATUS f(PEP_SESSION, A...), PEP_SESSION session, A... a); - } -} - -#include "passphrase_callback.hxx" \ No newline at end of file diff --git a/src/passphrase_callback.hxx b/src/passphrase_callback.hxx deleted file mode 100644 index e812841..0000000 --- a/src/passphrase_callback.hxx +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "passphrase_callback.hh" - -namespace pEp { - namespace JNIAdapter { - - template 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; - } - } -} \ No newline at end of file diff --git a/test/java/foundation/pEp/jniadapter/test/Makefile b/test/java/foundation/pEp/jniadapter/test/Makefile index 8052adc..67c4354 100644 --- a/test/java/foundation/pEp/jniadapter/test/Makefile +++ b/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 diff --git a/test/java/foundation/pEp/jniadapter/test/Makefile.conf b/test/java/foundation/pEp/jniadapter/test/Makefile.conf index 0ee4a7b..79ac8d4 100644 --- a/test/java/foundation/pEp/jniadapter/test/Makefile.conf +++ b/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 diff --git a/test/java/foundation/pEp/jniadapter/test/basic/TestMain.java b/test/java/foundation/pEp/jniadapter/test/basic/TestMain.java index d1f290c..539b377 100644 --- a/test/java/foundation/pEp/jniadapter/test/basic/TestMain.java +++ b/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 { diff --git a/test/java/foundation/pEp/jniadapter/test/jni100/TestMain.java b/test/java/foundation/pEp/jniadapter/test/jni100/TestMain.java index 2a0ddd8..28e4df0 100644 --- a/test/java/foundation/pEp/jniadapter/test/jni100/TestMain.java +++ b/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(), Message.EncFormat.PEP); ctx.engine.key_reset_all_own_keys(); diff --git a/test/java/foundation/pEp/jniadapter/test/jni111/TestAlice.java b/test/java/foundation/pEp/jniadapter/test/jni111/TestAlice.java index 429c361..d5dea18 100644 --- a/test/java/foundation/pEp/jniadapter/test/jni111/TestAlice.java +++ b/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; } } diff --git a/test/java/foundation/pEp/jniadapter/test/jni114/TestAlice.java b/test/java/foundation/pEp/jniadapter/test/jni114/TestAlice.java index e6a753a..f307984 100644 --- a/test/java/foundation/pEp/jniadapter/test/jni114/TestAlice.java +++ b/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.*; diff --git a/test/java/foundation/pEp/jniadapter/test/jni115/TestAlice.java b/test/java/foundation/pEp/jniadapter/test/jni115/TestAlice.java index fb82385..446f76a 100644 --- a/test/java/foundation/pEp/jniadapter/test/jni115/TestAlice.java +++ b/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 messagesToBobSmall; @@ -19,7 +21,7 @@ class Jni115TestContext extends AdapterBaseTestContext { public List 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; } } diff --git a/test/java/foundation/pEp/jniadapter/test/jni117/Makefile b/test/java/foundation/pEp/jniadapter/test/jni117/Makefile new file mode 100644 index 0000000..8c8748e --- /dev/null +++ b/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 diff --git a/test/java/foundation/pEp/jniadapter/test/jni117/TestAlice.java b/test/java/foundation/pEp/jniadapter/test/jni117/TestAlice.java new file mode 100644 index 0000000..597eb74 --- /dev/null +++ b/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("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(); + } +} + + diff --git a/test/java/foundation/pEp/jniadapter/test/jni118/Makefile b/test/java/foundation/pEp/jniadapter/test/jni118/Makefile new file mode 100644 index 0000000..d9d921c --- /dev/null +++ b/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 diff --git a/test/java/foundation/pEp/jniadapter/test/jni118/TestAlice.java b/test/java/foundation/pEp/jniadapter/test/jni118/TestAlice.java new file mode 100644 index 0000000..7f3380d --- /dev/null +++ b/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 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 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(), 0); + if (msgToBobEncrypted == null) { + throw new RuntimeException("Context failure, error decrypting message"); + } + return this; + } + + public void addRatingToOptFields(Message msg, String ratingStr) { + ArrayList> opts = msg.getOptFields(); + opts.add(new Pair("X-EncStatus",ratingStr)); + msg.setOptFields(opts); + } + + public void addRcptsToOptFields(Message msg, String fprs) { + ArrayList> opts = msg.getOptFields(); + opts.add(new Pair("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("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("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(); + } +} + + diff --git a/test/java/foundation/pEp/jniadapter/test/jni119/Makefile b/test/java/foundation/pEp/jniadapter/test/jni119/Makefile new file mode 100644 index 0000000..329571b --- /dev/null +++ b/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 diff --git a/test/java/foundation/pEp/jniadapter/test/jni119/TestAlice.java b/test/java/foundation/pEp/jniadapter/test/jni119/TestAlice.java new file mode 100644 index 0000000..304732b --- /dev/null +++ b/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("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()); + }); + + new TestUnit("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 grpIdents = new Vector(); + grpIdents.add(ctx.alice); + grpIdents.add(ctx.bob); + + ctx.engine.enter_device_group(grpIdents); + }); + + TestSuite.getDefault().run(); + } +} + + diff --git a/test/java/foundation/pEp/jniadapter/test/jni125/Makefile b/test/java/foundation/pEp/jniadapter/test/jni125/Makefile index 6e3eec4..e97b00d 100644 --- a/test/java/foundation/pEp/jniadapter/test/jni125/Makefile +++ b/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) diff --git a/test/java/foundation/pEp/jniadapter/test/jni88/TestMain.java b/test/java/foundation/pEp/jniadapter/test/jni88/TestMain.java index bc53fb5..68a15a6 100644 --- a/test/java/foundation/pEp/jniadapter/test/jni88/TestMain.java +++ b/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; diff --git a/test/java/foundation/pEp/jniadapter/test/jni91/TestMain.java b/test/java/foundation/pEp/jniadapter/test/jni91/TestMain.java index 0f01ccf..be7f75d 100644 --- a/test/java/foundation/pEp/jniadapter/test/jni91/TestMain.java +++ b/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; diff --git a/test/java/foundation/pEp/jniadapter/test/jni92/TestMain.java b/test/java/foundation/pEp/jniadapter/test/jni92/TestMain.java index 5a9d3c7..62654f9 100644 --- a/test/java/foundation/pEp/jniadapter/test/jni92/TestMain.java +++ b/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 ev, Consumer 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); }); } diff --git a/test/java/foundation/pEp/jniadapter/test/jni98/TestMain.java b/test/java/foundation/pEp/jniadapter/test/jni98/TestMain.java index a8327e1..75cd06f 100644 --- a/test/java/foundation/pEp/jniadapter/test/jni98/TestMain.java +++ b/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(), 0); log("\n" + msgToString(result.dst, false)); }).run(); diff --git a/test/java/foundation/pEp/jniadapter/test/regression/TestMain.java b/test/java/foundation/pEp/jniadapter/test/regression/TestMain.java index f211897..89b30f7 100644 --- a/test/java/foundation/pEp/jniadapter/test/regression/TestMain.java +++ b/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 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(), 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> opts = msg.getOptFields(); + opts.add(new Pair("X-EncStatus",ratingStr)); + msg.setOptFields(opts); + } + + public void addRcptsToOptFields(Message msg, String fprs) { + ArrayList> opts = msg.getOptFields(); + opts.add(new Pair("X-KeyList", fprs)); + msg.setOptFields(opts); + } + +} + class TestMain { public static void main(String[] args) { TestSuite.getDefault().setVerbose(false); - new TestUnit("Engine.myself", new RegTestContext(), ctx -> { + new TestUnit("Engine.myself", new AdapterBaseTestContext(), ctx -> { ctx.alice = ctx.engine.myself(ctx.alice); }); - new TestUnit("Engine.encrypt_message", new RegTestContext(), ctx -> { + new TestUnit("Engine.encrypt_message", new AdapterBaseTestContext(), ctx -> { ctx.engine.encrypt_message(ctx.msgToBob, null, Message.EncFormat.PEP); }); - new TestUnit("Engine.encrypt_message_and_add_priv_key", new RegTestContext(), ctx -> { - ctx.alice = ctx.engine.myself(ctx.alice); + new TestUnit("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("Engine.encrypt_message_for_self", new RegTestContext(), ctx -> { - ctx.alice = ctx.engine.myself(ctx.alice); + new TestUnit("Engine.encrypt_message_for_self", new CTXAlice(), ctx -> { ctx.engine.encrypt_message_for_self(ctx.alice, ctx.msgToSelf, null); }); - new TestUnit("Engine.decrypt_message", new RegTestContext(), ctx -> { - ctx.engine.decrypt_message(ctx.msgToSelf, ctx.vStr, 0); + new TestUnit("Engine.decrypt_message", new AdapterBaseTestContext(), ctx -> { + ctx.engine.decrypt_message(ctx.msgToSelf, new Vector(), 0); }); - //TODO: Coredump -// new TestUnit("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("Engine.re_evaluate_message_rating", new CTXReEvaluateMessageRating(), ctx -> { + ctx.engine.re_evaluate_message_rating(ctx.msgToBobDecrypted); + }); - new TestUnit("Engine.outgoing_message_rating", new RegTestContext(), ctx -> { + new TestUnit("Engine.outgoing_message_rating", new AdapterBaseTestContext(), ctx -> { ctx.engine.outgoing_message_rating(ctx.msgToBob); }); - new TestUnit("Engine.outgoing_message_rating_preview", new RegTestContext(), ctx -> { + new TestUnit("Engine.outgoing_message_rating_preview", new AdapterBaseTestContext(), ctx -> { ctx.engine.outgoing_message_rating_preview(ctx.msgToBob); }); - new TestUnit("Engine.get_identity", new RegTestContext(), ctx -> { - ctx.alice = ctx.engine.myself(ctx.alice); + new TestUnit("Engine.get_identity", new CTXAlice(), ctx -> { ctx.engine.get_identity(ctx.alice.address, ctx.alice.user_id); }); - new TestUnit("Engine.identity_rating", new RegTestContext(), ctx -> { - ctx.alice = ctx.engine.myself(ctx.alice); + new TestUnit("Engine.identity_rating", new CTXAlice(), ctx -> { ctx.engine.identity_rating(ctx.alice); }); - new TestUnit("Engine.blacklist_retrieve", new RegTestContext(), ctx -> { + new TestUnit("Engine.blacklist_retrieve", new AdapterBaseTestContext(), ctx -> { ctx.engine.blacklist_retrieve(); }); - //FAIL - new TestUnit("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("Engine.own_message_private_key_details", new CTXAlice2(), ctx -> { +// ctx.engine.own_message_private_key_details(ctx.msgToSelf); +// }); - new TestUnit("Engine.OpenPGP_list_keyinfo", new RegTestContext(), ctx -> { + new TestUnit("Engine.OpenPGP_list_keyinfo", new AdapterBaseTestContext(), ctx -> { ctx.engine.OpenPGP_list_keyinfo(""); }); - new TestUnit("Engine.set_identity_flags", new RegTestContext(), ctx -> { + new TestUnit("Engine.set_identity_flags", new AdapterBaseTestContext(), ctx -> { ctx.engine.set_identity_flags(ctx.alice, 0); }); - new TestUnit("Engine.unset_identity_flags", new RegTestContext(), ctx -> { + new TestUnit("Engine.unset_identity_flags", new AdapterBaseTestContext(), ctx -> { ctx.engine.unset_identity_flags(ctx.alice, 0); }); - new TestUnit("Engine.own_identities_retrieve", new RegTestContext(), ctx -> { + new TestUnit("Engine.own_identities_retrieve", new AdapterBaseTestContext(), ctx -> { ctx.engine.own_identities_retrieve(); }); - new TestUnit("Engine.get_trustwords", new RegTestContext(), ctx -> { - ctx.alice = ctx.engine.myself(ctx.alice); - ctx.bob = ctx.engine.myself(ctx.bob); + new TestUnit("Engine.get_trustwords", new CTXAlice2(), ctx -> { ctx.engine.get_trustwords(ctx.alice, ctx.bob, "en", false); }); - new TestUnit("Engine.get_trustwords_for_fprs", new RegTestContext(), ctx -> { - ctx.alice = ctx.engine.myself(ctx.alice); - ctx.bob = ctx.engine.myself(ctx.bob); - + new TestUnit("Engine.get_trustwords_for_fprs", new CTXAlice2(), ctx -> { ctx.engine.get_trustwords_for_fprs(ctx.alice.fpr, ctx.bob.fpr, "en", false); }); - new TestUnit("Engine.get_message_trustwords", new RegTestContext(), ctx -> { + new TestUnit("Engine.get_message_trustwords", new AdapterBaseTestContext(), ctx -> { ctx.engine.get_message_trustwords(ctx.msgToBob, null, ctx.bob, "en", false); }); - new TestUnit("Engine.get_languagelist", new RegTestContext(), ctx -> { + new TestUnit("Engine.get_languagelist", new AdapterBaseTestContext(), ctx -> { ctx.engine.get_languagelist(); }); - new TestUnit("Engine.key_reset_trust", new RegTestContext(), ctx -> { - ctx.alice = ctx.engine.myself(ctx.alice); + new TestUnit("Engine.key_reset_trust", new CTXAlice(), ctx -> { ctx.engine.key_reset_trust(ctx.alice); }); - new TestUnit("Engine.key_reset_identity", new RegTestContext(), ctx -> { - ctx.alice = ctx.engine.myself(ctx.alice); + new TestUnit("Engine.key_reset_identity", new CTXAlice(), ctx -> { ctx.engine.key_reset_identity(ctx.alice, ""); }); - new TestUnit("Engine.key_reset_user", new RegTestContext(), ctx -> { - ctx.alice = ctx.engine.myself(ctx.alice); + new TestUnit("Engine.key_reset_user", new CTXAlice(), ctx -> { ctx.engine.key_reset_user("fsdjugsh", ctx.alice.fpr); }); - new TestUnit("Engine.key_reset_all_own_keys", new RegTestContext(), ctx -> { + new TestUnit("Engine.key_reset_all_own_keys", new AdapterBaseTestContext(), ctx -> { ctx.engine.key_reset_all_own_keys(); }); - new TestUnit("Engine.deliverHandshakeResult", new RegTestContext(), ctx -> { - ctx.engine.deliverHandshakeResult(SyncHandshakeResult.SyncHandshakeCancel, ctx.vID); - }); - +// TODO: FAILS +// new TestUnit("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("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("Engine.leave_device_group", new AdapterBaseTestContext(), ctx -> { // ctx.engine.startSync(); // ctx.engine.leave_device_group(); // }); - new TestUnit("Engine.enable_identity_for_sync", new RegTestContext(), ctx -> { - ctx.alice = ctx.engine.myself(ctx.alice); + new TestUnit("Engine.enable_identity_for_sync", new CTXAlice(), ctx -> { ctx.engine.enable_identity_for_sync(ctx.alice); }); - new TestUnit("Engine.disable_identity_for_sync", new RegTestContext(), ctx -> { - ctx.alice = ctx.engine.myself(ctx.alice); + new TestUnit("Engine.disable_identity_for_sync", new CTXAlice(), ctx -> { ctx.engine.disable_identity_for_sync(ctx.alice); }); - new TestUnit("Engine.config_cipher_suite", new RegTestContext(), ctx -> { + new TestUnit("Engine.config_cipher_suite", new AdapterBaseTestContext(), ctx -> { ctx.engine.config_cipher_suite(CipherSuite.pEpCipherSuiteDefault); }); - new TestUnit("Engine.trustwords", new RegTestContext(), ctx -> { + new TestUnit("Engine.trustwords", new AdapterBaseTestContext(), ctx -> { ctx.engine.trustwords(ctx.alice); }); - new TestUnit("Engine.updateIdentity", new RegTestContext(), ctx -> { + new TestUnit("Engine.updateIdentity", new AdapterBaseTestContext(), ctx -> { ctx.engine.updateIdentity(ctx.alice); }); - new TestUnit("Engine.setOwnKey", new RegTestContext(), ctx -> { - ctx.alice = ctx.engine.myself(ctx.alice); + new TestUnit("Engine.setOwnKey", new CTXAlice(), ctx -> { ctx.engine.setOwnKey(ctx.alice, ctx.alice.fpr); }); - new TestUnit("Engine.keyMistrusted", new RegTestContext(), ctx -> { - ctx.alice = ctx.engine.myself(ctx.alice); + new TestUnit("Engine.keyMistrusted", new CTXAlice(), ctx -> { ctx.engine.keyMistrusted(ctx.alice); }); - new TestUnit("Engine.keyResetTrust", new RegTestContext(), ctx -> { + new TestUnit("Engine.keyResetTrust", new AdapterBaseTestContext(), ctx -> { ctx.engine.keyResetTrust(ctx.alice); }); - new TestUnit("Engine.trustPersonalKey", new RegTestContext(), ctx -> { + new TestUnit("Engine.trustPersonalKey", new AdapterBaseTestContext(), ctx -> { ctx.engine.trustPersonalKey(ctx.alice); }); - new TestUnit("Engine.trustOwnKey", new RegTestContext(), ctx -> { - ctx.alice = ctx.engine.myself(ctx.alice); + new TestUnit("Engine.trustOwnKey", new CTXAlice(), ctx -> { ctx.engine.trustOwnKey(ctx.alice); }); - new TestUnit("Engine.importKey", new RegTestContext(), ctx -> { + new TestUnit("Engine.importKey", new AdapterBaseTestContext(), ctx -> { ctx.engine.importKey(ctx.keyBobPub); }); - new TestUnit("Engine.blacklist_add", new RegTestContext(), ctx -> { + new TestUnit("Engine.blacklist_add", new AdapterBaseTestContext(), ctx -> { ctx.engine.blacklist_add("43"); }); - new TestUnit("Engine.blacklist_delete", new RegTestContext(), ctx -> { + new TestUnit("Engine.blacklist_delete", new AdapterBaseTestContext(), ctx -> { ctx.engine.blacklist_delete("43"); }); - new TestUnit("Engine.blacklist_is_listed", new RegTestContext(), ctx -> { + new TestUnit("Engine.blacklist_is_listed", new AdapterBaseTestContext(), ctx -> { ctx.engine.blacklist_is_listed("43"); }); - new TestUnit("Engine.config_passive_mode", new RegTestContext(), ctx -> { + new TestUnit("Engine.config_passive_mode", new AdapterBaseTestContext(), ctx -> { ctx.engine.config_passive_mode(false); }); - new TestUnit("Engine.config_unencrypted_subject", new RegTestContext(), ctx -> { + new TestUnit("Engine.config_unencrypted_subject", new AdapterBaseTestContext(), ctx -> { ctx.engine.config_unencrypted_subject(false); }); - new TestUnit("Engine.getCrashdumpLog", new RegTestContext(), ctx -> { + new TestUnit("Engine.getCrashdumpLog", new AdapterBaseTestContext(), ctx -> { ctx.engine.getCrashdumpLog(0); }); - new TestUnit("Engine.getUserDirectory", new RegTestContext(), ctx -> { + new TestUnit("Engine.getUserDirectory", new AdapterBaseTestContext(), ctx -> { ctx.engine.getUserDirectory(); }); - new TestUnit("Engine.getMachineDirectory", new RegTestContext(), ctx -> { + new TestUnit("Engine.getMachineDirectory", new AdapterBaseTestContext(), ctx -> { ctx.engine.getMachineDirectory(); }); // AbstractEngine.java - new TestUnit("Engine.close", new RegTestContext(), ctx -> { + new TestUnit("Engine.close", new AdapterBaseTestContext(), ctx -> { ctx.engine.close(); }); - new TestUnit("Engine.getVersion", new RegTestContext(), ctx -> { + new TestUnit("Engine.getVersion", new AdapterBaseTestContext(), ctx -> { ctx.engine.getVersion(); }); - new TestUnit("Engine.getProtocolVersion", new RegTestContext(), ctx -> { + new TestUnit("Engine.getProtocolVersion", new AdapterBaseTestContext(), ctx -> { ctx.engine.getProtocolVersion(); }); - new TestUnit("Engine.startKeyserverLookup", new RegTestContext(), ctx -> { + new TestUnit("Engine.startKeyserverLookup", new AdapterBaseTestContext(), ctx -> { ctx.engine.startKeyserverLookup(); }); - new TestUnit("Engine.startSync", new RegTestContext(), ctx -> { + new TestUnit("Engine.startSync", new AdapterBaseTestContext(), ctx -> { ctx.engine.startSync(); }); - new TestUnit("Engine.stopSync", new RegTestContext(), ctx -> { + new TestUnit("Engine.stopSync", new AdapterBaseTestContext(), ctx -> { ctx.engine.stopSync(); }); - new TestUnit("Engine.isSyncRunning", new RegTestContext(), ctx -> { + new TestUnit("Engine.isSyncRunning", new AdapterBaseTestContext(), ctx -> { ctx.engine.isSyncRunning(); }); - new TestUnit("Engine.config_passphrase",new RegTestContext() , ctx -> { + new TestUnit("Engine.config_passphrase",new AdapterBaseTestContext() , ctx -> { ctx.engine.config_passphrase("SUPERCOMPLICATEDPASSPHRASE"); }); - new TestUnit("Engine.config_passphrase_for_new_keys",new RegTestContext() , ctx -> { + new TestUnit("Engine.config_passphrase_for_new_keys",new AdapterBaseTestContext() , ctx -> { ctx.engine.config_passphrase_for_new_keys(true, "SUPERCOMPLICATEDPASSPHRASE"); }); diff --git a/test/java/foundation/pEp/jniadapter/test/speedtest/SpeedTest.java b/test/java/foundation/pEp/jniadapter/test/speedtest/SpeedTest.java index 6b2f81e..21f49f2 100644 --- a/test/java/foundation/pEp/jniadapter/test/speedtest/SpeedTest.java +++ b/test/java/foundation/pEp/jniadapter/test/speedtest/SpeedTest.java @@ -28,7 +28,7 @@ public class SpeedTest { try { Message[] msgs = codec.decode(testDataEnc); Vector keys = new Vector(); - 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"); diff --git a/test/java/foundation/pEp/jniadapter/test/templateAliceBob/MultiPeerCTX.java b/test/java/foundation/pEp/jniadapter/test/templateAliceBob/MultiPeerCTX.java index 4206abc..3a5c9d5 100644 --- a/test/java/foundation/pEp/jniadapter/test/templateAliceBob/MultiPeerCTX.java +++ b/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(); vStr = new Vector(); @@ -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; } } diff --git a/test/java/foundation/pEp/jniadapter/test/templateAliceBob/TestAlice.java b/test/java/foundation/pEp/jniadapter/test/templateAliceBob/TestAlice.java index 1cb6358..f872423 100644 --- a/test/java/foundation/pEp/jniadapter/test/templateAliceBob/TestAlice.java +++ b/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); diff --git a/test/java/foundation/pEp/jniadapter/test/templateAliceBob/TestBob.java b/test/java/foundation/pEp/jniadapter/test/templateAliceBob/TestBob.java index c8b7afc..d5e477e 100644 --- a/test/java/foundation/pEp/jniadapter/test/templateAliceBob/TestBob.java +++ b/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); diff --git a/test/java/foundation/pEp/jniadapter/test/utils/AdapterBaseTestContext.java b/test/java/foundation/pEp/jniadapter/test/utils/AdapterBaseTestContext.java index 5c3fa10..5ebae55 100644 --- a/test/java/foundation/pEp/jniadapter/test/utils/AdapterBaseTestContext.java +++ b/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 vID; - public Vector vStr; - - public void init() throws Throwable { - vID = new Vector(); - vStr = new Vector(); - + 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; } } \ No newline at end of file diff --git a/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/ctx/FsMQManagerBaseTestContext.java b/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/ctx/FsMQManagerBaseTestContext.java index 0542b35..dc64485 100644 --- a/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/ctx/FsMQManagerBaseTestContext.java +++ b/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() { diff --git a/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/ctx/FsMQManagerTestContext.java b/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/ctx/FsMQManagerTestContext.java index 261ecb3..6d10bca 100644 --- a/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/ctx/FsMQManagerTestContext.java +++ b/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; } } \ No newline at end of file diff --git a/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/identities/Makefile b/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/identities/Makefile index 0d73d43..408c8b9 100644 --- a/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/identities/Makefile +++ b/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) diff --git a/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/identities/TestMain.java b/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/identities/TestMain.java index 70f23b8..76ddb3b 100644 --- a/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/identities/TestMain.java +++ b/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/identities/TestMain.java @@ -31,8 +31,9 @@ class FsMQManagerIdentitiesTestContext extends AbstractTestContext { List messages; @Override - public void init() throws Throwable { + public FsMQManagerIdentitiesTestContext init() throws Throwable { messages = FsMQManagerTestUtils.createTestMessages(ownAddress, MSG_COUNT); + return this; } } diff --git a/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/stateless_ping/Makefile b/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/stateless_ping/Makefile index 7f67743..5702d25 100644 --- a/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/stateless_ping/Makefile +++ b/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) \ No newline at end of file diff --git a/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/stateless_rxtx/Makefile b/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/stateless_rxtx/Makefile index 566a944..cfa1548 100644 --- a/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/stateless_rxtx/Makefile +++ b/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) diff --git a/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/stateless_rxtx/TestMain.java b/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/stateless_rxtx/TestMain.java index 3dd3070..f8aafe2 100644 --- a/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmqmanager/test/stateless_rxtx/TestMain.java +++ b/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 { diff --git a/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmsgqueue/test/regression/Makefile b/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmsgqueue/test/regression/Makefile index ebfd10e..e02b539 100644 --- a/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmsgqueue/test/regression/Makefile +++ b/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) diff --git a/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmsgqueue/test/regression/TestMain.java b/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmsgqueue/test/regression/TestMain.java index 2dd38c2..3dfe994 100644 --- a/test/java/foundation/pEp/jniadapter/test/utils/transport/fsmsgqueue/test/regression/TestMain.java +++ b/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 createTestMessages(int count) { diff --git a/test/java/foundation/pEp/pitytest/Makefile b/test/java/foundation/pEp/pitytest/Makefile index bb49978..203bfab 100644 --- a/test/java/foundation/pEp/pitytest/Makefile +++ b/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) diff --git a/test/java/foundation/pEp/pitytest/Makefile.conf b/test/java/foundation/pEp/pitytest/Makefile.conf index 51eae4a..6a7df96 100644 --- a/test/java/foundation/pEp/pitytest/Makefile.conf +++ b/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 \ diff --git a/test/java/foundation/pEp/pitytest/TestContextInterface.java b/test/java/foundation/pEp/pitytest/TestContextInterface.java index 177bbb5..cd75f46 100644 --- a/test/java/foundation/pEp/pitytest/TestContextInterface.java +++ b/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); } diff --git a/test/java/foundation/pEp/pitytest/TestSuite.java b/test/java/foundation/pEp/pitytest/TestSuite.java index f44d355..e5e5920 100644 --- a/test/java/foundation/pEp/pitytest/TestSuite.java +++ b/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() { diff --git a/test/java/foundation/pEp/pitytest/TestUnit.java b/test/java/foundation/pEp/pitytest/TestUnit.java index a14b4f0..d195cbb 100644 --- a/test/java/foundation/pEp/pitytest/TestUnit.java +++ b/test/java/foundation/pEp/pitytest/TestUnit.java @@ -44,20 +44,45 @@ public class TestUnit implements Runnable { add(TestSuite.getDefault()); } + //Shallow Copy + public TestUnit(TestUnit 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 copy() { + return new TestUnit<>(this); + } + public boolean isVerboseMode() { return verboseMode; } - public void setVerboseMode(boolean verboseMode) { + public TestUnit setVerboseMode(boolean verboseMode) { this.verboseMode = verboseMode; + return this; } public TermColor getTestColor() { return testColor; } - public void setTestColor(TermColor testColor) { + public TestUnit setTestColor(TermColor testColor) { this.testColor = testColor; + return this; } public TestState getResult() { @@ -65,7 +90,11 @@ public class TestUnit implements Runnable { } public Throwable getLastException() { - return lastException; + Throwable ret = new Throwable("No Exception caught"); + if(lastException != null) { + ret = lastException; + } + return ret; } public TestUnit add(TestSuite suite) { @@ -82,10 +111,15 @@ public class TestUnit implements Runnable { return ctx; } + public TestUnit 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 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 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, ".. "); } diff --git a/test/java/foundation/pEp/pitytest/examples/ctxinitfail/Makefile b/test/java/foundation/pEp/pitytest/examples/ctxinitfail/Makefile index 5586816..d36de9d 100644 --- a/test/java/foundation/pEp/pitytest/examples/ctxinitfail/Makefile +++ b/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) diff --git a/test/java/foundation/pEp/pitytest/examples/ctxinitfail/TestMain.java b/test/java/foundation/pEp/pitytest/examples/ctxinitfail/TestMain.java index 8f787de..b0100a9 100644 --- a/test/java/foundation/pEp/pitytest/examples/ctxinitfail/TestMain.java +++ b/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; } } diff --git a/test/java/foundation/pEp/pitytest/examples/ctxmembers/Makefile b/test/java/foundation/pEp/pitytest/examples/ctxmembers/Makefile index 27efb57..035fab6 100644 --- a/test/java/foundation/pEp/pitytest/examples/ctxmembers/Makefile +++ b/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) diff --git a/test/java/foundation/pEp/pitytest/examples/ctxmembers/TestMain.java b/test/java/foundation/pEp/pitytest/examples/ctxmembers/TestMain.java index 7fcce08..11228c9 100644 --- a/test/java/foundation/pEp/pitytest/examples/ctxmembers/TestMain.java +++ b/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; } } diff --git a/test/java/foundation/pEp/pitytest/examples/helloworld/Makefile b/test/java/foundation/pEp/pitytest/examples/helloworld/Makefile index 4e02f47..2431ab4 100644 --- a/test/java/foundation/pEp/pitytest/examples/helloworld/Makefile +++ b/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) diff --git a/test/java/foundation/pEp/pitytest/examples/helloworld/TestMain.java b/test/java/foundation/pEp/pitytest/examples/helloworld/TestMain.java index 1924aee..16044b1 100644 --- a/test/java/foundation/pEp/pitytest/examples/helloworld/TestMain.java +++ b/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; } } diff --git a/test/java/foundation/pEp/pitytest/examples/testsuite/Makefile b/test/java/foundation/pEp/pitytest/examples/testsuite/Makefile index 987f50b..66009d0 100644 --- a/test/java/foundation/pEp/pitytest/examples/testsuite/Makefile +++ b/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) diff --git a/test/java/foundation/pEp/pitytest/examples/testsuite/TestMain.java b/test/java/foundation/pEp/pitytest/examples/testsuite/TestMain.java index 06d2485..af96af1 100644 --- a/test/java/foundation/pEp/pitytest/examples/testsuite/TestMain.java +++ b/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; } } diff --git a/test/java/foundation/pEp/pitytest/utils/Pair.java b/test/java/foundation/pEp/pitytest/utils/Pair.java index 220775b..146a286 100644 --- a/test/java/foundation/pEp/pitytest/utils/Pair.java +++ b/test/java/foundation/pEp/pitytest/utils/Pair.java @@ -24,5 +24,11 @@ public class Pair { key = f; value = s; } + + public String toString() { + String ret=""; + ret += "'" + key.toString() + "' : '" + value.toString() + "'"; + return ret; + } } diff --git a/test/java/foundation/pEp/pitytest/utils/TestUtils.java b/test/java/foundation/pEp/pitytest/utils/TestUtils.java index f18d6b4..159ee34 100644 --- a/test/java/foundation/pEp/pitytest/utils/TestUtils.java +++ b/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 intMap; + + private CharClass(int value) { + this.value = value; + } + + public static CharClass getByInt(int value) { + if (intMap == null) { + intMap = new HashMap(); + for (CharClass s : CharClass.values()) { + intMap.put(s.value, s); + } + } + if (intMap.containsKey(value)) { + return intMap.get(value); + } + return null; + } + } } diff --git a/utils/extract_pEp_status_codes_from_engine.sh b/utils/gen_status_codes.sh old mode 100755 new mode 100644 similarity index 73% rename from utils/extract_pEp_status_codes_from_engine.sh rename to utils/gen_status_codes.sh index 112d200..238db98 --- a/utils/extract_pEp_status_codes_from_engine.sh +++ b/utils/gen_status_codes.sh @@ -6,15 +6,14 @@ if [ ! -f $1 ]; then echo -e "\e[1m\e[31mInput file not found!\e[0m" fi -if [ -z "$2" ]; then - echo -e "\e[1m\e[31mNo output file supplied\e[0m" -fi - -if [ "$#" -ne 2 ]; then - echo "Expected use is: $0 input_file output_file" +if [ "$#" -ne 1 ]; then + echo "Expected use is: $0 input_file" exit 1 fi +STAT_FILE=status_list.yml2 +PASS_FILE=passphrase_status_list.yml2 + ################################################################################ # Select GNU SED # ################################################################################ @@ -33,15 +32,17 @@ esac # Transform input file PEP_STATUS to yml2 status # ################################################################################ -$SED -n '/} PEP_STATUS/q;p' $1 > $2 -$SED -i -n '/STATUS_OK/,$p' $2 -$SED -i -e 's/\(.*\)/\L\1/' $2 -$SED -i "-e s/ pep/ pEp/g" $2 -$SED -i s/=/\>/g $2 -$SED -i s/,//g $2 +$SED -n '/} PEP_STATUS/q;p' $1 > $STAT_FILE +$SED -i -n '/STATUS_OK/,$p' $STAT_FILE +$SED -i -e 's/\(.*\)/\L\1/' $STAT_FILE +$SED -i "-e s/ pep/ pEp/g" $STAT_FILE +$SED -i s/=/\>/g $STAT_FILE +$SED -i s/,//g $STAT_FILE +grep -i passphrase $STAT_FILE | sed -e 's/^/enumitem/' > $PASS_FILE ################################################################################ # Show results # ################################################################################ -cat $2 +cat $STAT_FILE +cat $PASS_FILE