A driver is the piece of code that allows DirXML to communicate with an external application in order to synchronize
data between that application and NDS.
DirXML can be thought of as two separate black boxes called channels. Each channel takes an event on its input
and issues a set of commands on its output. The goal of the transformation from events to commands is to propagate
the changes made by the application connected to the channel input into the application connected to the channel
output. The transformation involves fixed logic in DirXML together with a set of configurable rules that guide
the transformation of events to commands.
The first channel is the Subscriber channel. NDS acts as the Subscriber channel input and a driver's
SubscriptionShim
acts as the Subscriber channel output. The Subscriber channel therefore accepts NDS events, generates commands with
the help of the rules, and issues those commands to the
SubscriptionShim
which then updates the application.
The second channel is the Publisher channel. The driver's
PublicationShim
acts as the Publisher channel input and NDS acts as the Publisher channel output. The Publisher channel therefore
accepts events for the application through the
PublicationShim,
generates commands with the help of the rules, and issues those commands to update NDS.
No. It is useful for the driver writer to understand what rules do, but the driver has no responsibility for
rules processing. The driver writer should have a good understanding of the responsibilities of the driver before
worrying about the rules.
Associations are the mechanism used by DirXML to establish and maintain a correspondence between an object in
NDS and an application object. The driver provides a unique key value for each application object, and DirXML manages
the storage of those key values in NDS.
A driver's responsibility with respect to associations is to provide a unique key value for each object and
to notify DirXML whenever something happens that affects that unique key. In practice this means:
Provide the unique key value for the object whenever communicating any information about the object to DirXML
(events and queries).
Report to DirXML whenever the unique key value of a relevant object changes using <modify-association>.
Report to DirXML the unique key value of an object created as a result of processing <add>
in the SubscriptionShim using <add>
in the result document returned from the add processing.
Optionally tell DirXML to forget any key that is no longer valid and for which driver has reason to believe
that DirXML is still holding using <remove-association>. The
most common occurrence of this is when DirXML sends a command using a key value that no longer exists in the application.
DirXML communicates with a driver through interfaces. In Java these are represented by Java interfaces. In C++
these are represented as pure abstract base classes. In the interest of brevity this document will focus primarily
on the Java interfaces. A FAQ on C++ drivers is available and covers
items specifically of interest to writers of C++ drivers.
DriverShim - The top-level interface responsible
for starting up and shutting down the driver.
SubscriptionShim - The interface
responsible for accepting and processing commands from DirXML.
PublicationShim - The interface responsible
for notifying DirXML of events that occur in the application.
XmlQueryProcessor - The interface
passed by the PublicationShim into XmlCommandProcessor.execute()
when calling DirXML to report an application event. DirXML uses the XmlQueryProcessor interface to query the PublicationShim
for any additional information DirXML may need to process the application event.
DriverShim is instantiated
by DirXML via introspection using a no-argument constructor.
DriverShim.init() method is called
by DirXML. DirXML passes in the driver initialization parameters.
DirXML retrieves the object implementing the SubscriptionShim
interface using DriverShim.getSubscriptionShim().
DirXML retrieves the object implementing the PublicationShim
interface using DriverShim.getPublicationShim().
DirXML calls SubscriptionShim.init(),
passing the Subscriber initialization parameters.
A separate Publisher thread is created. In the Publisher thread:
DirXML calls PublicationShim.init(),
passing the Publisher initialization parameters.
DirXML calls PublicationShim.start(),
passing the DirXML object that implements
XmlCommandProcessor.
The PublicationShim.start() method loops,
notifying DirXML using XmlCommandProcessor.execute()
whenever a relevant event occurs in the application. It does not return
until DriverShim.shutdown()
is called unless there is a fatal error.
XmlCommandProcessor.execute()
processes the event, possibly calling the driver XmlQueryProcessor
(passed into XmlCommandProcessor.execute())
one or more times if additional information is needed by DirXML to process the event.
DirXML monitors NDS for relevant events and invokes SubscriptionShim.execute()
when an application object must be created or a change must be made to an application object. In addition, DirXML
invokes SubscriptionShim.execute() to query the application for information about application objects.
SubscriptionShim.execute() processes
the command, optionally calling the DirXML XmlQueryProcessor
(passed into SubscriptionShim.execute())
one or more times if additional information is needed to process the command.
At some time in the future NDS sends DirXML an event telling DirXML to shut down the
driver. DriverShim.shutdown()
is called, which performs whatever driver-specific cleanup is needed (including
signaling the PublicationShim
to return from start().)
XmlDocument is a high level
abstraction representing an XML document. It allows for easy conversions between several common representations
of XML, notably Document Object Model (DOM), Simple API for
XML 1.0 (SAX), and a serialized, human-readable form.
This allows drivers to create and consume XML documents in the form that is most convenient for the particular
application. DirXML predominantly uses DOM internally, but uses the serialized form when logging messages to DSTRACE.
Most drivers will probably also use DOM internally, but drivers which must pass the XML to external or remote processes
will likely use the serialized form as well.
The implementation of DOM used by DirXML is provided by nxsl.jar (which contains Novell's XSLT processor as
well as many XML utility classes). To create a document that uses the same implementation as DirXML,
use com.novell.xml.dom.DocumentFactory.newDocument().
It is possible for a driver to use a different implementation of DOM. However, keep in mind that documents that
are passed to the driver by DirXML will always use the nxsl.jar implementation, so any extensions to DOM that might
be available in another implementation will not be available in documents received from DirXML. Note also that
the performance of the Novell XSLT processor is significantly better on documents created using the nxsl.jar implementation.
The documents passed to and from the various methods have a structure defined by
nds.dtd.
All documents use <nds> as the document (top-level) element, which may contain
an optional <source> element. Documents that are passed as parameters to
interface methods also contain a single <input> element that contains an
arbitrary number of events or commands as applicable. Documents that are returned from interface methods contain
a single <output> element which contains the results of the processing the
events or commands contained in the input document and may contain a limited set of commands.
<nds dtdversion="1.0" ndsversion="8.5">
<source>
<product asn1id="2 16 840 1 113719 1 x" version="1.0b3">DirXML</product>
<contact>Novell, Inc.</contact>
</source>
<input>
<!-- input commands or events go here -->
</input>
</nds>
Shim returns:
<nds dtdversion="1.0" ndsversion="8.5">
<source>
<product version="1.0b3">Some Application Driver</product>
<contact>Nobody in particular</contact>
</source>
<output>
<!-- results from commands or events go here -->
</output>
</nds>
The distinction is subtle but important. Many of the possible child elements of <input>
can be interpreted either as commands or as events, depending on the context, and have essentially the same syntax.
In general, for elements that can be used as either a command or as notification of an event the following applies:
If the element is being sent to the driver the element is a command and if the element is being sent to DirXML
the element is an event notification. When the driver sends an event notification to DirXML the driver is informing
DirXML of something that occurred in the application. DirXML will then determine, based on configurable rules,
what commands, if any, must be sent to NDS. When DirXML sends a command to the driver, DirXML has already taken
an NDS event as input, applied the appropriate rules, and determined that the change in the application represented
by the command is necessary.
Rules help DirXML transform an event on a channel input into a set of commands on the channel output. Rules
are configurable by the System Administrator so that the rules can be customized to do whatever an individual installation
requires. Some rules perform a well-defined role in the event-to-command transformation while others allow for
more general customization. All rules can be implemented using XSLT stylesheets, but rules that perform well-defined
roles more commonly use a DirXML-specific XML format (a "simple" rule) that more easily describes the transformation needed. Rules
that use DirXML-specific XML formats can usually be created and edited using ConsoleOne snapins that guide the
administrator in creating the rules so that the administrator does not have to see the raw XML that encodes the
rule. However, when an XSLT stylesheet is used as a rule (either for those rules that can only be implemented using
XSLT or as a replacement for one of the more common rules) the XSLT must be programmed manually.
Rules are stored in the XmlData attribute of DirXML-Rule and DirXML-Stylesheet objects. The DirXML-Driver, DirXML-Subscriber,
and DirXML-Publisher objects have attributes that reference the rule objects:
Rule chaining is a feature added in DirXML 1.1 that allows multiple rule objects to be chained together to form the total
rule processing for a rule step (e.g., Create Rule, Placement Rule, etc.). This allows a stylesheet to supplement the
operation of a simple rule without having to completely replace the rule with a stylesheet.
Rules are chained together using the DirXML-NextTransformation attribute on the rule object. Any number of rules may be chained;
multiple simple rules and stylesheets may be freely mixed. There may not be any loops in the chain, and any simple rules used must
match the rule step. In other words, if rules are being chained in the Create Rule step, any simple rules must use the simple
Create Rule syntax.
The Schema Mapping Rule is referenced by the driver object and applies to both the Subscriber channel and to
the Publisher channel. The purpose of the Schema Mapping Rule is to map schema names (particularly attribute names
and class names) between the NDS namespace and the application namespace. The rule syntax is defined by the documentation
for <attribute-name-map>. The Schema Mapping Rule is applied to the
XML documents sent to and returned from SubscriptionShim.execute(),
XmlQueryProcessor.query(), and
XmlCommandProcessor().execute(). The
Schema Mapping Rule is also applied to XML sent to (but not to XML returned from)
SubscriptionShim.init()
and PublicationShim().init(). The Schema
Mapping Rule is applied before the Output Transformation Rule when DirXML issues a document to the driver and before
the Input Transformation Rule when the driver issues a document to DirXML.
The Input Transformation Rule is referenced by the driver object and applies to both the Subscriber channel
and to the Publisher channel. The purpose of the Input Transformation Rule is to perform any preliminary transformation
on all XML documents sent to DirXML by the driver and returned to DirXML from the driver. The Input Transformation
Rule is applied to the XML document sent to XmlCommandProcessor.execute()
and XmlQueryProcessor.query() (when
called by the driver) and to the XML document returned from SubscriptionShim.execute(),
and XmlQueryProcessor.query() (when
called by DirXML). The Input Transformation Rule is applied before the Schema Mapping Rule.
The Input Transformation Rule is always implemented using an XSLT stylesheet. A common application is performing
data format mapping. Note that schema names will always be in the application namespace in the XML processed by
the Input Transformation Rule.
It is possible to use the Input Transformation Rule to transform an arbitrary XML format native to the target
application to the format expected by DirXML, but this is discouraged because it makes it harder for administrators
to customize the rule for site-specific needs. It is usually wiser if the driver performs this transformation itself,
possibly by calling the Novell XSLT processor directly.
The Output Transformation Rule is referenced by the driver object and applies to both the Subscriber channel
and to the Publisher channel. The purpose of the Output Transformation Rule is to perform any final transformation
necessary on the XML documents sent to the driver by DirXML and returned to the driver by DirXML. The Output Transformation
Rule is applied to the XML document sent to SubscriptionShim.execute()
and XmlQueryProcessor.query() (when
called by DirXML) and to XML returned from XmlCommandProcessor.execute()
and XmlQueryProcessor.query() (when
called by the driver). The Output Transformation Rule is applied after the Schema Mapping Rule.
The output transform is always implemented using an XSLT stylesheet. A common application is performing data
format mapping. Note that schema names will always be in the application namespace in the XML processed by the
Output Transformation Rule.
It is possible to use the Output Transformation Rule to transform between DirXML format and an arbitrary XML
format native to the target application, but this is discouraged because it makes it harder for administrators
to customize the rule for site-specific needs. It is usually wiser if driver performs this transformation itself,
possibly by calling the Novell XSLT processor directly.
An Event Transformation Rule may be referenced by the Subscriber object and/or by the Publisher object (typically
the Subscriber and Publisher would reference different rule objects). The purpose of an Event Transformation Rule
is to perform preliminary transformations on events. When referenced by the Subscriber object the Event Transformation
Rule applies to events received by DirXML from NDS and is applied before any other event processing. When referenced
by the Publisher object the Event Transformation Rule applies to events issued by the driver to DirXML and is applied
after the Input Transformation Rule and Schema Mapping Rules, but before any other event processing.
The Event Transformation Rule is always implemented using an XSLT stylesheet. There are many common applications
for the Event Transformation Rule, including:
custom event filtering
transforming the event directly into a custom command to be passed to the application
A Command Transformation Rule may be referenced by the Subscriber object and/or by the Publisher object (typically
the Subscriber and Publisher would reference different rule objects). The purpose of the Command Transformation Rule
is to provide final processing on commands before the commands are sent to eDirectory or the application. Note that
the Command Transformation Rule did not exist in DirXML 1.0; the Command Transformation Rule was added in DirXML 1.1.
The Command Transformation Rule on the Publisher channel is executed after all other rules and is executed directly
before the DirXML engine applies the commands in the command document to eDirectory. It is the "last chance" to modify
a command before the command is applied to eDirectory.
The Command Transformation Rule on the Subscriber channel is executed directly before the Schema Mapping Rule. Both
the Schema Mapping Rule and the Output Transformation are executed after the Command Transformation Rule on the
Subscriber channel.
The Command Transformation Rule is always implemented using an XSLT stylesheet. Many applications that had to be performed
in the Event Transformation Rule in DirXML 1.0 can be more easily performed in the Command Transformation Rule in DirXML 1.1.
This is because all event to command processing performed by the DirMXL Engine has already been performed.
Some other possible applications for the Command Transformation Rule include:
changing the command type (for example, an object delete command might be transformed into a modification that
will cause the object to be archived)
generating additional events
blocking commands
adding additional commands
controlling the output of the DirXML Engine's "merge" process
A Matching Rule may be referenced by the Subscriber object and/or by the Publisher object (typically the Subscriber
and Publisher would reference different rule objects). The purpose of the Matching Rule is to automatically associate
objects in NDS with objects in the application. The rule syntax is defined by the documentation for <matching-rules>.
The matching rule is only applied to <add> events.
A Create Rule may be referenced by the Subscriber object and/or by the Publisher object (typically the Subscriber
and Publisher would reference different rule objects). The purpose of the Create Rule is to decide whether or not
to create a new object if a suitable association could not be automatically generated by the Matching Rule. A Create
Rule also can perform other modifications to the <add> event such as providing
default values for attributes and/or specifying an object to use as a template for creating the new object. The
rule syntax is defined by the documentation for <create-rules>. The
Create Rule is only applied to <add> events for which no matches for the corresponding
object were found by the Matching Rule.
A Placement Rule may be referenced by the Subscriber object and/or by the Publisher object (typically the Subscriber
and Publisher would reference different rule objects). The purpose of the Placement Rule is to determine where
in the storage hierarchy to place an object that is to be created and to determine the name for the new object.
For NDS and other directory applications this means generating a distinguished name for the new object. The rule
syntax is defined by the documentation for <placement-rules>. The
Placement Rule is only applied to <add> events which were not vetoed by the
Create Rule.
An Event Filter specifies the classes of objects and the attributes of those objects for which DirXML will process
events. Separate Event Filters are specified for the Subscriber and Publisher channels. Event Filters only pass
events on objects whose effective class matches one of those classes specified by the filter. Event Filters do
not pass events on objects that are a subclass of a class specified in the filter unless the subclass is also specified.
The following is the general order of rule processing. Note that this is an extreme over-simplification of the
processing that actually occurs and that processing may stop at any point or skip to the last step if the result
of processing a rule dictates it.
Rules and Event Filters must be explicitly constructed to complement each other. What this means really depends
on the particular requirements of the installation and on the requirements of the application, but here are a few
general things to keep in mind:
If a rule operates on attribute values or uses attribute values to make a decision, those attributes need to
be in the corresponding Event Filter.
Usually a Create Rule should require all the attributes used by the Matching Rule. This forces creation of
a new object to be deferred until enough is known about the object to perform a reasonable attempt at finding a
matching object in the target space.
A good working understanding of XSLT is a good place to start. Obtain the XSLT
and XPath specifications. Make sure any tutorial or
book reference on the subject is based on the final 16 November 1999 W3C Recommendation.
A recommended reference for XSLT programming is XSLT Programmer's Reference, by Michael Key, published
by Wrox Press. ISBN 1-861003-12-9.
You also need a good working understanding of the XML specified by nds.dtd..
Each kind of rule accomplishes specific kinds of tasks as outlined in a general fashion above. Additional things
you might need to know for each rule type are:
Input Transformation Rule
Performs any pre-processing of XML issued to DirXML from the driver.
Good place to perform data format mapping.
Names are in the application namespace.
Can change event types, generate extra events, and remove events.
Output Transformation Rule
Does any post-processing of XML issued from DirXML to the driver before the XML is sent to the driver.
Good place to perform data format mapping.
Names are in the application namespace.
Can change event types, generate extra events, and remove events.
Event Transformation Rule
Names are in the NDS namespace.
Can change event types, generate extra events, and remove events.
Command Transformation Rule
Performs processing of XML issued from DirXML to the driver (Subscriber channel) or
to eDirectory (Publisher channel) before the XML is sent to the driver or eDirectory.
Names are in the NDS namespace.
Can change command types, generate extra commands, and remove commands.
On the Subscriber channel must add an <association> to the <add>
for any matches that are found in the application.
On the Publisher channel must fill the dest-dn attribute of the <add> if
a match is found in NDS. The special value of a single unicode character � signals that multiple matches
were found.
Cannot change event types or generate extra events.
Fills in the dest-dn attribute of the <add>. For the Subscriber channel
this must be in the application namespace. For the Publisher channel this must be in the NDS namespace.
Unless you are translating to/from an XML format that is completely different from the DirXML format in the
Input and Output Transformation Rules, you will want to start your stylesheet with templates that implement the
identity transformation. This is so that anything in the document that you don't specifically try to intercept
and change will be passed through as is.
The following two templates together implement the identity transform:
Except for the Input and Output Transformation Rules, rules implemented as stylesheets are passed several parameters
from DirXML that the stylesheet can use:
fromNDS - boolean value that is true if the rule is being processed by the Subscriber channel and false if
the rule is being processed by the Publisher channel.
srcQueryProcessor - a Java object of class com.novell.nds.dirxml.driver.XdsQueryProcessor.
This allows the stylesheet to query the event source for more information.
destQueryProcessor - a Java object class com.novell.nds.dirxml.driver.XdsQueryProcessor.
This allows the stylesheet to query the event target for more information.
srcCommandProcessor - a Java object class com.novell.nds.dirxml.driver.XdsCommandProcessor.
This allows the stylesheet to "write-back" a command to the event source. Not available in DirXML 1.0.
destCommandProcessor - a Java object class com.novell.nds.dirxml.driver.XdsCommandProcessor.
This allows the stylesheet to issue a command to the command destination directly, bypassing most other rules. Not available in DirXML 1.0.
dnConverter - a Java object implementing interface com.novell.nds.dirxml.driver.DNConverter.
This allows the stylesheet to convert eDirectory DNs from one DN format to another. Not available in DirXML 1.0 or DirXML 1.1.
To use these parameters include the following at the top level of your stylesheet:
Use of the query processors depends on the Novell XSLT implementation of extension functions. In order to make
a query you need to declare a namespace for the Java interfaces used. For example, to use the XdsQueryProcessor interface add xmlns:query="http://www.novell.com/nxsl/java/com.novell.nds.dirxml.driver.XdsQueryProcessor"
to the <xsl:stylesheet> or <xsl:transform> element of the stylesheet.
An example of using one of the query processors:
<!-- query object name queries NDS for the passed object-name. Ideally, this would -->
<!-- not depend on "CN": to do this, add another parameter that is the name of the -->
<!-- naming attribute. -->
<xsl:template name="query-object-name">
<xsl:param name="object-name"/>
<!-- build an xds query as a result tree fragment -->
<xsl:variable name="query">
<!-- note: in DirXML 1.0 an <nds> and an <input> element are needed -->
<query>
<search-class class-name="{ancestor-or-self::add/@class-name}"/>
<!-- NOTE: depends on CN being the naming attribute -->
<search-attr attr-name="CN">
<value><xsl:value-of select="$object-name"/></value>
</search-attr>
<!-- put an empty read attribute in so that we don't get the whole object back -->
<read-attr/>
</query>
</xsl:variable>
<!-- query NDS -->
<xsl:variable name="result" select="query:query($destQueryProcessor,$query)"/>
<!-- return an empty or non-empty result tree fragment depending on result of query -->
<xsl:value-of select="$result//instance"/>
</xsl:template>
Use of the command processors depends on the Novell XSLT implementation of extension functions. In order to issue
a command you need to declare a namespace for the XdsCommandProcessor interface: this is done by adding xmlns:command="http://www.novell.com/nxsl/java/com.novell.nds.dirxml.driver.XdsCommandProcessor"
to the <xsl:stylesheet> or <xsl:transform> element of the stylesheet.
An example of using one of the command processors:
<!-- update full name sets the "Full Name" attribute in the event source -->
<!-- it expects the context node to be the <modify> element in the document -->
<xsl:template name="update-full-name">
<!-- build an xds command as a result tree fragment -->
<xsl:variable name="command">
<modify>
<!-- get the association from the modify coming through -->
<xsl:copy-of select="association"/>
<!-- put in the <modify-attr> for the Full Name attribute -->
<modify-attr attr-name="Full Name">
<remove-all-values/>
<add-value>
<value>
<xsl:value-of select="modify-attr[@attr-name='Given Name']/add-value/value"/>
<xsl:text> </xsl:text>
<xsl:value-of select="modify-attr[@attr-name='Surname']/add-value/value"/>
</value>
</add-value>
</modify-attr>
</modify>
</xsl:variable>
<!-- send command to source -->
<xsl:variable name="result" select="command:execute($srcCommandProcessor,$command)"/>
</xsl:template>
XSLT is an excellent tool for performing some kinds of transformations and a rather poor tool for other types
of transformations (non-trivial string manipulation, iterative processes, etc.). Fortunately the Novell XSLT processor
implements extension functions which allow the stylesheet to call a function implemented in Java (and by extension
any other language that can be accessed through JNI).
Additional documentation on using extension functions with Novell's XSLT implementation can be found elsewhere.
For specific examples see the above example using the query processor, and the following example that illustrates
using Java for string manipulation:
<!-- get-dn-prefix places the part of the passed dn that precedes the -->
<!-- last occurrence of '\' in the passed dn in a result tree fragment -->
<!-- meaning that it can be used to assign a variable value -->
<xsl:template name="get-dn-prefix" xmlns:jstring="http://www.novell.com/nxsl/java/java.lang.String">
<xsl:param name="src-dn"/>
<!-- use java string stuff to make this much easier -->
<xsl:variable name="dn" select="jstring:new($src-dn)"/>
<xsl:variable name="index" select="jstring:lastIndexOf($dn,'\')"/>
<xsl:if test="$index != -1">
<xsl:value-of select="jstring:substring($dn,0,$index)"/>
</xsl:if>
</xsl:template>
Drivers can invoke the Novell XSLT processor directly by using the com.novell.xsl.StyleSheet
class. There are various ways in which this can be set up and invoked so it pays to read the documentation, but
a typical invocation is illustrated by the following code fragment.
import com.novell.nds.dirxml.driver.*;
import com.novell.xsl.*;
import com.novell.xsl.result.*;
import org.w3c.dom.*;
.
.
.
try
{
XmlDocument inputDoc = new XmlDocument();
XmlDocument stylesheetDoc = new XmlDocument();
// load the input and stylesheet documents from a file
inputDoc.readDocument(new FileInputStream("input.xml"));
stylesheetDoc.readDocument(new FileInputStream("stylesheet.xsl"));
// create the stylesheet processor and give it the stylesheet
Stylesheet styleSheet = new Stylesheet();
styleSheet.load(stylesheetDoc.getDocument());
// pass in any stylesheet parameters that the stylesheet might need
styleSheet.setParameter("fromNds", new Boolean(fromNDS));
// setup a result handler to get a DOM tree
Document resultDoc = com.novell.xml.dom.DocumentFactory.newDocument();
DOMResultHandler resultHandler = new DOMResultHandler(resultDoc);
styleSheet.setResultHandler(resultHandler);
// apply the stylesheet
styleSheet.process(doc, null);
// result will be in resultDoc
}
catch( XSLException xsle )
{
// handle any exception thrown
}
com.novell.xml.dom.DOMUtil - Utility class implementing,
among others, things that XSLT and DirXML need for DOM that aren't defined by the 1.0 DOM spec (namespaces, serialization,
whitespace stripping, id resolution, etc.).
com.novell.xml.dom.DOMWriter - A class for serializing
DOM trees, used by XmlDocument and DOMUtil. Using this class directly allows for finer control of the serialization
process.
com.novell.xsl.util.Util - Has a method called getXSLStringValue()
which evaluates the string value of a Node according to the XPath definition. Useful for the text content of an
Element.
com.novell.xml.util.Base64Codec - implements
encoding and decoding of binary data using Base64 encoding. Base64 encoding is used by DirXML to encode binary
data in command and event notification documents.
The short answer is: no.
The long answer is: If your driver makes assumptions about where it is running it may need to be modified. If, for
example, your driver uses a "side-band" connection to eDirectory via LDAP and assumes it can do so on "localhost" then your driver
won't work correctly with the Remote Loader. In general, if your driver strictly adheres to the DirXML interfaces and doesn't assume
that it is running on the same machine as eDirectory then your driver will function properly with the DirXML Remote Loader.
Messages originating from DirXML show up in DSTRACE if you enable the DirXML Drivers events (DVRS on NetWARE).
By default very little information is given, mostly just the status of events. To enable more verbose output, add
the DirXML-DriverTraceLevel attribute to the DirXML-DriverSet object using Other tab on the ConsoleOne
Properties dialog. Useful values for this attribute are:
1 - Informational messages about what DirXML is doing;
2 - adds dumps of the XML passed to/from the driver;
3 - adds XML dumps after a stylesheet is applied and more verbose output during rule evaluation.
Drivers may also send messages to DSTRACE by creating and using an instance of com.novell.nds.dirxml.driver.Trace.
It is recommended that drivers not write directly to System.out or System.err (even though this will currently
send the output to DSTRACE) because this may not be supported in future releases.
Trace messages may also be directed to a file (in addition to DSTRACE) by setting the value of the DirXML-JavaTraceFile
attribute on the DirXML-DriverSet object to a valid filename. Use the Other tab on the ConsoleOne
Properties dialog for the DirXML-DriverSet object.
Make a backup copy of the DirXML jre directory (typically C:\Novell\Nds\jre).
Delete the DirXML jre directory.
Copy the jre directory from the JDK into the DirXML jre directory.
Copy the contents of the jdk lib directory (jdk/lib) into the DirXML jre/lib directory (tools.jar, etc.).
Add the DirXML-JavaDebugPort attribute to the DirXML-DriverSet object (use the Other tab in the ConsoleOne
Properties dialog for the DirXML-DriverSet object).
Set the DirXML-JavaDebugPort value to a TCP port value not in use on your machine (8080 usually works).
Restart NDS.
Before the first driver in the driver set starts a dialog box will pop up informing you of the debugger password.
At this point you can attach a debugger to the JVM and press OK. You can also press OK without attaching a debugger.
Copy the jdwp.dll, dt_shmem.dll, and dt_socket.dll from the bin directory in the JDK into the NDS directory.
Set the appropriate debug options in the DHOST_JVM_OPTIONS environment variable
(See http://java.sun.com/products/jpda for details).
Sample: set DHOST_JVM_OPTIONS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,address=8080,suspend=n Note that if running as a server, you must set this in the System control panel under System variables.
Restart NDS.
Before the first driver in the driver set starts a dialog box will pop up informing you that you that Java
2 debugging is enabled . At this point you can attach a debugger to the JVM and press OK. You can also press OK
without attaching a debugger.
The Visual Cafe debugger is an agent-type debugger. To setup a debugging session:
Create a project to use for debugging.
Set the main class to sun.tools.agent.EmptyApp.
Set the source directories and input class files directories appropriately for your environment.
Attach the debugger to the DirXML JVM using Projects | Debug in Waiting VM. Use localhost as the
host name and the password supplied by the dialog box mentioned above.
The jdb is an agent-type debugger. To setup a debugging session:
Enter the following command on the command line jdb -host localhost -password <password>
Set the path to your source directories using the "use" command"
You can create a file named "startup.jdb" in the working directory that can contain commands that
will be executed when jdb starts. This is a good place to put the "use" command.
CodeWarrior supports both agent and JPDA debugging API's. To setup a debugging session:
Add the registry key "HKEY_LOCAL_MACHINE\SOFTWARE\Metrowerks\CodeWarrior\4.0\Java VMs" if it doesn't
already exist.
Add to that key the String value "JDWP debug ports" for JPDA debugging or "11XWP debug ports"
for Agent debugging.
Set the value to be the port number that DirXML was set up to use. Note that contrary to the documentation,
apparently CodeWarrior does not seem to recognize ports greater than 9999 or more than 1 port for each value.
Start CodeWarrior.
Open the class or jar file that you wish to debug.
Choose SunJavaPlugin.dll when asked to choose the debugger.
Select Window | Process Window to open the Processes window.
Select the entry "JDWP debug port XXXX (inactive)" or "11XWP debug port XXXX (inactive)"
(where XXXX is the port number you are using).
Press the attach to process button.
For more information see the CodeWarrior help topic: Help | Other... | Targeting Java VM | Debugging Java Projects
| Debugging External Java Sessions (Windows Only).
Usually you can attach a debugger after you have dismissed the DirXML dialog that pauses, waiting for you to
attach to the JVM.
If you stop the debugging session in VisualCafe or jdb it shuts down the DirXML JVM running in the NDS process
and you will have to restart NDS to get it back up again.
The VisualCafe 3.0 debugger has a lot of quirks:
Occasionally it has trouble attaching to the JVM.
Sometimes it gets internal java exceptions, after which no data will display until you shutdown VisualCafe
and restart it.
Often it will still stop at breakpoints that have been removed or disabled.
The password is really just an obfuscated version of the port number. Since you are picking a static port number
you can reuse any of the passwords that are generated. If you see one that is easy to memorize, remember and use
it instead of using a new password everytime.
The following environment variables can be used on Win32:
DHOST_JVM_USE_VFPRINTF
If set to a value other than "0"; will cause installation of a vfprintf hook function that will write
to a log file named "jvm_vfprintf.log"; in the temp directory. This will also enable verbose class and
JNI messages.
DHOST_JVM_VERBOSE_GC
If set to a value other than "0"; will enable verbose garbage collector messages. This is only useful
in conjunction with JVM_USE_VFPRINTF.
DHOST_JVM_INITIAL_HEAP
Set to value in decimal number of bytes of initial JVM heap size.
DHOST_JVM_MAX_HEAP
Set to value in decimal number of bytes of maximum JVM heap size.
DHOST_JVM_OPTIONS
Set to arguments for the 1.2 JVM.
Example: -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,address=8080,suspend=n
Each option string is separated by whitespace. If an option string contains whitespace, it must be enclosed in
double quotes.
DHOST_JVM_DESTROY
If set to a value other than "0"; will cause the JVM loader thread to call DestroyJavaVM() when DirXML
is unloaded.
This is useful to cause the Java 2 hprof profiler to dump its data to a file. Note that the JVM is unusable after
this call and CANNOT be reloaded (thank Sun for that). DHOST must be shutdown and restarted to use the JVM again
(this means DirXML cannot be restarted until DHOST has restarted).
The following options can be used on NetWare:
DIRXML_JVM_INITIAL_HEAP
set to value in bytes of initial java heap size. Works with 1.1.x and 1.2.x.
Example: DIRXML_JVM_INITIAL_HEAP=4M
Example: DIRXML_JVM_INITIAL_HEAP=4096K
DIRXML_JVM_MAX_HEAP
set to value in decimal bytes of maximum java heap size. Works with 1.1.x and 1.2.x.
Example: DIRXML_JVM_MAX_HEAP=36M
Example: DIRXML_JVM_MAX_HEAP=36864K
DIRXML_JVM_VIRTUAL_HEAP
set to value in decimal bytes of virtual java heap size. Works with 1.1.x and 1.2.x.
set to arguments for the 1.2 JVM.
Example: -Xnoagent -Xdebug -Xdebugport8080 -Xmx36M
Each option string is separated by whitespace. If an option string contains whitespace, it must be enclosed in
double quotes.
DHOST_JVM_OPTIONS only works with 1.2.x.
DIRXML_JVM_C_STACK_SIZE
set to value in decimal bytes of the java C process stack size.
Example: DIRXML_JVM_C_STACK_SIZE=128K (default)
Example: DIRXML_JVM_C_STACK_SIZE=256K