com.mindoo.domino.jna.dxl.DXLImporter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of domino-jna Show documentation
Show all versions of domino-jna Show documentation
Java project to access the HCL Domino C API using Java Native Access (JNA)
The newest version!
package com.mindoo.domino.jna.dxl;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicReference;
import com.mindoo.domino.jna.internal.TeeOutputStream;
import com.mindoo.domino.jna.NotesDatabase;
import com.mindoo.domino.jna.NotesIDTable;
import com.mindoo.domino.jna.NotesNote;
import com.mindoo.domino.jna.dxl.DXLExporter.DXLExportCharset;
import com.mindoo.domino.jna.dxl.DXLExporter.DXLMIMEOption;
import com.mindoo.domino.jna.dxl.DXLExporter.DXLRichtextOption;
import com.mindoo.domino.jna.dxl.DXLExporter.DXLValidationStyle;
import com.mindoo.domino.jna.errors.NotesError;
import com.mindoo.domino.jna.errors.NotesErrorUtils;
import com.mindoo.domino.jna.gc.IAllocatedMemory;
import com.mindoo.domino.jna.gc.NotesGC;
import com.mindoo.domino.jna.internal.NotesCallbacks;
import com.mindoo.domino.jna.internal.NotesConstants;
import com.mindoo.domino.jna.internal.NotesNativeAPI;
import com.mindoo.domino.jna.internal.NotesNativeAPI32;
import com.mindoo.domino.jna.internal.NotesNativeAPI64;
import com.mindoo.domino.jna.internal.ReaderInputStream;
import com.mindoo.domino.jna.internal.Win32NotesCallbacks;
import com.mindoo.domino.jna.utils.PlatformUtils;
import com.mindoo.domino.jna.utils.StringUtil;
import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import lotus.domino.NotesException;
import lotus.domino.NotesThread;
/**
* DXL importer
*
* Default values are set as follows:
*
* Note: (i) = can input new value into the importer.
* (o) = can get current value out of importer.
* (io) = can do both.
*
* iACLImportOption = (io) {@link DXLImportOption#IGNORE}
* iDesignImportOption = (io) {@link DXLImportOption#IGNORE}
* iDocumentsImportOption = (io) {@link DXLImportOption#CREATE}
* iCreateFullTextIndex = (io) FALSE
* Note:
To create a Full Text Index on a database, the iCreateFullTextIndex must be set to TRUE,
* the iReplaceDbProperties must be set to TRUE and a schema element named
* <fulltextsettings> must be defined.
*
* iReplaceDbProperties = (io) FALSE
* iInputValidationOption = (io) {@link XMLValidationOption#AUTO}
* iReplicaRequiredForReplaceOrUpdate = (io) TRUE
* iExitOnFirstFatalError = (io) TRUE
* iUnknownTokenLogOption = (io) {@link DXLLogOption#FATALERROR}
* iResultLogComment = (io) NULLMEMHANDLE
* iResultLog = (o) NULLMEMHANDLE
* iImportedNoteList = (o) NULLHANDLE
*
* @author Karsten Lehmann
*/
public class DXLImporter extends AbstractDXLTransfer implements IAllocatedMemory {
private int m_hImporter;
public DXLImporter() {
IntByReference rethDXLExport = new IntByReference();
short result = NotesNativeAPI.get().DXLCreateImporter(rethDXLExport);
NotesErrorUtils.checkResult(result);
m_hImporter = rethDXLExport.getValue();
if (m_hImporter==0) {
throw new NotesError(0, "Failed to allocate DXL importer");
}
NotesGC.__memoryAllocated(this);
}
@Override
public void free() {
if (isFreed()) {
return;
}
if (m_hImporter!=0) {
NotesNativeAPI.get().DXLDeleteImporter(m_hImporter);
m_hImporter = 0;
}
}
@Override
public boolean isFreed() {
return m_hImporter==0;
}
@Override
public int getHandle32() {
return m_hImporter;
}
@Override
public long getHandle64() {
return m_hImporter;
}
@Override
protected void checkHandle() {
if (m_hImporter==0)
throw new NotesError(0, "DXL importer already freed");
if (PlatformUtils.is64Bit()) {
NotesGC.__b64_checkValidMemHandle(DXLImporter.class, m_hImporter);
}
else {
NotesGC.__b32_checkValidMemHandle(DXLImporter.class, m_hImporter);
}
}
public boolean importErrorWasLogged() {
checkHandle();
short logged = NotesNativeAPI.get().DXLImportWasErrorLogged(m_hImporter);
return logged == 1;
}
@Override
protected short getProperty(int index, Memory m) {
return NotesNativeAPI.get().DXLGetImporterProperty(m_hImporter, index, m);
}
@Override
protected short setProperty(int index, Memory m) {
return NotesNativeAPI.get().DXLSetImporterProperty(m_hImporter, index, m);
}
public static enum DXLImportOption {
/** ignore imported data */
IGNORE(1),
/** create new data from imported data */
CREATE(2),
/** if imported data matches existing data, ignore the imported data, otherwise create it */
IGNORE_ELSE_CREATE(3),
/** do not used - reserved for future variation of create option */
CREATE_RESERVED2(4),
/** if imported data matches existing data, then replace existing data with imported data, else ignore imported data. */
REPLACE_ELSE_IGNORE(5),
/** if imported data matches existing data, then replace existing data with imported data, else create
* new data from imported data */
REPLACE_ELSE_CREATE(6),
/** do not used - reserved for future variation of replace option */
REPLACE_RESERVED1(7),
/** do not used - reserved for future variation of replace option */
REPLACE_RESERVED2(8),
/** if imported data matches existing data, then update existing data with imported data, else ignore imported data. */
UPDATE_ELSE_IGNORE(9),
/** if imported data matches existing data, then update existing data with imported data, else create
* new data from imported data */
UPDATE_ELSE_CREATE(10),
/** do not used - reserved for future variation of update option */
UPDATE_RESERVED1(11),
/** do not used - reserved for future variation of update option */
UPDATE_RESERVED2(12);
private int m_option;
private DXLImportOption(int option) {
m_option = option;
}
public int getValue() {
return m_option;
}
}
public static enum DXLLogOption {
/** ignore the action. don't log anything and just continue */
IGNORE(1),
/** log the problem as a warning */
WARNING(2),
/** log the problem as an error */
ERROR(3),
/** log the problem as a fatal error */
FATALERROR(4);
private int m_option;
private DXLLogOption(int option) {
m_option = option;
}
public int getValue() {
return m_option;
}
}
public static enum XMLValidationOption {
NEVER(0),
ALWAYS(1),
AUTO(2);
private int m_option;
private XMLValidationOption(int option) {
m_option = option;
}
public int getValue() {
return m_option;
}
}
/**
* Returns the import option for the ACL
*
* @return option or null if unknown value
*/
public DXLImportOption getACLImportOption() {
short optionAsShort = getShort(NotesConstants.iACLImportOption);
int optionAsInt = (int) (optionAsShort & 0xffff);
for (DXLImportOption currOpt : DXLImportOption.values()) {
if (currOpt.getValue() == optionAsInt) {
return currOpt;
}
}
return null;
}
/**
* Sets the import option for the ACL
*
* @param option option
*/
public void setACLImportOption(DXLImportOption option) {
int optionAsInt = option.getValue();
short optionAsShort = (short) (optionAsInt & 0xffff);
setShort(NotesConstants.iACLImportOption, optionAsShort);
}
/**
* Returns the import option for design
*
* @return option or null if unknown value
*/
public DXLImportOption getDesignImportOption() {
short optionAsShort = getShort(NotesConstants.iDesignImportOption);
int optionAsInt = (int) (optionAsShort & 0xffff);
for (DXLImportOption currOpt : DXLImportOption.values()) {
if (currOpt.getValue() == optionAsInt) {
return currOpt;
}
}
return null;
}
/**
* Sets the import option for design
*
* @param option option
*/
public void setDesignImportOption(DXLImportOption option) {
int optionAsInt = option.getValue();
short optionAsShort = (short) (optionAsInt & 0xffff);
setShort(NotesConstants.iDesignImportOption, optionAsShort);
}
/**
* Returns the import option for data documents
*
* @return option or null if unknown value
*/
public DXLImportOption getDocumentsImportOption() {
short optionAsShort = getShort(NotesConstants.iDocumentsImportOption);
int optionAsInt = (int) (optionAsShort & 0xffff);
for (DXLImportOption currOpt : DXLImportOption.values()) {
if (currOpt.getValue() == optionAsInt) {
return currOpt;
}
}
return null;
}
/**
* Sets the import option for data documents
*
* @param option option
*/
public void setDocumentsImportOption(DXLImportOption option) {
int optionAsInt = option.getValue();
short optionAsShort = (short) (optionAsInt & 0xffff);
setShort(NotesConstants.iDocumentsImportOption, optionAsShort);
}
/**
* Returns whether to create a fulltext index
*
* @return BOOL, TRUE = create full text index, FALSE Do NOT create full text index
*/
public boolean isCreateFullTextIndex() {
return getBooleanProperty(NotesConstants.iCreateFullTextIndex);
}
/**
* Sets whether to create a fulltext index
* @param b BOOL, TRUE = create full text index, FALSE Do NOT create full text index
*/
public void setCreateFullTextIndex(boolean b) {
setBooleanProperty(NotesConstants.iCreateFullTextIndex, b);
}
/**
* Returns whether to replace database properties
* @return BOOL, TRUE = replace database properties, FALSE Do NOT replace database propertie
*/
public boolean isReplaceDbProperties() {
return getBooleanProperty(NotesConstants.iReplaceDbProperties);
}
/**
* Sets whether to replace database properties
*
* @param b BOOL, TRUE = replace database properties, FALSE Do NOT replace database propertie
*/
public void setReplaceDbProperties(boolean b) {
setBooleanProperty(NotesConstants.iReplaceDbProperties, b);
}
/**
* Returns whether the input data should bbe validated
*
* @return option or null if unknown value
*/
public XMLValidationOption getInputValidationOption() {
int optionAsInt = getInt(NotesConstants.iInputValidationOption);
for (XMLValidationOption currOpt : XMLValidationOption.values()) {
if (currOpt.getValue() == optionAsInt) {
return currOpt;
}
}
return null;
}
/**
* Defines whether the input data should bbe validated
*
* @param option validation option
*/
public void setInputValidationOption(XMLValidationOption option) {
int optionAsInt = option.getValue();
setInt(NotesConstants.iInputValidationOption, optionAsInt);
}
/**
* Returns if replica id must match
*
* @return TRUE = skip replace/update ops if target DB and import DXL do not have same replicaid's, FALSE = allow replace/update ops even if target DB and import DXL do not have same replicaid's
*/
public boolean isReplicaRequiredForReplaceOrUpdate() {
return getBooleanProperty(NotesConstants.iReplicaRequiredForReplaceOrUpdate);
}
/**
* Sets if replica id must match
*
* @param b TRUE = skip replace/update ops if target DB and import DXL do not have same replicaid's, FALSE = allow replace/update ops even if target DB and import DXL do not have same replicaid's
*/
public void setReplicaRequiredForReplaceOrUpdate(boolean b) {
setBooleanProperty(NotesConstants.iReplicaRequiredForReplaceOrUpdate, b);
}
/**
* Returns the behavior when errors occur
*
* @return TRUE = importer exits on first fatal error, FALSE = importer continues even if fatal error found
*/
public boolean isExitOnFirstFatalError() {
return getBooleanProperty(NotesConstants.iExitOnFirstFatalError);
}
/**
* Sets the behavior when errors occur
*
* @param b TRUE = importer exits on first fatal error, FALSE = importer continues even if fatal error found
*/
public void setExitOnFirstFatalError(boolean b) {
setBooleanProperty(NotesConstants.iExitOnFirstFatalError, b);
}
/**
* Returns what to do if DXL contains an unknown element or attribute
*
* @return log option or null if unknown value
*/
public DXLLogOption getUnknownTokenLogOption() {
short optionAsShort = getShort(NotesConstants.iUnknownTokenLogOption);
int optionAsInt = (int) (optionAsShort & 0xffff);
for (DXLLogOption currOpt : DXLLogOption.values()) {
if (optionAsInt == currOpt.getValue()) {
return currOpt;
}
}
return null;
}
/**
* Specifies what to do if DXL contains an unknown element or attribute
*
* @param option log option
*/
public void setUnknownTokenLogOption(DXLLogOption option) {
int optionAsInt = option.getValue();
short optionAsShort = (short) (optionAsInt & 0xffff);
setShort(NotesConstants.iUnknownTokenLogOption, optionAsShort);
}
/**
* Returns the string to be added as comment to top of result log
*
* @return comment
*/
public String getResultLogComment() {
return getStringFromMemhandle(NotesConstants.iResultLogComment);
}
/**
* Sets the string to be added as comment to top of result log
*
* @param comment comment
*/
public void setResultLogComment(String comment) {
setStringProperty(NotesConstants.iResultLogComment, comment);
}
/**
* Returns the result log from the last import
*
* @return og
*/
public String getResultLog() {
return getStringFromMemhandle(NotesConstants.iResultLog);
}
/**
* Returns a {@link NotesIDTable} listing the notes imported by the last import operation
*
* @return id table (copy of the table returned by the C API call) or null
*/
public NotesIDTable getImportedNoteList() {
return getIDTableFromHandle(NotesConstants.iImportedNoteList);
}
/**
* This function imports XML data into Domino Data based on the {@link DXLImportOption} options set.
*
* @param dxl DXL to be imported
* @param db Domino database that is to be imported
* @throws IOException in case of I/O errors
*/
public void importDxl(String dxl, NotesDatabase db) throws IOException {
importDxl(new StringReader(dxl), db);
}
/**
* This function imports XML data into Domino Data based on the {@link DXLImportOption} options set.
*
* @param in reader returning the DXL
* @param db Domino database that is to be imported
* @throws IOException in case of I/O errors
*/
public void importDxl(Reader in, NotesDatabase db) throws IOException {
importDxl(new ReaderInputStream(in, "UTF-8"), db);
}
/**
* This function imports XML data into Domino Data based on the {@link DXLImportOption} options set.
*
* @param in input stream returning the DXL
* @param db Domino database that is to be imported
* @throws IOException in case of I/O errors
*/
public void importDxl(final InputStream in, final NotesDatabase db) throws IOException {
checkHandle();
final NotesCallbacks.XML_READ_FUNCTION callback;
final Exception[] ex = new Exception[1];
if (PlatformUtils.isWin32()) {
callback = new Win32NotesCallbacks.XML_READ_FUNCTIONWin32() {
@Override
public int invoke(Pointer pBuffer, int length, Pointer pAction) {
if (ex[0] == null) {
byte[] buf = new byte[length];
try {
int readBytes = in.read(buf);
if (readBytes>0) {
pBuffer.write(0, buf, 0, readBytes);
}
return readBytes;
} catch (Exception e) {
ex[0] = e;
return 0;
}
}
else {
return 0;
}
}
};
}
else {
callback = new NotesCallbacks.XML_READ_FUNCTION() {
@Override
public int invoke(Pointer pBuffer, int length, Pointer pAction) {
if (ex[0] == null) {
byte[] buf = new byte[length];
try {
int readBytes = in.read(buf);
if (readBytes>0) {
pBuffer.write(0, buf, 0, readBytes);
}
return readBytes;
} catch (Exception e) {
ex[0] = e;
return 0;
}
}
else {
return 0;
}
}
};
}
short result;
if (PlatformUtils.is64Bit()) {
result = AccessController.doPrivileged(new PrivilegedAction() {
@Override
public Short run() {
return NotesNativeAPI64.get().DXLImport(m_hImporter, callback, db.getHandle64(), null);
}
});
}
else {
result = AccessController.doPrivileged(new PrivilegedAction() {
@Override
public Short run() {
return NotesNativeAPI32.get().DXLImport(m_hImporter, callback, db.getHandle32(), null);
}
});
}
if (ex[0] instanceof IOException) {
throw (IOException) ex[0];
}
else if (ex[0] != null) {
throw new NotesError(0, "Error during DXL import into database "+
db.getServer()+"!!"+db.getRelativeFilePath(), ex[0]);
}
NotesErrorUtils.checkResult(result);
}
/**
* Imports DXL of a source database by piping the data between an DXL producing thread and this {@link DXLImporter}
*
* @param dbSource source database
* @param exporter DXL exporter used to read exporter properties and recreate a DXLExporter in the producer thread
* @param dbTarget target database
* @param debugExportOut optional {@link OutputStream} to mirror the generated DXL content for debugging purpose, or null
*/
public void importDxlFromDBExporter(final NotesDatabase dbSource, DXLExporter exporter, final NotesDatabase dbTarget,
final OutputStream debugExportOut) {
importDxlFromExporter(dbSource, (Collection) null, false, exporter, dbTarget, debugExportOut);
}
/**
* Imports DXL of the source database ACL by piping the data between an DXL producing thread and this {@link DXLImporter}
*
* @param dbSource source database
* @param exporter DXL exporter used to read exporter properties and recreate a DXLExporter in the producer thread
* @param dbTarget target database
* @param debugExportOut optional {@link OutputStream} to mirror the generated DXL content for debugging purpose, or null
*/
public void importDxlFromACLExporter(NotesDatabase dbSource, DXLExporter exporter, final NotesDatabase dbTarget,
final OutputStream debugExportOut) {
importDxlFromExporter(dbSource, (Collection) null, true, exporter, dbTarget, debugExportOut);
}
/**
* Imports DXL of {@link NotesNote} objects in the source database by piping the data
* between an DXL producing thread and this {@link DXLImporter}
*
* @param dbSource source database
* @param ids note ids to export
* @param exporter DXL exporter used to read exporter properties and recreate a DXLExporter in the producer thread
* @param dbTarget target database
* @param debugExportOut optional {@link OutputStream} to mirror the generated DXL content for debugging purpose, or null
*/
public void importDxlFromIDExporter(final NotesDatabase dbSource, final Collection ids,
DXLExporter exporter, final NotesDatabase dbTarget, final OutputStream debugExportOut) {
importDxlFromExporter(dbSource, ids, false, exporter, dbTarget, debugExportOut);
}
/**
* Imports DXL by piping the data between an DXL producing thread and this {@link DXLImporter}
*
* @param dbSource source database
* @param ids optional note ids to export
* @param onlyACL true to export the db ACL
* @param exporter DXL exporter used to read exporter properties and recreate a DXLExporter in the producer thread
* @param dbTarget target database
* @param debugExportOut optional {@link OutputStream} to mirror the generated DXL content for debugging purpose, or null
*/
private void importDxlFromExporter(final NotesDatabase dbSource, final Collection ids, final boolean onlyACL,
DXLExporter exporter, final NotesDatabase dbTarget, final OutputStream debugExportOut) {
final Exception exporterEx[] = new Exception[1];
final PipedOutputStream dxlPipedOut = new PipedOutputStream();
PipedInputStream dxlPipedIn;
try {
dxlPipedIn = new PipedInputStream(dxlPipedOut) {
@Override
public synchronized int read() throws IOException {
if (exporterEx[0] instanceof IOException) {
throw (IOException) exporterEx[0];
}
else if (exporterEx[0]!=null) {
throw new NotesError(0, "Error in DXL producer thread", exporterEx[0]);
}
else {
return super.read();
}
}
@Override
public int read(byte[] b) throws IOException {
if (exporterEx[0] instanceof IOException) {
throw (IOException) exporterEx[0];
}
else if (exporterEx[0]!=null) {
throw new NotesError(0, "Error in DXL producer thread", exporterEx[0]);
}
else {
return super.read(b);
}
}
@Override
public synchronized int read(byte[] b, int off, int len) throws IOException {
if (exporterEx[0] instanceof IOException) {
throw (IOException) exporterEx[0];
}
else if (exporterEx[0]!=null) {
throw new NotesError(0, "Error in DXL producer thread", exporterEx[0]);
}
else {
return super.read(b, off, len);
}
}
};
} catch (IOException e2) {
throw new NotesError(0, "Error creating PipedInputStream", e2);
}
final String attOmittedTxt = exporter.getAttachmentOmittedText();
final String docTypeSYSTEM = exporter.getDoctypeSYSTEM();
final String dxlBannerComments = exporter.getDXLBannerComments();
final String dxlExportResultLogComment = exporter.getDxlExportResultLogComment();
final String dxlSchemaLocation = exporter.getDxlSchemaLocation();
final DXLExportCharset charset = exporter.getExportCharset();
final DXLMIMEOption mimeOption = exporter.getMIMEOption();
final String oleObjectOmittedTxt = exporter.getOLEObjectOmittedText();
final List omitItemNames = exporter.getOmitItemNames();
final String pictureOmittedTxt = exporter.getPictureOmittedText();
final List restrictToItemNames = exporter.getRestrictToItemNames();
final DXLRichtextOption rtOption = exporter.getRichtextOption();
final DXLValidationStyle validationStyle = exporter.getValidationStyle();
final AtomicReference dxlExportResultLogInThread = new AtomicReference();
//use separate thread to connect DXL producer and consumer
NotesThread producerThread = new NotesThread() {
@Override
public void runNotes() throws NotesException {
final AtomicReference dxlOut = new AtomicReference();
try {
NotesGC.runWithAutoGC(new Callable