Preface
This document describes the RSJ XML Archive software.

Note:
This documentation is intended to be used by application programmers and system support personnel. The average end user might not be able to understand all topics in this book.


Purpose
The purpose of RSJ XML Archive is to archive large amounts of documents. It is designed to be flexible, secure, reliable and fast. It provides the following features:
  • Compression
  • Asymmetric encryption
  • Redundant storage to compensate eventual media errors
  • Digital signing to prove authenticity and origin
  • Indexing to provide quick document search and retrieval
  • Journal operation API (based on Win32 COM)
  • Journal Load/Unload applications (Win32 console)


Design Goals
The design goals for RSJ XML Archive are:
  • Quick data access
  • International use (Unicode support)
  • Data access even years after creation
  • Access to the current journal (while it is open)
  • Data compression
  • Verification of data authenticity
  • Protection against later manipulation
  • Protection against unauthorized access
  • Redundant storage to compensate media errors
  • Independent operation


System Requirements
The following system environment is required to operate RSJ XML Archive:

Software Environment

  • Microsoft ® Windows® NT 4.0 SP6 or
    • Microsoft ® Windows® 2000 SP2 or Microsoft ® Windows® XP
  • Microsoft ® XML Parser version 4.0 SP1
  • Microsoft ® Windows® Scripting Host Version 5.6 or later is required for script-based operation

Hardware

Due to the frequent use of compression and encryption algorhythms in RSJ XML Archive, we recommend a machine equipped with at least a GHz class CPU (x86) and about 512 MB RAM.


RSJ XML Archive - Cryptography
General

RSJ XML Archive uses asymmetric and symmetric encryption to protect data from unauthorized access. Asymmetric encryption means that cipher keys consist of a complementary key pair - a public and a private key. The public key is used to encrypt and may be publicly available. The private key is used to decrypt and should be kept in a safe place.
Asymmetric encryption is used to encrypt the journal's session key; the journal data itself is protected by symmetric encryption. In other words: the session key required to decrypt journal data is encrypted using journal users' public keys. The session key is only recoverable with a private key of a journal user.

Journal Encryption

During journal creation, encryption is turned on by passing a set of public keys to the journal object. Later, the journal can be opened using any one of the private counterparts of those public keys, i.e. any user whose public key was added to the journal can later open the journal using his private key.

User Key Generation

To create user key pairs, you can use the functionality of the KeyFactory COM object. It provides methods to create complementary user keys in the format that is expected by the RSJ XML Archive.

The public part of a user key contains a tag that specifies whether the key allows write access to journals. It is set during key creation using the KeyFactory.writeAccess property.

New User

If another user shall be granted access to the journal, the journals session key must be retrieved by one of the users that have access to the journal; during this process, the public key of the new user must be available, since the session key is immediately encrypted with the new user's public key.

See the journal object's newUser() method for a detailled description of the process.


COM-based Client API

XML Archive - COM-based Client API

The XML Archive provides a COM based API that client applications can use to operate archives and journals.

The API is implemented by the COM server module xmljrnapi; its functionality is accessible through the following objects:

Name | Purpose
Archive | represents an archive object - a collection of journals that is accessible (read-only) as if it was a single journal
JournalFactory | provides an interface to create new or open existing journals
Journal | represents a journal and provides methods to add, retrieve and search documents
DocumentSequence | object returned by the journal object's document search method; represents a key sequence of documents in a journal
DocumentFactory | provides an interface to create new documents
Document | represents a journal document and provides methods to create new and serialize documents
KeyFactory | provides an interface to create cryptographic user key pairs to be used for RSJ XML Archive
RunLog | provides an interface to log messages to the RSJ XML Archive system log
Signer | provides an interface to add a signature to an XML file
Verifier | provides an interface to verify a document's signature created by the Signer-Object

Sample Program

RSJ XML Archive comes with a sample program and a set of sample XML files needed to run it prperly. More information about the sample program and how to run it can be found here.

Error Handling

If you encounter problems while using the XML Archive API, always check the error log!


Error Handling

XML Archive - Error Handling

Calls to methods of the XML Archive COM API may raise exceptions in the script code if they fail. Exceptions may also occur when dealing with properties.

To determine the cause of the problem, the XML Archive Error Log File should be checked. It is located in the root directory of the system's boot drive and named after the following pattern:

RSJErr-XXX-ISO_Date-XXXX.txt

The XXX in the name may have different meanings, e.g. machine name or some kind of ID number.

If an error might be recoverable by the calling application, the exception contains a specific, nonstandard error code that describes the problem. See the description of the method in question if and in which case it returns such an error code.

These nonstandard error codes are defined in the header file xmljerr.h, which is part of the distribution.


Sample Program

RSJ XML Journal gets installed with a sample program and a set of XML files needed to operate the program. It can be found in the Samples sub directory of the installation directory.

Click here to save a copy of the sample program or scroll down on this page to view it.

Running the sample program

To run the sample program, open an command prompt window and change to the Samples directory located in the RSJ XML Journal installation folder.

First Run

If run without arguments, the sample program will create a new journal and add 5 documents:

C:\xmljrn\Samples>cscript //nologo sample.js
Adding files to journal sample.jrn:
---------------------------------------------------------------
File:   C:\xmljrn\Samples\xml\doc1.xml
Doc ID: DocID_0
File:   C:\xmljrn\Samples\xml\doc2.xml
Doc ID: DocID_1
File:   C:\xmljrn\Samples\xml\doc3.xml
Doc ID: DocID_2
File:   C:\xmljrn\Samples\xml\doc4.xml
Doc ID: DocID_3
File:   C:\xmljrn\Samples\xml\doc5.xml
Doc ID: DocID_4

If you encounter a problem, check the error log file.

Second Run

If run with the -r switch, the journal is re-opened and another document is appended. Afterwards, the journal is finalized.

C:\xmljrn\Samples>cscript //nologo sample.js -r
Attempting to restart journal sample.jrn
Successfully added document and finalized the journal.

Third Run

If run with the -o switch, the journal is opened to locate and retrieve some documents:

C:\xmljrn\Samples>cscript //nologo sample.js -o
Attempting to open journal sample.jrn
Following documents found where key "OperatorID" is "1000000997":
DocID_2
DocID_3

Program Source

/******************************************************************************

  sample.js

  Purpose:    sample program that demonstrates how to add documents,
              restart an interrupted journal and search documents

  Author:     Markus Mueller

  Usage:      cscript sample.js [-r|-o]

              if run without arguments, it creates a journal named
              "sample.jrn" containing 5 documents

              -r reopens the journal, appends another document
              and finalizes the journal

              -o opens the journal after restart,
              searches for a document whose key "OperatorID" is "1000000997"
              and dumps its docID to stdout

******************************************************************************/

/* create some objects */
var fso = new ActiveXObject("Scripting.FileSystemObject");
var docFactory = new ActiveXObject("xmljrnapi.DocumentFactory");
var jrnFactory = new ActiveXObject("xmljrnapi.JournalFactory");

/* define some constants */
var indexTransDocID = "IndexKeyExt";
var appendedDocID = "appended doc id";
var jrnFileName = "sample.jrn";

/* search mode constants */
var xmlJrnCompEqual   = 1;
var xmlJrnCompLess    = 2;
var xmlJrnCompGreater = 4;

var args = WScript.Arguments;

/* test Runlog functionality */
var log = new ActiveXObject("xmljrnapi.RunLog");
log.runLog("SMP0001", "Sample script tests runlog access.");

/* set the base path of the journal to the current directory */
jrnFactory.basePath = fso.GetAbsolutePathName(".");

jrnFactory.fileName = jrnFileName;

var folder = fso.GetFolder(fso.GetAbsolutePathName("./xml"));
var fc = new Enumerator(folder.files);

/* xsl for key extraction */
var idx_key_domdoc = loadXML("key.xsl");

/* check arguments
 * if run without args, we create a new journal */
if (args.count() == 0) {
  createJournal();
  WScript.Quit(0);
  }

/* -r restarts the journal */
if (args(0).substring(1, 100).toLowerCase() == "r") {
  restart_journal();
  }

/* -o opens the journal and searches a document */
if (args(0).substring(1, 100).toLowerCase() == "o") {
  reopen_journal();
  }

WScript.Quit(0);

