Reputation: 681
Faced with the following issue: I am actively use DominoDocument class (wrapped Document) in my projects, particularly as basis for my business model objects.
Very often I have a need to access / iterate my business model objects as Anonymous user thus underlying lotus.domino.Document retrieved based on SessionAsSigner session object (for example in case of some REST Services, or in case of xAgent, etc).
The behavior of restoreWrappedDocument() method in such cases really breaks all flexibility of using such architecture: this method tries to restore wrapped document based on current execution environment access rights, and of course that causes errors with ACL.
Let’s consider the following code snippet as example:
public void test3() {
try {
System.out.println(">>>>>");
System.out.println(">>>>> START");
lotus.domino.Database db = AppBean.getSessionAsSigner().getDatabase(AppBean.getInstance().getContactsDBserverName(), AppBean.getInstance().getContactsDBname(), false);
Document notesDoc = db.getAllDocuments().getFirstDocument();
String dbName = notesDoc.getParentDatabase().getServer() + "!!" + notesDoc.getParentDatabase().getFilePath();
DominoDocument ds = DominoDocument.wrap(dbName, notesDoc, null, "exception", false, "UseWeb", null);
System.out.println(">> 1 >> " + ds.getValue("form"));
ds.getDocument().recycle();
try {
ds.restoreWrappedDocument();
}catch(Throwable e2){
System.out.println(">> 2 - exception - >> " + e2.toString());
e2.printStackTrace();
}
try {
System.out.println(">> 3 >> " + ds.getValue("form"));
}catch(Throwable e3){
System.out.println(">> 3 - exception - >> " + e3.toString());
}
System.out.println(">>>>> END");
System.out.println(">>>>>");
}catch(Exception e){
e.printStackTrace();
}
}
1) Scenario 1: executing this code by authenticated user that has access to target DB gives the following result:
So method works as expected and everything perfect.
2) Scenario 2: executing this code by Anonymous user causes Exception (generally, what is expected):
You can clearly see that restoreWrappedDocument() executes some helper methods in order to get DB, and of course that is done with current user access level (Anonymous).
Possible solutions:
Thanks!
Upvotes: 0
Views: 367
Reputation: 10485
A solution with a Helper class using Java Reflection: (Incomplete, missing some parts)
package ch.hasselba.xpages;
import java.lang.reflect.Field;
import lotus.domino.Database;
import lotus.domino.Document;
import lotus.domino.NotesException;
import com.ibm.xsp.FacesExceptionEx;
import com.ibm.xsp.model.domino.DominoUtils;
import com.ibm.xsp.model.domino.wrapped.DominoDocument;
public class DominoDocumentUtil {
private static final long serialVersionUID = 1L;
private transient final Field wrappedObj;
private transient final DominoDocument dominoDoc;
public DominoDocumentUtil(DominoDocument doc) throws SecurityException,
NoSuchFieldException {
dominoDoc = doc;
wrappedObj= doc.getClass().getDeclaredField("_wrappedObject");
wrappedObj.setAccessible(true);
}
public void restoreWrappedDocument(Database db)
throws IllegalArgumentException, IllegalAccessException {
try {
Document doc = DominoUtils.getDocumentById(db, dominoDoc
.getDocumentId(), dominoDoc.isAllowDeletedDocs());
this.wrappedObj.set(dominoDoc, doc);
} catch (NotesException ne) {
throw new FacesExceptionEx(ne.getMessage());
}
}
}
To use the class you can call the restoreWrappedDocument method with a database opened with sessionAsSigner:
DominoDocumentUtil util = new DominoDocumentUtil(ds);
util.restoreWrappedDocument(db);
Upvotes: 1
Reputation: 4471
I don't think there's a proper way to do this, other than your option 1, for better or for worse.
However, and I'm not saying this is a good idea, it seems like DominoDocument
likely gets to its session through the current request map. If you want to be tricky, you could try temporarily swapping session
out for sessionAsSigner
in the request scope, calling restoreWrappedDocument
, and then swapping it back.
Upvotes: 1