klehmann / domino-jna

Java project to access the IBM/HCL Domino C API using Java Native Access (JNA)
Apache License 2.0
66 stars 16 forks source link

How can i use IDUtils.switchid in a multithreaded program? #65

Closed glasen closed 3 years ago

glasen commented 3 years ago

Hi,

i'm trying to use "IDUtils.switchID" in a multithreaded program. That means i want to open a database and use the provided id-file and passwort to decrypt the data.

When opening a single database-file the static method works perfectly. But when opening two or more databases and using the method, it doesn't work. It seems that the method changes the user and credentials on a global scale.

Does there exists a method were i can provide the id-file and password on database level or maybe even on document-level?

klehmann commented 3 years ago

Hi,

I am using this method in my local standalone applications or test cases only to unlock the local ID file and be able to access data on remote Domino servers without password prompts in the console. I would not recommend using it on a server or within a running Notes Client process. Have you looked at the other methods in IDUtils that return a NotesUserId object, e.g. IDUtils.openUserIdFile(String idPath, String password, IDAccessCallback<T> callback) or IDUtils.getUserIdFromVault(String userName, String password, String serverName)?

The NotesUserId can be used to encrypt/decrypt/sign data, e.g. in NotesNote.copyAndEncrypt(NotesUserId id, EnumSet<EncryptionMode> encryptionMode), NotesNote.decrypt(NotesUserId id) or NotesNote.sign(NotesUserId id, boolean signNotesIfMimePresent).

glasen commented 3 years ago

I've tried to use "IDUtils.openUserIdFile()" but i have no idea how to use it properly. What kind of callback do i have to provide? How do i get the NotesUserId-object from the above method?

klehmann commented 3 years ago

It’s provided in the callback and its handle is automatically closed when the callback execution is done.

glasen commented 3 years ago

Can you please be a bit more specific and provide my some lines of sample code?

NotesDatabase db = new NotesDatabase(session, "", filename);
callback = ???? -> What do i need to call?
IDUtils.openUserIdFile(idFile, passwors, callback);
NotesNote note = db.openNoteById(2306);
note.decrypt(someUserID);
klehmann commented 3 years ago

openUserIdFile takes a callback object of type IDUtils.IDAccessCallback:

    /**
     * Callback interface to work with an opened ID
     * 
     * @param <T> computation result type
     * 
     * @author Karsten Lehmann
     */
    public static interface IDAccessCallback<T> {

        /**
         * Implement this method to work with the passed user id. <b>Do not store it anywhere, since it is disposed right after the method call!</b>.
         * 
         * @param id id
         * @return optional computation result
         * @throws Exception in case of errors
         */
        public T accessId(NotesUserId id) throws Exception;

    }

The interface has a generic result parameter "T" that you can use to let your accessId method implementation return a computation result easily. If that's not important, just use Object for type "T" and return null.

You could call openUserIdFile like this (here my return value is of type Map<String,Object>):

    //using anonymous class for callback (any Java version)
    Map<String,Object> computationResult1 = IDUtils.openUserIdFile(idPath, password,
            new IDUtils.IDAccessCallback<Map<String,Object>>() {

        @Override
        public Map<String,Object> accessId(NotesUserId id) throws Exception {
            Map<String,Object> result = computeSomeResultWithId(id);
            return result;
        }
    });         

Since Java 1.8 you might as well use a shorter syntax for interfaces that just have one method:

    //using lambda function for callback (Java 1.8+)
    Map<String,Object> computationResult = IDUtils.openUserIdFile(idPath, password,
            (id) -> {
                Map<String,Object> result = computeSomeResultWithId(id);
                return result;
            });
glasen commented 3 years ago

Thank you very much. That solves my problem.