/******************************************************************************
  createJournal()
  creates a new journal, adds some documents and aborts
******************************************************************************/
function createJournal()
{

try {
  var jrn = jrnFactory.create();
  } catch(e) {
  WScript.Echo("Failed to create journal file \"" +
               jrnFactory.fileName + "\": " + e.description);
  WScript.Quit(1);
  }

/* add keys of authorized users */
var public_key_domdoc = loadXML("public.xml");
jrn.addPublicKeys(public_key_domdoc);

var idx_doc = docFactory.create();

idx_doc.xmlSource = idx_key_domdoc;
idx_doc.docID = indexTransDocID;
jrn.addDoc(idx_doc);

WScript.Echo("Adding files to journal " + jrnFactory.fileName + ":");
WScript.Echo("---------------------------------------------------------------");

/* add 5 docs and quit */
for (var i = 0; i < 5; i++) {

  var file = fso.GetFile(fc.item());
  var fn = file.Path;
  WScript.Echo("File:   " + fn);

  /* load XML source */
  var xmlDoc = loadXML(fn);

  var doc = docFactory.create();
  doc.xmlSource = xmlDoc;
  doc.docID = "DocID_" + i;
  WScript.Echo("Doc ID: " + doc.docID);
  doc.keyTransform = idx_doc;
  jrn.addDoc(doc);

  fc.moveNext();
  }

jrn.flush("FirstFlush!");
}

/******************************************************************************
  restart_journal()
  opens the aborted journal, appends a document to it and finalizes it
******************************************************************************/
function restart_journal()
{

WScript.Echo("Attempting to restart journal " + jrnFactory.fileName);

var privkeys = loadXML("private.xml");
var jrn = jrnFactory.open(privkeys, null);

/* get index transformation document */
var docSeq = jrn.searchDocs("", indexTransDocID, xmlJrnCompEqual);
if (docSeq.isEmpty) {
  WScript.Echo("Failed to locate index key transformation document in journal");
  WScript.Quit(1);
  }
var idx_key_doc = jrn.retrieveDoc(docSeq.docNo);

/* add one document */
var doc = docFactory.create();
var xmldoc = loadXML("xml\\doc1.xml");

doc.xmlSource = xmldoc;
doc.keyTransform = idx_key_doc;
doc.docID = appendedDocID;
jrn.addDoc(doc);
jrn.finalize(loadXML("private.xml"));

WScript.Echo("Successfully added document and finalized the journal.");

}

/******************************************************************************
  reopen_journal()
  re-opens the journal after restart
  searches for a document where the key OperatorID is "1000000997"
******************************************************************************/
function reopen_journal()
{
WScript.Echo("Attempting to open journal " + jrnFactory.fileName);

var privkeys = loadXML("private.xml");
try {
var jrn = jrnFactory.open(privkeys, null);
  }
catch (e) {
    WScript.Echo("Failed to open journal: " + e.description);
    WScript.Quit(1);
  }

var docSeq = jrn.searchDocs("OperatorID", "1000000997", xmlJrnCompEqual);

if (docSeq.isEmpty == false) {

  WScript.Echo('Following documents found where key "OperatorID" is "1000000997":');

   for (;;) {

     var doc = jrn.retrieveDoc(docSeq.docNo);
     WScript.Echo(doc.docID);
     if (docSeq.atEnd) {
       break;
       }
     docSeq.moveNext();
     }

  } else {
  WScript.Echo("No document found!");
  WScript.Quit(1);
  }
}

/******************************************************************************
  loadXML()
  loads an XML file into a DOM document object and returns it
******************************************************************************/
function loadXML(filename)
{
var xmldoc;

try {
  xmldoc = new ActiveXObject("Msxml2.DOMDocument.4.0");
  }
catch (e) {
  WScript.Echo("Failed to create DOM Document 4.0:" + e.description);
  WScript.Echo("Maybe MS XML Parser 4.0 is not installed?");
  WScript.Quit(1);
  }

xmldoc.async = false;
xmldoc.resolveExternals = false;
xmldoc.validateOnParse = false;
xmldoc.load(filename);

return(xmldoc);
}


JournalFactory.open Method

Life Time / Closing of Journal Objects

There is no explicit close() method for the journal object. The journal is closed implicitly when its object representation (its "containing variable") is running out of scope and if there are no more client objects depending on the journal.

This means, journal objects should never be declared globally but locally, at least if the application is intended to run for some longer time. If it is declared locally (at function level), it will be implicitly destroyed when the function returns (the journal object "runs out of scope").

If a journal object stays alive although its containing variable runs out of scope, this happens because there are still journal client (document, document sequence) objects. In this case, destruction of the journal object is delayed until the last client object is destroyed.

Caution: if raw interface pointers are used (C/C++), e.g. IJournal *pJournal, an interface still must be Released explicitly (by calling the Release() method), naturally before it runs out of scope. However, calling Release until the journal object gets destroyed is a 100% sure way to trigger a protection fault.

So why is there no close method?
It's obsolete! Let the journal run out of scope or call Release(), whatever applies. Additionally, a close() method would lead to the assumption that the underlying physical file is closed, too. However, this cannot be guaranteed since there can be any number of journal objects that operate on the same file. The physical file won't be closed until the last journal object using it is destroyed.

If interested in a more detailled explanation of the topic in general (Reference Counting), search google for "reference counting addref release".


Archive Object

Description

represents an archive object - a collection of journals that is accessible (read-only) as if it was a single journal.

Creation

var oJrnFactory = new ActiveXObject("xmljrnapi.JournalFactory");

Methods

The Journal object provides the following methods:

addJournal() | Adds a journal object to the archive
searchDocs() | Searches for documents in all journals of the archive
retrieveDoc() | Returns a Document object from the archive

Properties

The Journal object provides the following properties:

basePath | sets the base path for all relative path specifications
cacheSize | sets the number of journals kept in memory
journalCount | returns the number of journals in the archive

Example Code (JavaScript)

See the Working with Archives page.


Archive.basePath Property

basePath Property

Description

Sets or retrieves the base path to be used for all relative pathnames used by this object.

Applies to the Archive object.

Syntax

basePath

Remarks

This property is necessary since pathnames passed to XML Archive objects are not - as one would expect - relative to the current directory of the script file being executed, but to the location of the COM object server module (xmljrnapi.exe).

Therefore, it is a good idea to include this code fragment (adopt it to your needs) somewhere at the beginning of any XML Archive client program or script:

var fso = new ActiveXObject("Scripting.FileSystemObject");
var oArchive = new ActiveXObject("xmljrnapi.Archive");

/* get the current directory and pass it to the document factory */
oArchive.basePath = fso.GetAbsolutePathName(".");

Setting this property affects relative path names only; if a script does not use relative path names, setting this property is not required and has no effect.


Archive.cacheSize Property

cacheSize Property

Description

Read/write; sets or retrieves the number of journals to be kept in memory during an archive search operation.

Applies to the Archive object.

Syntax

cacheSize

Remarks

The default value is 15 (at time of writing); the best value depends heavily on the number of documents in the archive, the amount of available RAM and the search operation's compare mode. Lesser/greater searches benefit much more from a large cache.


Archive.journalCount Property

journalCount Property

Description

Read only; returns the number of journals in the Archive.

Applies to the Archive object.

Syntax

journalCount

Remarks

None


Archive.addJournal Method

addJournal() Method

Description

Adds a journal to an archive.

Applies to the Archive object.

Syntax

addJournal(
  fileName,            // filename of journal to add
  privKeyDoc,          // DOMDocument containing private user key
  sessionKeyDoc        // DOMDocument containing optional session key
  )

Parameters

fileName | file name of an existing journal file
privKeyDoc | DOMDocument object containing the private key to access the journal
sessionKeyDoc DOMDocument object containing the session key of the journal; can be NULL if privateKey is a key whose complementary public key has been added to the journal with the Journal.addPublicKeys() method.
If non-NULL, it must be the journal's session key which was encrypted using the complementary public key of privateKey.

Return values

These values can be extracted from the IErrorInfo interface in the exception handler.
S_OK | success
E_OUTOFMEMORY | not enough memory available
E_FAIL | unspecified, unrecoverable error

Remarks

See the Working with Archives page.


Archive.retrieveDoc Method

retrieveDoc() Method

Description

Returns a Document object for a specified document number. This document number is returned by the docNo property of the DocumentSequence object.

Applies to the Archive object.

Syntax

retrieveDoc(
  docNo           // Document number of document to retrieve
  )

Parameters

This method has the following parameters:

docID specifies the ID of the document to be returned.

Return values

These values can be extracted from the IErrorInfo interface in the exception handler.
S_OK | success
E_OUTOFMEMORY | system ran out of memory allocating the document
E_FAIL | unspecified, unrecoverable error

Remarks

None


Archive.searchDocs Method

