Greetings all. I am having issues getting my prototype correct for a couple Java methods. I tried to find examples of native Base64 encoding/decoding but found different versions where some used Scott Klement's open source Base64 utility, others use a set of APIs that I can't remember what they are, and still others user the apr_base64 APIs. None of which I can seem to get working which I'm sure is due to my inability to piece things together.
I decided not to reinvent the wheel as I know Java can do it. This is the code from the Java example I am attempting to recreate in RPG:
I'm not sure I can do the above with APIs on the IBM i so I figured I would prototype the various methods in RPG and try it from there. I get an error in my RPG program when it gets to a certain point when working with the java.util.Base64 class and the getDecoder method. When I look at my joblog, this is what it says: Java exception "java.lang.NoSuchMethodError: java/util/Base64.getDecoder()Ljava/util/Base64/Decoder;" when calling method "getDecoder" with signature "()Ljava.util.Base64.Decoder;" in class "java.util.Base64".
Here is a link to the Java Docs regarding the Base64 class: https://docs.oracle.com/javase/8/doc...il/Base64.html.
I also ran javap -s java.util.Base64 on the IBM i I'm using and it looks like the signature matches my prototype:
Compiled from "Base64.java"
public class java.util.Base64 {
public static java.util.Base64$Encoder getEncoder();
descriptor: ()Ljava/util/Base64$Encoder;
public static java.util.Base64$Encoder getUrlEncoder();
descriptor: ()Ljava/util/Base64$Encoder;
public static java.util.Base64$Encoder getMimeEncoder();
descriptor: ()Ljava/util/Base64$Encoder;
public static java.util.Base64$Encoder getMimeEncoder(int, byte[]);
descriptor: (I[B)Ljava/util/Base64$Encoder;
public static java.util.Base64$Decoder getDecoder();
descriptor: ()Ljava/util/Base64$Decoder;
public static java.util.Base64$Decoder getUrlDecoder();
descriptor: ()Ljava/util/Base64$Decoder;
public static java.util.Base64$Decoder getMimeDecoder();
descriptor: ()Ljava/util/Base64$Decoder;
}
Below is my code. Realize that this is just a test program so I've tried a few other things and commented them out while I work on other pieces. Any help with what I am missing would be greatly appreciated and/or pointing me to resources that show how to use available APIs on the IBM i to do what I want.
I decided not to reinvent the wheel as I know Java can do it. This is the code from the Java example I am attempting to recreate in RPG:
Code:
SecretKeySpec secretKey = new SecretKeySpec(Base64.getDecoder().decode(merchantSecretKey), "HmacSHA256");
Here is a link to the Java Docs regarding the Base64 class: https://docs.oracle.com/javase/8/doc...il/Base64.html.
I also ran javap -s java.util.Base64 on the IBM i I'm using and it looks like the signature matches my prototype:
Compiled from "Base64.java"
public class java.util.Base64 {
public static java.util.Base64$Encoder getEncoder();
descriptor: ()Ljava/util/Base64$Encoder;
public static java.util.Base64$Encoder getUrlEncoder();
descriptor: ()Ljava/util/Base64$Encoder;
public static java.util.Base64$Encoder getMimeEncoder();
descriptor: ()Ljava/util/Base64$Encoder;
public static java.util.Base64$Encoder getMimeEncoder(int, byte[]);
descriptor: (I[B)Ljava/util/Base64$Encoder;
public static java.util.Base64$Decoder getDecoder();
descriptor: ()Ljava/util/Base64$Decoder;
public static java.util.Base64$Decoder getUrlDecoder();
descriptor: ()Ljava/util/Base64$Decoder;
public static java.util.Base64$Decoder getMimeDecoder();
descriptor: ()Ljava/util/Base64$Decoder;
}
Below is my code. Realize that this is just a test program so I've tried a few other things and commented them out while I work on other pieces. Any help with what I am missing would be greatly appreciated and/or pointing me to resources that show how to use available APIs on the IBM i to do what I want.
Code:
H DFTACTGRP(*NO) ACTGRP(*CALLER) H THREAD(*SERIALIZE) // /DEFINE JNI_COPY_ALL // /copy QSYSINC/QRPGLESRC,JNI // /UNDEFINE JNI_COPY_ALL /DEFINE OS400_JVM_12 /copy qsysinc/qrpglesrc,jni /undefine OS400_JVM_12 /DEFINE JAVA_UTIL_COPIED /copy allsrc,javautil /UNDEFINE JAVA_UTIL_COPIED D newString PR O EXTPROC(*JAVA D : STRING_CLASS D : *CONSTRUCTOR) D value 65535A VARYING CONST * Define a prototype to retrieve the value of a String D getBytes PR 65535A VARYING D EXTPROC(*JAVA: D STRING_CLASS: D 'getBytes') * Define the getDecoder Method D getBase64Decoder... D PR o extproc(*JAVA: D BASE64_CLASS: D 'getDecoder') D CLASS(*JAVA: D 'java.util.Base64.Decoder') D STATIC * Define a prototype to decode a byte array D base64Decode PR o D extproc(*JAVA D : BASE64_DECODER_CLASS D : 'decode') D CLASS(*JAVA D : 'java.lang.Object') D byteArray o CLASS(*JAVA D : 'java.lang.Object') D STRING_CLASS C 'java.lang.String' D BASE64_DECODER_CLASS... D C 'java.util.Base64.Decoder' D BASE64_CLASS C 'java.util.Base64' D SHA256 C 'HmacSHA256' D HTTP_METHOD_POST... D C 'POST' D base64Decoder1 s o Class(*JAVA: BASE64_DECODER_CLASS) D base64Decoder2 s o Class(*JAVA: BASE64_DECODER_CLASS) D byteArray1 s o Class(*JAVA: 'java.lang.Object') D httpSignature1 s o Class(*JAVA: STRING_CLASS) D tempField s 1000A inz D env s * inz(*null) /free env = getJniEnv(); beginObjGroup(env); base64Decoder1 = getBase64Decoder(); endObjGroup(env); *inlr = *on; /end-free *---------------------------------------------------------------- * beginObjGroup - start a new group of objects that can all * be deleted together later *---------------------------------------------------------------- P beginObjGroup b export D beginObjGroup pi 10i 0 D env * const D capacityParm 10i 0 value options(*nopass) D rc s 10i 0 D capacity s 10i 0 inz(100) /free JNIENV_p = env; if (%parms >= 2); capacity = capacityParm; endif; rc = PushLocalFrame (JNIENV_p : capacity); if (rc <> 0); return JNI_GROUP_NOT_ADDED; endif; return JNI_GROUP_ADDED; /end-free P beginObjGroup e *---------------------------------------------------------------- * endObjGroup - end the group of objects that was started * most recently *---------------------------------------------------------------- P endObjGroup b export D endObjGroup pi 10i 0 D env * const D refObjectP o class(*java:'java.lang.Object') D const D options(*nopass) D newObjectP o class(*java:'java.lang.Object') D options(*nopass) D retVal s o class(*java:'java.lang.Object') D refObject s like(refObjectP) inz(*null) D newObject s like(newObjectP) /free JNIENV_p = env; if %parms() >= 2; refObject = refObjectP; endif; newObject = PopLocalFrame (JNIENV_p : refObject); if %parms() >= 3; newObjectP = newObject; endif; return JNI_GROUP_ENDED; /end-free P endObjGroup e P freeLocalRef b D freeLocalref pi D env * value D localRef o class(*java D : 'java.lang.Object') D value /free jniEnv_P = env; DeleteLocalRef(env: localRef); /end-free P freeLocalRef e *---------------------------------------------------------------- * getJniEnv - get the JNI environment pointer * Note: This procedure will cause the JVM to be created if * it was not already created. *---------------------------------------------------------------- P getJniEnv b export D getJniEnv pi * D attachArgs ds likeds(JavaVMAttachArgs) D env s * inz(*null) D jvm s like(JavaVM_p) dim(1) D nVms s like(jsize) D rc s 10i 0 D obj s o class(*java D : 'java.lang.Integer') D newInteger pr o extproc(*java D : 'java.lang.Integer' D : *constructor) D value 10i 0 value /free monitor; // Get the current JVM rc = JNI_GetCreatedJavaVMs(jvm : 1 : nVms); if (rc <> 0); // Some error occurred return *null; endif; if (nVms = 0); // The JVM is not created yet. Call a Java // method to get the RPG runtime to start the JVM obj = newInteger(5); // Try again to get the current JVM rc = JNI_GetCreatedJavaVMs(jvm : 1 : nVms); if (rc <> 0 or nVms = 0); // Some error occurred return *null; endif; endif; // Attach to the JVM JavaVM_P = jvm(1); attachArgs = *allx'00'; attachArgs.version = JNI_VERSION_1_2; rc = AttachCurrentThread (jvm(1) : env : %addr(attachArgs)); if (rc <> 0); return *null; endif; // Free the object if we created it above while // getting the RPG runtime to start the JVM if obj <> *null; freeLocalRef (env : obj); endif; on-error; return *null; endmon; return env; /end-free P getJniEnv e
Comment