Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.mindoo.domino.jna.utils.LegacyAPIUtils Maven / Gradle / Ivy
Go to download
Java project to access the HCL Domino C API using Java Native Access (JNA)
package com.mindoo.domino.jna.utils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import com.mindoo.domino.jna.IAdaptable;
import com.mindoo.domino.jna.NotesDatabase;
import com.mindoo.domino.jna.NotesNamesList;
import com.mindoo.domino.jna.NotesNote;
import com.mindoo.domino.jna.errors.NotesError;
import com.mindoo.domino.jna.gc.IRecyclableNotesObject;
import com.mindoo.domino.jna.gc.NotesGC;
import com.mindoo.domino.jna.utils.NotesNamingUtils.Privileges;
import lotus.domino.Database;
import lotus.domino.Document;
import lotus.domino.NotesException;
import lotus.domino.Session;
/**
* Utility class that bridges between the C API calls provided in this project and
* the legacy lotus.domino API.
*
* @author Karsten Lehmann
*/
public class LegacyAPIUtils {
private static boolean m_initialized;
private static volatile Method getDocumentHandleRW;
private static volatile Method getDatabaseHandleRO;
private static volatile Method createDocument;
private static volatile Method createDatabase;
private static volatile Method createXPageSession;
private static volatile Method getDBHandle;
private static synchronized void initialize() {
if (m_initialized)
return;
m_initialized = true;
AccessController.doPrivileged(new PrivilegedAction() {
@Override
public Object run() {
try {
String backendBridgeFinderClassname = System.getProperty(IBackendBridgeFinder.class.getName());
IBackendBridgeFinder backendBridgeFinder;
if (!StringUtil.isEmpty(backendBridgeFinderClassname)) {
Class backendBridgeFinderClass =
(Class) Class.forName(backendBridgeFinderClassname);
backendBridgeFinder = backendBridgeFinderClass.newInstance();
}
else {
//use fallback, works when running in a plugin that has the
//com.ibm.domino.napi dependency
backendBridgeFinder = new DefaultBackendBridgeFinder();
}
try {
Class> backendBridgeClass = backendBridgeFinder.getBackendBridgeClass();
try {
getDocumentHandleRW = backendBridgeClass.getMethod("getDocumentHandleRW", lotus.domino.Document.class);
}
catch (Exception e) {
//
}
try {
getDatabaseHandleRO = backendBridgeClass.getMethod("getDatabaseHandleRO", lotus.domino.Database.class);
}
catch (Exception e) {
//
}
try {
createDatabase = backendBridgeClass.getMethod("createDatabase", lotus.domino.Session.class, Long.TYPE);
}
catch (Exception e) {
//
}
try {
createDocument = backendBridgeClass.getMethod("createDocument", lotus.domino.Database.class, Long.TYPE);
}
catch (Exception e) {
//
}
}
catch (Exception e) {
//
}
String xspNativeFinderClassname = System.getProperty(IXSPNativeFinder.class.getName());
IXSPNativeFinder xspNativeFinder;
if (!StringUtil.isEmpty(xspNativeFinderClassname)) {
Class xspNativeFinderClass =
(Class) Class.forName(xspNativeFinderClassname);
xspNativeFinder = xspNativeFinderClass.newInstance();
}
else {
//use fallback, works when running in a plugin that has the
//com.ibm.domino.napi dependency
xspNativeFinder = new DefaultXSPNativeFinder();
}
try {
Class> xspNativeClass = xspNativeFinder.getXSPNativeClass();
try {
createXPageSession = xspNativeClass.getMethod("createXPageSession", String.class, Long.TYPE, Boolean.TYPE, Boolean.TYPE);
}
catch (Exception e) {
//
}
try {
getDBHandle = xspNativeClass.getMethod("getDBHandle", Database.class);
}
catch (Exception e) {
//
}
}
catch (Exception e) {
//
}
}
catch (Exception t) {
t.printStackTrace();
}
return null;
}
});
}
/**
* Reads the C handle for the specific legacy {@link Document}
*
* @param doc document
* @return handle
*/
public static long getDocHandle(Document doc) {
initialize();
if (getDocumentHandleRW==null) {
throw new NotesError(0, "Required method BackendBridge.getDocumentHandleRW(Document) class not available in this environment");
}
try {
long cHandle = (Long) getDocumentHandleRW.invoke(null, doc);
return cHandle;
} catch (Exception e) {
throw new NotesError(0, "Could not read document c handle", e);
}
}
/**
* Reads the C handle for the specific legacy {@link Database}
*
* @param db database
* @return handle
*/
public static long getDBHandle(Database db) {
initialize();
if (getDBHandle==null && getDatabaseHandleRO==null) {
throw new NotesError(0, "Required method to extract DB handle not available in this environment");
}
if (getDBHandle!=null) {
try {
long cHandle = (Long) getDBHandle.invoke(null, db);
return cHandle;
} catch (Exception e) {
throw new NotesError(0, "Could not get db handle", e);
}
}
else {
try {
long cHandle = (Long) getDatabaseHandleRO.invoke(null, db);
return cHandle;
} catch (Exception e) {
throw new NotesError(0, "Could not get db handle", e);
}
}
}
/**
* Converts a C handle to a legacy {@link Document}
*
* @param db parent database
* @param handle handle
* @return document
* @deprecated does not seem to work yet, always returns null
*/
public static Document createDocument(Database db, long handle) {
initialize();
if (createDocument==null) {
throw new NotesError(0, "Required method BackendBridge.createDocument(Database,long) not available in this environment");
}
try {
Document doc = (Document) createDocument.invoke(null, db, handle);
return doc;
} catch (Exception e) {
throw new NotesError(0, "Could not convert document c handle", e);
}
}
/**
* Method to convert a handle to a legacy {@link Database}
*
* @param session session
* @param handle handle
* @return legacy database
* @deprecated does not seem to work yet, always returns null
*/
public static Database createDatabase(Session session, long handle) {
initialize();
if (createDatabase==null) {
throw new NotesError(0, "Required method BackendBridge.createDatabase(Session,long) not available in this environment");
}
try {
Database db = (Database) createDatabase.invoke(null, null, handle);
db = (Database) createDatabase.invoke(null, session, handle);
return db;
} catch (Exception e) {
throw new NotesError(0, "Could not convert database c handle", e);
}
}
/**
* Creates a legacy {@link Session} for a usernames list
*
* @param userName Notes username, either in canonical or abbreviated format
* @param privileges user privileges
* @return Session
*/
public static Session createSessionAs(String userName, EnumSet privileges) {
NotesNamesList namesList = NotesNamingUtils.buildNamesList(userName);
NotesNamingUtils.setPrivileges(namesList, privileges);
return createSessionAs(namesList);
}
/**
* Creates a legacy {@link Session} for a usernames list
*
* @param userNamesList user names list with name, wildcards and groups
* @param privileges user privileges
* @return Session
*/
public static Session createSessionAs(List userNamesList, EnumSet privileges) {
final List userNamesListCanonical = new ArrayList();
for (String currName : userNamesList) {
userNamesListCanonical.add(NotesNamingUtils.toCanonicalName(currName));
}
NotesNamesList namesList = NotesNamingUtils.writeNewNamesList(userNamesListCanonical);
NotesNamingUtils.setPrivileges(namesList, privileges);
return createSessionAs(namesList);
}
/**
* Creates a legacy {@link Session} for a usernames list
*
* @param namesList names list of user to create the session for
* @return Session
*/
public static Session createSessionAs(NotesNamesList namesList) {
initialize();
if (createXPageSession==null) {
throw new NotesError(0, "Required method XSPNative.createXPageSession(String, long, boolean, boolean) not available in this environment");
}
try {
long hList = PlatformUtils.is64Bit() ? namesList.getHandle64() : namesList.getHandle32();
final Session session = (Session) createXPageSession.invoke(null, namesList.getNames().get(0), hList, true, false);
long longHandle = 0;
int intHandle = 0;
if (PlatformUtils.is64Bit()) {
Long oldHandle = (Long) NotesGC.getCustomValue("FakeSessionHandle");
if (oldHandle==null) {
oldHandle = Long.valueOf(0);
}
Long newHandle = oldHandle.longValue()+1;
NotesGC.setCustomValue("FakeSessionHandle", newHandle.longValue());
longHandle = newHandle.longValue();
}
else {
Integer oldHandle = (Integer) NotesGC.getCustomValue("FakeSessionHandle");
if (oldHandle==null) {
oldHandle = Integer.valueOf(0);
}
Integer newHandle = oldHandle.intValue()+1;
NotesGC.setCustomValue("FakeSessionHandle", newHandle.intValue());
intHandle = newHandle.intValue();
}
NotesGC.__objectCreated(Session.class, new DummySessionRecyclableNotesObject(intHandle, longHandle, namesList.getNames(), session));
return session;
}
catch (Exception t) {
throw new NotesError(0, "Could not create session", t);
}
}
/**
* Implementation of {@link IRecyclableNotesObject} that recycles a legacy {@link Session}
* as part of the auto GC process
*
* @author Karsten Lehmann
*/
private static final class DummySessionRecyclableNotesObject implements IRecyclableNotesObject {
private final int intHandle;
private final long longHandle;
private final List userNamesListCanonical;
private final Session session;
private DummySessionRecyclableNotesObject(int intHandle, long longHandle,
List userNamesListCanonical, Session session) {
this.intHandle = intHandle;
this.longHandle = longHandle;
this.userNamesListCanonical = userNamesListCanonical;
this.session = session;
}
@Override
public void recycle() {
try {
session.recycle();
}
catch (NotesException ignore) {}
}
@Override
public boolean isRecycled() {
try {
session.isOnServer();
}
catch (NotesException e) {
if (e.id==4376 || e.id==4466)
return true;
}
catch (Exception t) {
t.printStackTrace();
return true;
}
return false;
}
@Override
public boolean isNoRecycle() {
return false;
}
@Override
public long getHandle64() {
return longHandle;
}
@Override
public int getHandle32() {
return intHandle;
}
@Override
public String toString() {
if (isRecycled()) {
return "Session [recycled, names="+userNamesListCanonical.toString()+"]";
}
else {
return "Session [names="+userNamesListCanonical.toString()+"]";
}
}
}
/**
* Converts a legacy {@link Database} to a {@link NotesDatabase}
*
* @param db legacy DB
* @return JNA db
*/
public static NotesDatabase toNotesDatabase(final Database db) {
return new NotesDatabase(new IAdaptable() {
@Override
public T getAdapter(Class clazz) {
if (clazz == Database.class)
return (T) db;
else
return null;
}
});
}
/**
* Converts a legacy {@link Document} to a {@link NotesNote}
*
* @param doc legacy document
* @return JNA note
*/
public static NotesNote toNotesNote(final Document doc) {
return new NotesNote(new IAdaptable() {
@Override
public T getAdapter(Class clazz) {
if (clazz == Document.class)
return (T) doc;
else
return null;
}
});
}
/**
* Interface to provide a custom class that locates the class
* com.ibm.domino.napi.c.BackendBridge. Default implementation
* just uses the JNA project's classloader to find it.
*
* @author Karsten Lehmann
*/
public static interface IBackendBridgeFinder {
public Class> getBackendBridgeClass() throws ClassNotFoundException;
}
/**
* Interface to provide a custom class that locates the class
* com.ibm.domino.napi.c.xsp.XSPNative. Default implementation
* just uses the JNA project's classloader to find it.
*
* @author Karsten Lehmann
*/
public static interface IXSPNativeFinder {
public Class> getXSPNativeClass() throws ClassNotFoundException;
}
/**
* Default implementation of {@link IBackendBridgeFinder} that uses
* the JNA project's classloader to find the BackendBridge class.
*
* @author Karsten Lehmann
*/
private static class DefaultBackendBridgeFinder implements IBackendBridgeFinder {
@Override
public Class> getBackendBridgeClass() throws ClassNotFoundException {
//This class only works when lwpd.domino.napi.jar and lwpd.commons.jar are in the classpath
ClassLoader napiClassloader;
try {
Class> cClass = Class.forName("com.ibm.domino.napi.c.C");
if (!jnotesLoaded) {
Method initLibrary = cClass.getMethod("initLibrary", String.class);
initLibrary.invoke(null, "");
jnotesLoaded=true;
}
napiClassloader = cClass.getClassLoader();
} catch (ClassNotFoundException e) {
throw new ClassNotFoundException("Unable to initialize the NAPI class which is required to access the BackendBridge class", e);
} catch (NoSuchMethodException e) {
throw new ClassNotFoundException("Unable to initialize the NAPI class which is required to access the BackendBridge class", e);
} catch (SecurityException e) {
throw new ClassNotFoundException("Unable to initialize the NAPI class which is required to access the BackendBridge class", e);
} catch (IllegalAccessException e) {
throw new ClassNotFoundException("Unable to initialize the NAPI class which is required to access the BackendBridge class", e);
} catch (IllegalArgumentException e) {
throw new ClassNotFoundException("Unable to initialize the NAPI class which is required to access the BackendBridge class", e);
} catch (InvocationTargetException e) {
throw new ClassNotFoundException("Unable to initialize the NAPI class which is required to access the BackendBridge class", e);
}
return napiClassloader.loadClass("com.ibm.domino.napi.c.BackendBridge");
}
}
private static volatile boolean jnotesLoaded = false;
private static class DefaultXSPNativeFinder implements IXSPNativeFinder {
@Override
public Class> getXSPNativeClass() throws ClassNotFoundException {
//This class only works when lwpd.domino.napi.jar and lwpd.commons.jar are in the classpath
ClassLoader napiClassloader;
try {
Class> cClass = Class.forName("com.ibm.domino.napi.c.C");
if (!jnotesLoaded) {
Method initLibrary = cClass.getMethod("initLibrary", String.class);
initLibrary.invoke(null, "");
jnotesLoaded = true;
}
napiClassloader = cClass.getClassLoader();
} catch (ClassNotFoundException e) {
throw new ClassNotFoundException("Unable to initialize the NAPI class which is required to access the XSPNative class", e);
} catch (NoSuchMethodException e) {
throw new ClassNotFoundException("Unable to initialize the NAPI class which is required to access the XSPNative class", e);
} catch (SecurityException e) {
throw new ClassNotFoundException("Unable to initialize the NAPI class which is required to access the XSPNative class", e);
} catch (IllegalAccessException e) {
throw new ClassNotFoundException("Unable to initialize the NAPI class which is required to access the XSPNative class", e);
} catch (IllegalArgumentException e) {
throw new ClassNotFoundException("Unable to initialize the NAPI class which is required to access the XSPNative class", e);
} catch (InvocationTargetException e) {
throw new ClassNotFoundException("Unable to initialize the NAPI class which is required to access the XSPNative class", e);
}
return napiClassloader.loadClass("com.ibm.domino.napi.c.xsp.XSPNative");
}
}
}