searchDocs() Method

Description

Searches for documents in the Archive (i.e. across multiple journals); returns a DocumentSequence object.

Applies to the Archive object.

Syntax

searchDocs(
  keyID,           // ID of key to search
  keyValue,        // value of key to search for
  compareMode      // compare mode
  )

Parameters

This method has the following parameters:

keyID | specifies the key to be searched; if empty (""), the document id string is used (i.e. the docID property of a document object)
keyValue | specifies the value to search for
compareMode | can be either xmlJrnCompEqual, xmlJrnCompGreater or xmlJrnCompLess

Return values

These values can be extracted from the IErrorInfo interface in the exception handler.
S_OK | success
XJN_E_KEYNOTFOUND | the keyID string was not found in the index
E_FAIL | unspecified, unrecoverable error

If no matching documents are found, the returned document sequence is empty.

Remarks

See also the Working with Archives page.

The search mode constants xmlJrnCompEqual, xmlJrnCompGreater and xmlJrnCompLess are defined in VB Script progams only. Other script languages, e.g. JavaScript, require their explicit definition (JavaScript example):

var xmlJrnCompEqual   = 1;
var xmlJrnCompLess    = 2;
var xmlJrnCompGreater = 4;
.
.
.
oDocSeq = oArchive.searchDocs("", "DocID_02534", xmlJrnCompEqual);

This example returns a document sequence containing a single document whose id matches DocID_02534.


Document Object

Description

represents a document object in a journal.

Creation

The Document object is returned by the create() method of the DocumentFactory object.

Methods

The document object provides the following methods:

addIndex | manually adds the document to the journal's index
loadBinFile | initializes a document with binary data from a file
saveBinFile | saves a document's binary data to a file
loadXMLFile | initializes a document with XML data from a file
saveXMLFile | saves a document's XML data to a file

Properties

The document object provides the following properties:

binaryData | gets/sets binary contents for a document
binarySize | returns the size of the document's binary data
docID | user supplied document ID string
xmlSource | MSXML DOM Document object containing XML source
displayTransform | document object containing XSLT for displaying the document
keyTransform | document object containing XSLT for index key extraction
schemaURN | must be set to a valid schema URN if this document is a validation schema

Example Code (JavaScript)

See also the examples of the Journal and DocumentSequence object.

 var oDocFactory = new ActiveXObject("xmljrnapi.DocumentFactory");

 /* create document objects */
 var oDoc = oDocFactory.create();
 var oXMLDoc = new ActiveXObject("Msxml2.DOMDocument.4.0");
 oXMLDoc.async = false;

 /* load XML source and initialize document object */
 oXMLDoc.load("o:\\journals\\doc23235.xml");
 oDoc.xmlSource = oXMLDoc;
 oDoc.docID = "BKZxyzRNR349827";


Document.binaryData Property

binaryData Property

Description

Sets or retrieves the binary data stored in a Document object as a Safe Array or as a reference to a PDFDoc object.

Read-only for documents already part of a journal.

Applies to the Document object.

Please note the remarks on the bottom.

Syntax

  IDocument* IDoc->put_binaryData(VARIANT vArray);
  IDocument* IDoc->get_binaryData(VARIANT *vArray);

  IDocument* IDoc->put_binaryData(VARIANT *vDispatchPDFDoc);

Example

The following example shows how to initialize a document object with binary data using a SAFEARRAY:

/* example code in C++ */
VARIANT vBin;
HRESULT hr;
void *arrayData;
size_t cbData; /* number of bytes for the binary data */
void *binData; /* the data to copy to the array */

VariantInit(&vBin);
vBin.vt = VT_ARRAY;
SAFEARRAYBOUND aDim[1]; /* we create a one dimensional safe array */
aDim[0].lLbound = 0;
aDim[0].cElements = cbData + 1;

/* create a SAFEARRAY of single byte elements */
vBin.parray = SafeArrayCreate(VT_UI1, 1, aDim);
if (vBin.parray == NULL) {
return(E_FAIL);
}

/* get a pointer to the array data */
hr = SafeArrayAccessData(var->parray, &arrayData);
if (FAILED(hr)) {
VariantClear(&vBin);
return(hr);
}

/* copy data and unlock the array */
memcpy(arrayData, binData, cbData);
SafeArrayUnaccessData(vBin.parray);

/* IDoc is the document's interface; creation/initialization
* of the document omitted for brevity */
IDocument *IDoc;

hr = IDoc->put_binaryData(vBin);
/* free the array */
VariantClear(&vBin);

hr = IDoc->addIndex("Name", "Schmidt");

The next example shows how to retrieve binary data from a document:

/* example code in C++ */
HRESULT hr;
long cb; /* size of binary data in bytes */
VARIANT vBin;
void *binaryData;
IDocument *IDoc;

hr = IDoc->get_binaryData(&vBin);

/* get upper bound (number of bytes in data) */
hr = SafeArrayGetUBound(vBin.parray, 1, &cb);
if (FAILED(hr)) {
return(hr);
}

hr = SafeArrayAccessData(vBin.parray, &binaryData);

/* do something with the data */
[...]

/* free the SAFEARRAY */
SafeArrayUnaccessData(vBin.parray);
VariantClear(&vBin);

return(hr);

Remarks

  • To add a document containing binary data to the journal's index, call the addIndex() method.
  • using a SAFEARRAY for this property is recommended for C/C++ only; see example code above; the SAFEARRAY must be a one dimensional array of single byte members.
  • for scripting languages, pass a PDFDoc object to this property or use loadBinFile() or saveBinFile() instead.
  • The PDFDoc should be used whenever PDF data is to be stored in a journal, as it allows a more efficient compression
  • retrieving binary data with this property always returns a SAFEARRAY.


Document.binarySize Property

binarySize Property

Description

Returns the size of the binary data of a document. If the document does not contain binary data (either because it is not initialized or because it contains XML data), the return value is 0.

Applies to the Document object.

Syntax

binarySize

Remarks

None.


Document.displayTransform Property

displayTransform Property

Description

Sets/retrieves the display transformation XSLT of the document.

This property is of type Document. Read only for documents that are already part of a journal.

Applies to the Document object.

Syntax

displayTransform

Remarks

  • This property is not used in any way by the XML Archive itself; it is rather just stored and retrieved. It can be used by the caller e.g. to display XML documents in a web browser
  • When setting this property, the corresponding Document (value) must already be journalled (in the same journal).
  • This property becomes read-only after the document is added to a journal


Document.docID Property

docID Property

Description

User supplied document ID string; this property is read/write for documents that are not yet journalled and read only for documents already part of a journal.

Must have been set before the document object is added to a journal.

Applies to the Document object.

Syntax

docID

Remarks

None.


Document.keyTransform Property

keyTransform Property

Description

Sets/retrieves the document's index key transformation XSLT; this XSLT is used to extract the keys and values that are used to index the document.

This property is of type Document. Read only for documents that are already part of a journal.

Applies to the Document object.

Syntax

keyTransform

Remarks

This XSLT file is used to perform a transformation in order to retrieve index keys and values from the parent XML document.

For this to work, the transformation must return the following document tree:

<?xml version="1.0"?>
<index_keys>

 <index_key>
  <index_key_id>TransactionSequenceNumber</index_key_id>
  <index_key_value>1234567</index_key_value>
 </index_key>

 <index_key>
  <index_key_id>OperatorID</index_key_id>
  <index_key_value>4711</index_key_value>
 </index_key>

</index_keys>

In the XML example above, the document would be found during searches for TransactionSequenceNumber=1234567 or OperatorID=4711.

  • When setting this property, the corresponding Document (value) must already be journalled (in the same journal).
  • This property becomes read-only after the document is added to a journal


Document.schemaURN Property

schemaURN Property

Description

Sets and retrieves the document's schema URN. If set, it marks the document as being a validation schema.

Applies to the Document object.

Syntax

schemaURN

Remarks

If a document is a schema file, its schemaURN property must be set to a valid URN before the document is added to the journal. If not set, the document is not treated as a schema.

If this property is set before the document is journalled, the document is added to the journal's schema cache. This cache (collection of various schema documents) is used to validate other documents as they are added to the journal.

As soon as such a cache exists, every document that is not a schema itself is automatically validated using the schemas in the cache. To journal documents without validation, set these documents' validate property to false.


Document.validate Property

validate Property

Description

Sets and retrieves a boolean value that indicates if a document should be validated before it is journalled. Ignored if the schemaURN property is set.

Applies to the Document object.

Syntax

validate

Remarks

See remarks for the schemaURN property.


Document.xmlSource Property

xmlSource Property

Description

The document's XML source DOM object (MSXML.DOMDocument.4.0); this property is read/write for documents that are not yet journalled and read only for documents already part of a journal.

Must have been set before the document object is added to a journal.

Applies to the Document object.

Syntax

xmlSource

Remarks

Although the returned document object is in fact an instance of MSXML's DOMDocument.4.0, certain restrictions apply when the parent document object was retrieved from a journal (to be more specific, if the document object was created by the XML Journal COM server process).

Some methods and properties of DOMDocument.4.0 require that the object itself was created by the process calling the method. Such a method would fail with E_INVALIDARG if used on an object returned by the xmlSource property.

Example:

var xsltDoc = new ActiveXObject("msxml2.DOMDocument.4.0");
[...]
var doc = journal.retrieveDoc(docSeq.docNo);
var result = doc.xmlSource.transformNode(xsltDoc);

The transformNode() call fails with E_INVALIDARG.

According to this (link might be dead) article, if a method call works in release x of MSXML, it might fail in release y, so it's not safe just to try it out.

The solution is to use the xml property of the returned object to initialize a new DOMDocument.4.0:

var xsltDoc = new ActiveXObject("msxml2.DOMDocument.4.0");
[...]
var doc = journal.retrieveDoc(docSeq.docNo);

var xmlDoc = new ActiveXObject("msxml2.DOMDocument.4.0");
xmlDoc.load(doc.xmlSource.xml);

var result = xmlDoc.transformNode(xsltDoc);

Note:

This problem also applies to DOMDocument objects being added to a journal via the xmlSource property. The work around used in this case slows down journalling, so it is recommended to use either loadXMLFile or the xmlString property if performance is important.

This behaviour is by design of the MSXML toolkit.

See also:
Microsoft Knowledge Base Article - 251246
Microsoft Knowledge Base Article - 259004


Document.xmlString Property

xmlString Property

Description

Sets or retrieves the XML source of a Document object. Setting this property initializes a document and is equivalent of calling the loadXMLFile() method or setting the xmlSource property.

Read-only for documents that are already part of a journal.

Applies to the Document object.

Syntax

xmlString

Example

var file = fso.GetFile("xml\\record-001.xml");
var doc = docFactory.create();
var fXML = fso.OpenTextFile(file.Path, 1);
doc.xmlString = fXML.ReadAll();
fXML.Close();

doc.docID = "DocID_001";
doc.keyTransform = idxDoc;
jrn.addDoc(doc);

Remarks

XML strings passed to this property must be in UTF-16 encoding. This can be a pit fall: if a calling application converts XML data to UTF-16 to pass it to this property, it might still contain an XML declaration specifying a different encoding. This would result in XML data being encoded as UTF-16 but tagged as being something else - which is invalid.

This property is somewhat faster than the old-style property via the document's xmlSource propery, at least if a DOMDocument object passed to xmlSource is not used by the client for anything else.


Document.addIndex Method

addIndex Method

Description

Directly adds a document to the index.

Normally, document index entries are automatically retrieved using the documents keyTransform style sheet.

This method can be used if the transformation is not possible (binary data) or available.

Applies to the Document object.

Syntax

addIndex(
  keyName            // name of index key
  keyValue           // index key value
  )

Remarks

The document must not be journalled when this method is called.


Document.loadBinFile Method

loadBinFile Method

Description

Initializes a Document object by loading binary data from a file.

May not be called for documents that are already part of a Journal.

Applies to the Document object.

Note: Use the loadXMLFile() method to initialize a document object with XML data.

Syntax

loadBinFile(
  fileName            // path and file name of binary file
  )

Example

binDoc.loadBinFile("dk-coast.jpg");
binDoc.docID = "binary sample";

/* we cannot use an index key transformation here, since this
 * is no parsable XML
 */
binDoc.addIndex("location", "coast");

journal.addDoc(idxDoc);

Remarks

None.


Document.loadXMLFile Method

loadXMLFile Method

Description

Initializes a Document object by loading XML data from a file.

May not be called for ducoments that are already part of a Journal.

Applies to the Document object.

Syntax

loadXMLFile(
  fileName            // path and file name of XML file
  )

Example

var idxDoc = docFactory.create();
var idxKeyFn = ".\\xml\\key.xsl";

idxDoc.loadXMLFile(idxKeyFn);
idxDoc.docID = "indexTransDoc";
journal.addDoc(idxDoc);

Remarks

This method is somewhat faster than the old-style method via the document's xmlSource propery.


Document.saveBinFile Method

saveBinFile Method

Description

Saves the binary data of a Document object to a file.

Applies to the Document object.

Note: Use the saveXMLFile() method if the document does not contain binary data.

Syntax

saveBinFile(
  fileName            // path and file name of binary file
  )

Remarks

None.


Document.saveXMLFile Method

saveXMLFile Method

Description

Saves the XML data of a Document object to a file.

Applies to the Document object.

Note: Use the saveBinFile() method if the document contains binary data.

Syntax

saveXMLFile(
  fileName            // path and file name of binary file
  )

Remarks

None.


DocumentFactory Object

Description

provides an interface to create Document objects.

Creation (JavaScript)

var oDocFactory = new ActiveXObject("xmljrnapi.DocumentFactory");

Methods

The DocumentFactory object provides the following methods:

create() creates a new, empty document object

Properties

None.

Example Code (JavaScript)

See the example for the journal object.


DocumentFactory.create Method

create() Method

Description

Creates a new, empty document object.

Applies to the DocumentFactory object.

Syntax

create()

Parameters

None.

Return values

These values can be extracted from the IErrorInfo interface in the exception handler.
S_OK | success
E_FAIL | unspecified, unrecoverable error

Remarks

None.


DocumentSequence Object

Description

Represents a journal search result as a sequence of matching documents.

Creation

The DocumentSequence object is returned by the searchDocs() method of the Journal object and the searchDocs() method of the Archive object.

Methods

The Document object provides the following methods:

moveNext() Moves to the next document in the sequence of matching documents

Properties

The DocSequence object provides the following properties:

curJournal | returns the current journal in an archive-wide search
docNo | returns the document number of the current document
atEnd | returns true if the current document is the last or if the sequence is empty
isEmpty | returns true if the sequence is empty (no matches)

Example Code (JavaScript)

 var oJrnFactory = new ActiveXObject("xmljrnapi.JournalFactory");
 var customer_no = "3432423";
 var oXMLKey = new ActiveXObject("Msxml2.DOMDocument.4.0");
 var cnt = 0;
 var xmlJrnCompEqual   = 1;
 var xmlJrnCompLess    = 2;
 var xmlJrnCompGreater = 4;

 /* load user's private key document */
 oXMLKey.async = false;
 oXMLKey.load("o:\\users\\fred\\private_key.xml");

 /* open existing journal */
 var oJrn = oJrnFactory.open("32895790.jrn",
                             oXMLKey,
                             NULL);

 /* search all invoices for a certain customer */
 var oDocSeq = oJrn.searchDocs("customer_no",
                               customer_no,
                               xmlJrnCompEqual);

 /* retrieve all invoices for this customer */
 if (oDocSeq.isEmpty == false) {

   for (;;)  {

     var oDoc = oJrn.retrieveDoc(oDocSeq.docNo);
     cnt++;
     .
     .
     if (oDocSeq.atEnd) {
       break;
       }

     oDocSeq.moveNext();
     }

   WScript.Echo("The search returned " + cnt + " results.");


DocumentSequence.moveNext Method

moveNext() Method

Description

Moves to the next document in the sequence of matching documents. Fires an exception if the current document is the last or if the sequence does not contain any documents.

Applies to the DocumentSequence object.

Syntax

moveNext()

Parameters

None

Return values

These values can be extracted from the IErrorInfo interface in the exception handler.
S_OK | success
XJN_E_NOMOREHITS | no more hits; attempt was made to move beyond end of sequence
E_FAIL | unspecified, unrecoverable error

Remarks

None


DocumentSequence.atEnd Property

atEnd Property

Description

Read only; returns true if the current document in the sequence is the last or if the sequence is empty; false if not.

Applies to the DocumentSequence object.

Syntax

atEnd

Remarks

None


DocumentSequence.docNo Property

docNo Property

Description

Read only; returns the document number of the sequence's current document.

This number is automatically assigned to each document added to a journal and uniqueley identifies journalled documents; it is passed to the retrieveDoc method of the Journal object.

Applies to the DocumentSequence object.

Syntax

docNo

Remarks

None


DocumentSequence.isEmpty Property

isEmpty Property

Description

Read only; returns true if the document sequence is empty, false if not.

Applies to the DocumentSequence object.

Syntax

isEmpty

Remarks

None


JournalFactory Object

Description

provides an interface to create, open and repair Journal objects.

Creation (JavaScript)

var oJrnFactory = new ActiveXObject("xmljrnapi.JournalFactory");

Methods

The JournalFactory object provides the following methods:

create() | creates a new journal
open() | opens an existing journal
repair() | attempts to repair a journal that could not be opened due to media failure

Properties

The JournalFactory object provides the following properties:

basePath | sets the base path for all relative path specifications
fileName | sets or retrieves the file name of the journal being created/opened
readOnly | specifies whether the next open() call should open the journal in read-only mode
compressionMode | specifies the compression algorithm used for the journal
jrnVersion | retrieves the version string for RSJ XML Archive

Example Code (JavaScript)

See the example for the journal object.


JournalFactory.create Method

create() Method

Description

Creates a new, empty journal.

Applies to the JournalFactory object.

Syntax

create()

Parameters

None.

Return values

These values can be extracted from the IErrorInfo interface in the exception handler.
S_OK | success
XJN_E_ALREADYEXISTING | The physical file already exists; it won't be overwritten
E_ACCESSDENIED | Access was denied creating the journal file
E_FAIL | unspecified, unrecoverable error

Remarks

The fileName property must be set before calling this method. The file referenced must not yet exist.

To append to an existing (aborted) journal, use the open() method.


JournalFactory.open Method

open() Method

Description

Opens an existing journal.

Applies to the JournalFactory object.

Syntax

open(
  privateKey,    /* DOMDocument object specifying the private key
                  * to be used for decryption */
  sessionKey     /* DOMDocument object specifying the journal's
                  * encrypted session key */
  )

Parameters

This method has the following parameters:

privateKey DOMDocument object containing the private key to access the journal
sessionKey DOMDocument object containing the session key of the journal; can be NULL if privateKey is a key whose complementary public key has been added to the journal with the Journal.addPublicKeys() method.
If non-NULL, it must be the journal's session key which was encrypted using the complementary public key of privateKey.

Return values

These values can be extracted from the IErrorInfo interface in the exception handler.
S_OK | success
XJN_E_NOTFOUND | The physical file was not found
E_ACCESSDENIED | Access was denied attempting to open the journal file
E_FAIL | unspecified, unrecoverable error

Remarks

This method is also used to restart (in other words: append to) an existing journal that was not finalized. In this case, the journal object is opened in read/write mode. If the journal file was finalized, the returned journal object is read-only and write operations will fail.

To determine if any given journal is finalized, use the isFinalized property of the Journal object.

See also the notes about journal object life time here.


JournalFactory.repair() Method

repair() Method

Description

Attempts to repair a journal that failed to be opened due to media read errors.

Note: The repair attempt should be carried out with a copy of the journal file on a a reliable disk.

Applies to the JournalFactory object.

Syntax

repair()

Parameters

None.

Return values

These values can be extracted from the IErrorInfo interface in the exception handler.
S_OK | success
E_FAIL | repair attempt failed

Remarks

The fileName property must be set before calling this method.

After a successfull return, you can use the journal as usual. The journal file will be updated with the corrected data during repair.


JournalFactory.basePath Property

basePath Property

Description

Sets or retrieves the base path to be used for all relative pathnames for all journals created by this object.

Applies to the JournalFactory object.

Syntax

basePath

Remarks

This property is necessary since pathnames passed to XML Archive objects are not - as one would expect - relative to the current directory of the script file being executed, but to the location of the COM object server module (xmljrnapi.exe).

Therefore, it is a good idea to include this code fragment (adopt it to your needs) somewhere at the beginning of any XML Archive client program or script:

var fso = new ActiveXObject("Scripting.FileSystemObject");
var oJrnFactory = new ActiveXObject("xmljrnapi.JournalFactory");

/* get the current directory and pass it to the document factory */
oJrnFactory.basePath = fso.GetAbsolutePathName(".");

Setting this property affects relative path names only; if a script does not use relative path names, setting this property is not required and has no effect.


JournalFactory.compressionMode Property

compressionMode Property

Description

Sets or retrieves the compression algorithm used to compress the journal. The default is PPMD.

In order to take effect, this property must be set before the journal is created.

Applies to the JournalFactory object.

Syntax

compressionMode

Remarks

The following compression algorithms are available:

Symbol | Value | Name | Description
xmlJrnCompressionNone 1 - Use no compression at all
xmlJrnCompressionPPMD | 2 | PPMD | Very efficient text compression algorithm; rather high CPU usage (default mode in XML Archive)
xmlJrnCompressionBZIP | 3 | bzip | Very efficient compression algorithm (rather for binary data); high CPU usage
xmlJrnCompressionZLIB | 4 | zlib | Compression ratio not as good as bzip or ppmd, but low CPU usage

The symbols (xmlJrnCompression...) are defined in VBScript only; in JScript and other languages, these symbols must be defined manually:

var xmlJrnCompressionNone = 1;
var xmlJrnCompressionPPMD = 2;
var xmlJrnCompressionZLIB = 3;
var xmlJrnCompressionBZIP = 4;
.
.
.
jrnFactory.compressionMode = xmlJrnCompressionBZIP;
var jrn = jrnFactory.create();


JournalFactory.fileName Property

fileName Property

Description

Sets or retrieves the filename to be used by subsequent calls to the open() and create() methods.

Applies to the JournalFactory object.

Syntax

fileName

Remarks

This property must be set before calling open(), create() or repair().


JournalFactory.jrnVersion Property

jrnVersion Property

Description

Returns the product version of the RSJ XML Archive.

Applies to the JournalFactory object.

Syntax

jrnVersion

Remarks

None

Sample

var jf = new ActiveXObject("xmljrnapi.JournalFactory");

WScript.Echo(jf.jrnVersion);

The output of this sample would be e.g.:

0.09.0009


JournalFactory.readOnly Property

readOnly Property

Description

Boolean value; sets or retrieves if the next call to the open() method should open the journal in read-only mode. The default value is false, meaning that journals are opened as read-write by default.

In order to take effect, this property must be set before the journal is opened.

Applies to the JournalFactory object.

Syntax

readOnly

Remarks

It is recommended to use this property to allow smooth operation across networks. If the current task does not require write access, this property should be set to true.

This property is ignored if the journal is already finalized (in which case it is always read-only).


Journal Object

Description

represents a journal and provides methods to add, retrieve and search documents etc.

Creation

The Journal object is returned by the create() and open() methods of the JournalFactory object.

Methods

The Journal object provides the following methods:

load() | Initializes the journal object by loading an XML file created by a journal unload operation
addPublicKeys() | Adds public user keys to the journal (turns on encryption)
addDoc() | Adds a document to the journal
flush() | Flushes a journal to persistant storage
searchDocs() | Searches for documents in the journal
retrieveDoc() | Returns a Document object from the journal
finalize() | Finalizes (end-of-day) a journal
verifySignature() | verifies the internal signature of the journal

Properties

The Journal object provides the following properties:

flushTag | retrieves the tag string used during the last flush
docCount | returns the number of documents in the journal
isFinalized | returns true if the journal is finalized, false if not
isReadOnly | returns true if the journal is read only
fileName | returns the name of the journal file
externalSignatureDoc | sets/retrieves a DOMDocument containing an external signature
foreignSignature | sets/retrieves a foreign signature that must be verified by a third party
hash | retrieves the current hash value for the journal

Example Code (JavaScript)

See the sample program page.


Journal.addDoc Method

addDoc() Method

Description

Adds a document to the journal; may be called only if the corresponding journal object was not yet finalized.

Applies to the Journal object.

Syntax

addDoc(
  oDocument            // document to add
  )

Parameters

oDocument user document that is to be journalled; this must be a completely initialized document object created with the DocumentFactory object.

Return values

These values can be extracted from the IErrorInfo interface in the exception handler.
S_OK | success
XJN_E_ALREADYFINALIZED | the journal is already finalized, thus read-only
E_INVALIDARG | the document object passed in is not properly initialized
E_FAIL | unspecified, unrecoverable error

Remarks

None


Journal.addPublicKeys Method

addPublicKeys() Method

Description

Adds the public user keys to the journal; the complementary private keys can then be used to obtain read access the journal.

Applies to the Journal object.

Syntax

addPublicKeys(
  oXMLKeys         // DOMDocument object encapsulating a public key
  )

Parameters

oXMLKeys specifies a DOMDocument object representing an XML file that contains all public user keys.

Return values

These values can be extracted from the IErrorInfo interface in the exception handler.
S_OK | success
E_INVALIDARG | the key document object passed in is not properly initialized
E_FAIL | unspecified, unrecoverable error

Remarks

Public user keys contain a tag that specifies whether a certain user is allowed write access. The journal creator (the "one" calling addPublicKeys) has the option to add or remove this tag from public keys to allow or disallow write access. The tag is initially set by the KeyFactory.writeAccess property.

A sample key document could look like this:

<PublicKeys>
 <PublicKey>64cbb3f3e5150d22ecd6447dde1fda6414a4b561
 <KeyType>RSA</KeyType>
 <KeyVersion>0</KeyVersion>
 <Modulus>3a5457849f207...</Modulus>
  <PublicExponent>10001</PublicExponent>
  <WriteAccess/>
 </PublicKey>

 <PublicKey>64cbb3f3e5150d22ecd64353454354447dde1fda
 <KeyType>RSA</KeyType>
 <KeyVersion>0</KeyVersion>
 <Modulus>3a5457849f20...</Modulus>
  <PublicExponent>10001</PublicExponent>
 </PublicKey>

</PublicKeys>
The first key is allowed write access (note presence of a single <WriteAccess> tag), the second not.

See also

XML Archive - Cryptography


Journal.finalize Method

finalize() Method

Description

Finalizes a journal (end of day); after the journal is finalized, it cannot be changed anymore.

Applies to the Journal object.

Syntax

finalize(
  signerKeyDoc    // DOMDocument containing private key of signer
  )

Parameters

This method has the following parameters:

signerKeyDoc specifies a DOMDocument object containing the private key of the signer

Return values

These values can be extracted from the IErrorInfo interface in the exception handler.
S_OK | success
E_INVALIDARG | the key document object passed in is not properly initialized or invalid
E_FAIL | unspecified, unrecoverable error

Remarks

This method must be called after the last document was added.


Journal.flush Method

flush() Method

Description

Flushes a journal to persistant storage; only valid for journals that are not yet finalized.

Applies to the Journal object.

Syntax

flush(
  tagString       // string specifiying a unique tag for the flush
  )

Parameters

This method has the following parameters:

tagString specifies a unique string (i.e. an id, the restart position, ...) that tags the flush so it can be referenced later

Return values

These values can be extracted from the IErrorInfo interface in the exception handler.
S_OK | success
E_FAIL | unspecified, unrecoverable error

Remarks

A successfull call to the flush method means that all data written since the last flush (or the journal creation) is stored in persistant storage.

If, for any reason, journal creation gets interrupted (e.g. due to a hardware error), only documents added before the last flush call are recoverable. Documents added after the last flush call are discarded.


Journal.load Method

load() Method

Description

Initializes the journal object by loading a (possibly incomplete) XML file created by a journal unload operation.

Applies to the Journal object.

Syntax

load(
  fileName       /* name of a file containing XML data created during a journal unload */
  )

Parameters

This method has the following parameters:

fileName name of the file containing XML data

Return values

These values can be extracted from the IErrorInfo interface in the exception handler.
S_OK | success
E_FAIL | unspecified, unrecoverable error

Other errors might be returned if they were raised in the MSXML layer.

Remarks

None

Example Code (JavaScript)

Click here for a detailled description about how to unload a journal (i.e. create an XML stream from a journal).

/* create the journal factory */
var jrnFactory = new ActiveXObject("xmljrnapi.JournalFactory");
jrnFactory.fileName = "c:\\xmlarchive\\samples\\load.jrn";

/* create w new, empty journal and load the XML stream */
var jrn = jrnFactory.create();
jrn.load("c:\\xmlarchive\\samples\\sample.xml");

/* perform a document search */
var docSeq = jrn.searchDocs("OperatorID", "1000000997", 1);

if (docSeq.isEmpty == false) {

  WScript.Echo('Following documents found where key "OperatorID" is "1000000997":');

   for (;;) {

     var doc = jrn.retrieveDoc(docSeq.docNo);
     WScript.Echo(doc.docID);
     if (docSeq.atEnd) {
       break;
       }
     docSeq.moveNext();
     }

  } else {
  WScript.Echo("No document found!");
  }

WScript.Echo("No errors detected.");
jrn.finalize(null);
jrn.close();


Journal.retrieveDoc Method

retrieveDoc() Method

Description

Returns a Document object for a specified document number. This document number is returned by the docNo property of the DocumentSequence object.

Applies to the Journal object.

Syntax

retrieveDoc(
  docNo           // Document number of document to retrieve
  )

Parameters

This method has the following parameters:

docID specifies the ID of the document to be returned.

Return values

These values can be extracted from the IErrorInfo interface in the exception handler.
S_OK | success
E_OUTOFMEMORY | system ran out of memory allocating the document
E_FAIL | unspecified, unrecoverable error

Remarks

None


Journal.save Method

save() Method

Description

Stores the entire contents of this journal in an XML file.

Applies to the Journal object.

Syntax

save(
  fileName       /* name of the target file */
  )

Parameters

This method has the following parameters:

fileName name of the target file; if the file exists, it will be overwritten!

Return values

These values can be extracted from the IErrorInfo interface in the exception handler.
S_OK | success
E_FAIL | unspecified, unrecoverable error

Remarks

None


Journal.searchDocs Method

searchDocs() Method

Description

Searches for documents in the journal; returns a DocumentSequence object.

Applies to the Journal object.

Syntax

searchDocs(
  keyID,           // ID of key to search
  keyValue,        // value of key to search for
  compareMode      // compare mode
  )

Parameters

This method has the following parameters:

keyID | specifies the key to be searched; if empty (""), the document id string is used (i.e. the docID property of a document object)
keyValue | specifies the value to search for
compareMode | can be either xmlJrnCompEqual, xmlJrnCompGreater or xmlJrnCompLess

Return values

These values can be extracted from the IErrorInfo interface in the exception handler.
S_OK | success
XJN_E_KEYNOTFOUND | the keyID string was not found in the index
E_FAIL | unspecified, unrecoverable error

If no matching documents are found, the returned document sequence is empty.

Remarks

The search mode constants xmlJrnCompEqual, xmlJrnCompGreater and xmlJrnCompLess are defined in VB Script progams only. Other script languages, e.g. JavaScript, require their explicit definition (JavaScript example):

var xmlJrnCompEqual   = 1;
var xmlJrnCompLess    = 2;
var xmlJrnCompGreater = 4;
.
.
.
oDocSeq = oJrn.searchDocs("", "DocID_02534", xmlJrnCompEqual);

This example returns a document sequence containing a single document whose id matches DocID_02534.


Journal.verifySignature Method

verifySignature() Method

Description

Verifies the internal signature of the journal and returns the oldest signature's time stamp in the format

YYYY-MM-DD HH:MM:SS GMT

Throws an exception if the signature cannot be verified or some other error occurs.

Applies to the Journal object.

Syntax

verifySignature(
  pubKeyDOMDoc    // DOMDocument containing public key of signer
  )

Parameters

This method has the following parameters:

pubKeyDOMDoc specifies a DOMDocument object containing the public key of the signer

Return values

These values can be extracted from the IErrorInfo interface in the exception handler.
S_OK | success
XJN_E_XMLSOURCEINVALID | the key document passed in is invalid or empty
E_FAIL | unspecified, unrecoverable error

Remarks

None


Journal.docCount Property

docCount Property

Description

Read only; returns the number of documents in the journal.

Applies to the Journal object.

Syntax

docCount

Remarks

None


Journal.externalSignatureDoc Property

externalSignatureDoc Property

Description

Sets/retrieves an external signature DOMDocument (Msxml.DOMDocument.4.0) for the journal.

Applies to the Journal object.

Syntax

externalSignatureDoc

Parameters

None.

Remarks

An external signature's timestamp is created by an external, trusted, time source. In contrast to the foreign signature, it can be interpreted and thus verified by the COM API.


Journal.fileName Property

fileName Property

Description

Read only; returns the name of the journal file.

Applies to the Journal object.

Syntax

fileName

Remarks

None


Journal.flushTag Property

flushTag Property

Description

Read only; retrieves the tag string used during the last flush.

Applies to the Journal object.

Syntax

flushTag

Remarks

None


Journal.foreignSignature Property

foreignSignature Property

Description

Sets/retrieves a foreign signature for the journal.

Applies to the Journal object.

Syntax

foreignSignature

Parameters

None.

Remarks

A foreign signature is entirely created by a third party. In contrast to the external signature, it can not be interpreted and thus not be verified by the COM API.

Use the hash property of the journal object to retrieve the hash value of a journal (needed by the foreign signature creator).


Journal.hash Property

hash Property

Description

Retrieves the current hash value of the journal. This value is updated during any write operation that occurs.

Can be used to create a foreign signature.

Applies to the Journal object.

Syntax

hash

Parameters

None.

Remarks

None.


Journal.isFinalized Property

isFinalized Property

Description

Read only; returns true if the journal is finalized; false if not. As documents may not be added to finalized journals, this method also indicates if a journal is read-only.

Applies to the Journal object.

Syntax

isFinalized

Remarks

None


Journal.isReadOnly Property

isReadOnly Property

Description

Read only; returns true if the journal is read-only; false if not.

Journals are read-only if they are already finalized or if the authenticated user has no write access rights to the journal.

Applies to the Journal object.

Syntax

isReadOnly

Remarks

None


KeyFactory Object

Description

provides an interface to create cryptographic user key pairs to be used for RSJ XML Archive.

Creation (JavaScript)

var oDocFactory = new ActiveXObject("xmljrnapi.KeyFactory");

Methods

The KeyFactory object provides the following methods:

create() creates a new key pair that can be retrieved using the properties described below

Properties

The KeyFactory object provides the following properties:

writeAccess | sets/retrieves whether the next key should be granted write access to journals
publicKeyDoc | returns a DOM Document (MSXML.DOMDocument.4.0) containing the public key just created
privateKeyDoc | returns a DOM Document (MSXML.DOMDocument.4.0) containing the private key just created

See also

RSJ XML Archive - Cryptography

Example Code (JavaScript)

var keyFactory = new ActiveXObject("xmljrnapi.KeyFactory");

keyFactory.create();
var privateKeyDoc = keyFactory.privateKeyDoc;
var publicKeyDoc = keyFactory.publicKeyDoc;

/* save XML keys to persistant storage */
privateKeyDoc.save("o:\\users\\keys\\234934\\private.xml");
publicKeyDoc.save("o:\\users\\keys\\234934\\public.xml");


KeyFactory.create Method

create() Method

Description

Creates a new complementary key pair.

Applies to the KeyFactory object.

Syntax

create()

Parameters

None.

Return values

These values can be extracted from the IErrorInfo interface in the exception handler.
S_OK | success
E_FAIL | unspecified, unrecoverable error

Remarks

The keys can be retrieved with the publicKeyDoc and privateKeyDoc properties.


KeyFactory.keyLength Property

keyLength() Property

Description

Sets/retrieves the bit-length of the keys created. The default is 2048.

Applies to the KeyFactory object.

Syntax

keyLength

Parameters

None.

Remarks

None.


KeyFactory.privateKeyDoc Property

privateKeyDoc() Property

Description

Retrieves the private key previously created with the create() method. The object returned is an MSXML.DOMDocument.4.0 object.

Applies to the KeyFactory object.

Syntax

privateKeyDoc

Parameters

None.

Remarks

None.


KeyFactory.publicKeyDoc Property

publicKeyDoc() Property

Description

Retrieves the public key previously created with the create() method. The object returned is an MSXML.DOMDocument.4.0 object.

Applies to the KeyFactory object.

Syntax

publicKeyDoc

Parameters

None.

Remarks

None.


KeyFactory.writeAccess Property

writeAccess() Property

Description

Sets or retrieves whether the owner of the key generated during the next create() call shall be allowed write access to journals.

Applies to the KeyFactory object.

Syntax

writeAccess

Parameters

None.

Remarks

The default is writeAccess = true, that is, any user key is granted write access to journals.

See also the remarks in the cryptography section and for the journal.addPublicKeys() method.


PDFDoc Object

Description

implements a generic PDF document interface that can be used to journal PDF documents and decompress them; this is useful because compressed PDF documents cannot be journalled efficiently.

In other words, if a Document is to contain a PDF document as binary data, the resulting journal will be smaller if the PDF is decompressed.

Creation (JavaScript)

var oPDFDoc = new ActiveXObject("xmljrnapi.PDFDoc");

Methods

The PDFDoc object provides the following methods:

decompress() | decompress the contained PDF document
savePDFFile() | saves contained PDF data to a file
loadPDFFile() | loads PDF data to from a file

Properties

The PDFDoc object provides the following proerties:

pdfData get/set PDF binary data (SAFEARRAY)


PDFDoc.pdfData Property

pdfData() Property

Description

Sets or retrieves the PDF data of a PDFDoc object as a SAFEARRAY. This method is recommended only for C/C++ clients; scripting languages should use loadPDFFile() or savePDFFile(), respectively.

For an example how to use SAFEARRAYs for this purpose, see the example of the binaryData property of the Document object.

Applies to the PDFDoc object.

Syntax

  PDFDoc.pdfData

Return values

These values can be extracted from the IErrorInfo interface in the exception handler.
S_OK | success
E_FAIL | unspecified, unrecoverable error
E_OUTOFMEMORY | not enough memory available

Remarks

None.


PDFDoc.decompress Method

decompress() Method

Description

Decompresses a PDF document if it is compressed. The caller does not need to verify if the PDF document is compressed.

Applies to the PDFDoc object.

Naturally, the PDFDoc object must be initialized with PDF data before this method can be called.

Syntax

decompress(
  );

Parameters

This method needs no arguments.

Return values

These values can be extracted from the IErrorInfo interface in the exception handler.
S_OK | success
E_FAIL | unspecified, unrecoverable error
E_OUTOFMEMORY | not enough memory available

Remarks

None.


PDFDoc.loadPDFFile Method

loadPDFFile Method

Description

Loads a PDF file to initialize a PDFDoc object.

Applies to the PDFDoc object.

Syntax

loadPDFFile(
  fileName            // path and file name of source file
  )

Remarks

None.


PDFDoc.savePDFFile Method

savePDFFile Method

Description

Saves the PDF data contained in a PDFDoc object to a file.

Applies to the PDFDoc object.

Syntax

savePDFFile(
  fileName            // path and file name of target file
  )

Remarks

None.


RunLog Object

Description

provides an interface to log messages to the RSJ XML Archive system log.

Creation (JavaScript)

var oRunLog = new ActiveXObject("xmljrnapi.RunLog");

Methods

The RunLog object provides the following methods:

runLog() log message to the run log

Properties

None


RunLog.runLog Method

runLog() Method

Description

Logs a message to the XML Archive system log.

Applies to the RunLog object.

Syntax

runLog(
  messageID,       // preferably unique message id
  message          // message
  )

Parameters

This method has the following parameters:

messageID | preferably unique message id, e.g. "MOT0001". This ID is used to easily locate the source of the message in the program code
message | the message to put into the runlog

Return values

These values can be extracted from the IErrorInfo interface in the exception handler.
S_OK | success
E_FAIL | unspecified, unrecoverable error

Remarks

This call is the same as the well-known RunLog2() C-call, except that it does not support variable argument lists.


Signer Object

Description

provides an interface to add a signature to an XML file. The Verifier-Object can be used to verify signatures created with the Signer object.

Creation (JavaScript)

var oSigner = new ActiveXObject("xmljrnapi.Signer");

Methods

The Signer object provides the following methods:

sign() signs an XML document

Properties

The Signer object provides the following properties:

privateKey sets/retrieves the private key used to sign the document

See also

RSJ XML Archive - Cryptography


Signer.sign Method

sign() Method

Description

Signs an XML document. Returns a signed copy of the document passed in.

Applies to the Signer object.

Syntax

sign(
  xmlDoc,        /* DOMDocument object containing the XML document to be signed */
  signNodeName   /* name to be used for the signature node */
  ignoreNodes    /* X-Path query string specifiying the nodes to be ignored */
  )

Parameters

This method has the following parameters:

xmlDoc | DOMDocument object containing the XML document to be signed
signNodeName | string specifying the name of the node that is created for the signature
ignoreNodes | XPath query string is used to determine parts of the document that are to be ignored when creating the signature. This allows to specify ranges in the document that can be changed without breaking the signature. May be empty if not needed. See remarks below.

Remarks

  • The privateKey property must be set before calling this method.
  • The ignoreNodes paramater must be an XPath query string that selects one or more XPath string contained in the document; the "second level" XPath query string(s) is (are) supposed to specify the nodes of the document whose content is to be ignored.

    Consider the following example: the document to be signed contains the nodes

    <ModifiableSection>ignore</ModifiableSection>
<ModifiableSection>ignore_too</ModifiableSection>

    A call to the sign method using "ModifiableSection" as the ignoreNodes parameter would result in all nodes named "ignore" or "ignore_too" being ignored when the signature is created.


Signer.privateKey property

privateKey Property

Description

Sets/retrieves the DOMDocument object containing the private key used for signing.

Applies to the Signer object.

Syntax

privateKey

Remarks

None.


Verifier Object

Description

provides an interface to verify a document's signature created by the Signer-Object.

Creation (JavaScript)

var oVerifier = new ActiveXObject("xmljrnapi.Verifier");

Methods

The Verifier object provides the following methods:

verify() verifies a signature

Properties

The Verifier object provides the following properties:

publicKey sets/retrieves the public key used to verify the signature

See also

RSJ XML Archive - Cryptography


Verifier.verify Method

verify() Method

Description

verifies a signature created by the Signer-Object. Returns a non-zero value if the verification is successful.

Applies to the Verifier object.

Syntax

verify(
  xmlDoc,        /* DOMDocument object containing the signed XML document to be verified */
  signatureNodeName   /* name of the node continaing the signature */
  ignoreNodes    /* X-Path query string specifiying the nodes to be ignored */
  )

Parameters

This method has the following parameters:

xmlDoc | DOMDocument object containing the signed XML document to be verified
verifyNodeName | string specifying the name of the node that contains the signature
ignoreNodes | X-Path query string that indirectly specifies nodes that are to be ignored during verification. See remarks for the sign() method.

Remarks

The publicKey property must be set before calling this method.

See also the remarks for the sign() method.


Verifier.publicKey property

publicKey Property

Description

Sets/retrieves the DOMDocument object containing the public key key used to verify a signature.

Applies to the Verifier object.

Syntax

publicKey

Remarks

None.


Procedures

RSJ XML Archive - Guide

This chapter describes various procedures involved in working with RSJ XML Archive.

Cryptographic Key Generation

Cryptographic key pairs are generated from within a script program by the KeyFactory object.
See also the general notes about cryptography in RSJ XML Archive.

Journal Unload

How to save an entire journal into a single XML data stream.

Recovering From Media Errors

How to recover journals in case of media errors.


Journal Unload

Purpose

When a journal is unloaded, all its contents are dumped into a valid XML stream. This includes, naturally, all documents and cryptographic user keys.

Note: The unloaded XML data is neither compressed nor encrypted!

The distribution contains a small JavaScript program named jrnunload.js that dumps XML data to a file.

Syntax

cscript jrnunload.js <journal file name>
                     <output file name>
                     [private key file]
                     [session key file]

Parameters

journal file name | file name of the journalled XML file that is to be unloaded; required
output file name | file name of the target XML file to write to
private key file | name of the file containing a private user key that is to be used for decryption; optional if the journal was not encrypted
session key file | file name of a session key that was encrypted using the public key belonging to the private key file name passed in the second parameter; optional, see remarks below

Remarks

The session key file parameter is only needed if the private key passed as parameter 2 is not a counterpart of a public key known to the journal. The session key must then be encrypted with the public counterpart of the private key passed as parameter 2.

See RSJ XML Archive - Cryptography for more information.


Recovering Media Errors

Recovering from Media Errors

RSJ XML Archive contains error correction algorithms that store redundant error correction information along with the main data. Using this information, it is possible to recover from hardware errors, e.g. bad hard disk sectors.

See the documentation for the repair() method of the JournalFactory object for more details.


Working With Archives

Introduction

The Journal object provides powerful search and retrieval functions, but these are - naturally - limited to a single journal. To allow simple and fast read only access to multiple journals and search operations across multiple journals, RSJ XML Archive contains an object named Archive.

How it is done

After creating an archive object, any number of journal objects can be added to the archive (limited by available RAM, only). After that, a search operation is done exactly the same way as it is done in a single journal.

Create archive object:

var oArchive = new ActiveXObject("xmljrnapi.Archive");

/* set the base path for all relative path names */
oArchive.basePath = fso.GetAbsolutePathName(".");

Create a journal file enumeration and add every journal in this directory to the archive:

var fso = new ActiveXObject("Scripting.FileSystemObject");

var folder = fso.GetFolder(fso.GetAbsolutePathName("."));
var journals = new Enumerator (folder.files);

Add all journal files in the file enumeration to the archive:

for (; !journals.atEnd(); journals.moveNext()) {

  if (fso.GetExtensionName(journals.item()) != "jrn") {
    /* ignore all non-journal files */
    continue;
    }

  oArchive.addJournal(journals.item(), null, null);
  }

Now, a search operation can be performed as if it was a single journal:

var docSeq = oArchive.searchDocs("CustomerNumber", "4711", 1);
if (docSeq.isEmpty) {
  WScript.Echo("No hit.");
  WScript.Quit(1);
  }

for (;;) {

  var doc = oArchive.retrieveDoc(docSeq.docNo);
  WScript.Echo(doc.docID);
  if (docSeq.atEnd) {
    break;
    }
  docSeq.moveNext();
  }


RSJ XML Archive

Copyright © 2002-2003 by

RSJ Software GmbH, Germering.

All rights reserved.

Authors: Markus Müller, Rüdiger Jungbeck

The information in this manual is subject to change without further notice. Although we put great accuracy into the development and documentation of our products, occasional errors cannot be avoided. RSJ Software will in no case be liable for errors or any consequential damages, such as loss of data or production deficits.

Microsoft, Windows NT, Windows 2000, Windows XP are trademarks of Microsoft Corporation


DocumentSequence.curJournal Property

curJournal Property

Description

Read only; returns the current journal (that is, the journal containing the current match document) in an archive-wide (across journals) search.

Applies to the DocumentSequence object.

Syntax

curJournal

Remarks

None


Journal.newUser Method

newUser() Method

Description

Returns the journal's encrypted session key. The key is encrypted with the new user's public key that is passed to this method.

Applies to the Journal object.

Syntax

var encSessionKeyDoc = newUser(
  publicUserKeyDoc       /* DOMDocument containing the public key of the new user */
  )

Parameters

This method has the following parameters:

publicUserKeyDoc DOM document containing the public key of the new user

Return values

These values can be extracted from the IErrorInfo interface in the exception handler.
S_OK | success
E_INVALIDARG | the key document object passed in is not properly initialized
E_FAIL | unspecified, unrecoverable error

Returns

A DOM document containing the encrypted session key of the journal.

Remarks

If a new user shall be granted access to a journal, the following steps must be taken:

  1. Create a key pair for the new user using the KeyFactory object
  2. Call the journal's newUser() method, passing the public key of the new user
  3. The new user then has to pass the session key returned by the newUser() method and its private key to methods like JournalFactory.open()

Example Code (JavaScript)

/* create the journal factory */
var jrnFactory = new ActiveXObject("xmljrnapi.JournalFactory");
jrnFactory.fileName = "c:\\xmlarchive\\samples\\load.jrn";

/* load my private key to open the journal */
var myPrivateKey = new ActiveXObject("Msxml.DOMDocument.4.0");
myPrivateKey.load("c:\\Eigene Dateien\\Geheim\\private.xml");

/* open an existing journal */
var jrn = jrnFactory.open(myPrivateKey, null);

/* create a key pair for the new user */
var keyFactory = new ActiveXObject("xmljrnapi.KeyFactory");
keyFactory.create();
var privateKey = keyFactory.privateKey;
var publicKey = keyFactory.publicKey;

/* save XML keys to persistant storage */
privateKey.save("o:\\users\\keys\\234934\\private.xml");
publicKey.save("o:\\users\\keys\\234934\\public.xml");

/* retrieve session key and store it */
var sessionKey = jrn.newUser(publicKey);
sessionKey.save("o:\\users\\keys\\234934\\session.xml");

jrn.close();

Now, the user can gain access to the journal by loading his private key and the session key retrieved in the above example into DOMDocument objects and passing them to the JournalFactory.open() method:

/* load private key and encryted session key */
var privateKey = new ActiveXObject("Msxml.DOMDocument.4.0");
privateKey.load("o:\\users\\keys\\234934\\private.xml");

var sessionKey = new ActiveXObject("Msxml.DOMDocument.4.0");
sessionKey.load("o:\\users\\keys\\234934\\session.xml");

/* create journal factory and open the journal */
var jrnFactory = new ActiveXObject("xmljrnapi.JournalFactory");
jrnFactory.fileName = "c:\\xmlarchive\\samples\\load.jrn";
var jrn = jrnFactory.open(privateKey, sessionKey);

.
.
.