Domino Design Code Injection - Part 2
In Part 1 I introduced the approach to code injection and some sample LotusScript Code to pull a design element, transform it and push it back. Missing there was the function that actually implemented that method. I'm using a Java class to do that, which I wrap into LS2J. The LotusScript function looks like this:
This LotusScript was converted to HTML using the ls2html routine,
provided by Julian Robichaux at nsftools.com.
Now let us have a quick look at the Java class./**
* Sample Code without warranty, use at your own risk
* (C) 2008, stephan@wissel.net
* Proper error handling omitted for clarity
*/
import java.io.ByteArrayOutputStream;
import java.io.StringReader;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import javax.xml.xpath.*;
import org.w3c.dom.*;
import org.xml.sax.InputSource;
public class XPathInjector {
public static final int IMPORT_BEFORE = 0;
public static final int IMPORT_AFTER = 1;
public static final int IMPORT_REPLACE = 2;
public static final int IMPORT_FIRSTCHILD = 3;
public static final int IMPORT_LASTCHILD = 4;
Document doc;
private DocumentBuilder getDocumentBuilder() throws ParserConfigurationException {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setValidating(false);
documentBuilderFactory.setSchema(null);
documentBuilderFactory.setNamespaceAware(false);
documentBuilderFactory.setIgnoringComments(false);
documentBuilderFactory.setIgnoringElementContentWhitespace(false);
documentBuilderFactory.setXIncludeAware(false);
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
return documentBuilder;
}
private NodeList getMachingNodes(String xPathString) {
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
XPathExpression expr;
try {
expr = xpath.compile(xPathString);
Object result = expr.evaluate(doc, XPathConstants.NODESET);
return (NodeList) result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private Node getNodeFromString(String codeFragment) {
String workString = "<wrapper>" + codeFragment + "</wrapper>";
InputSource in = new InputSource(new StringReader(workString));
try {
DocumentBuilder documentBuilder = this.getDocumentBuilder();
Document miniDoc = documentBuilder.parse(in);
Node wrapper = doc.importNode(miniDoc.getDocumentElement(), true);
return wrapper;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public String injectCode(String codeFragment, String xPath, int importOption) {
Node codeToInsert = this.getNodeFromString(codeFragment);
NodeList replaceCandidates = this.getMachingNodes(xPath);
boolean appendToNode = true;
if (replaceCandidates != null) {
for (int i = 0, size = replaceCandidates.getLength(); i < size; i++) {
Node curNode = replaceCandidates.item(i);
Node referenceNode = null;
if (importOption == XPathInjector.IMPORT_BEFORE) {
appendToNode = false;
referenceNode = curNode;
} else if (importOption == XPathInjector.IMPORT_AFTER) {
if (curNode.getNextSibling() == null) {
referenceNode = curNode.getParentNode();
appendToNode = true;
} else {
referenceNode = curNode.getNextSibling();
appendToNode = false;
}
} else if (importOption == XPathInjector.IMPORT_FIRSTCHILD) {
if (curNode.getFirstChild() == null) {
referenceNode = curNode;
appendToNode = true;
} else {
referenceNode = curNode.getFirstChild();
appendToNode = false;
}
} else if (importOption == XPathInjector.IMPORT_LASTCHILD) {
referenceNode = curNode;
appendToNode = true;
} else if (importOption == XPathInjector.IMPORT_REPLACE) {
if (curNode.getNextSibling() == null) {
referenceNode = curNode.getParentNode();
appendToNode = true;
} else {
referenceNode = curNode.getNextSibling();
appendToNode = false;
}
curNode.getParentNode().removeChild(curNode);
} else {
return this.toString();
}
NodeList newNodes = codeToInsert.getChildNodes();
for (int k = 0, insertSize = newNodes.getLength(); k < insertSize; k++) {
if (appendToNode) {
referenceNode.appendChild(newNodes.item(k));
} else {
referenceNode.getParentNode().insertBefore(newNodes.item(i), referenceNode);
}
}
}
}
return this.toString();
}
public void setDocument(String docString) {
InputSource in = new InputSource(new StringReader(docString));
try {
DocumentBuilder documentBuilder = this.getDocumentBuilder();
this.doc = documentBuilder.parse(in);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public String toString() {
try {
StreamResult result = null;
ByteArrayOutputStream byteResult = new ByteArrayOutputStream();
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
DOMSource source = new DOMSource(doc);
result = new StreamResult(byteResult);
transformer.transform(source, result);
return byteResult.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
Option Public Option Declare Uselsx "*javacon" Use "CodeInjector" Function injectCode (rawDXL As String , xPath As String , codeSnippet As String ) As String 'Dummy doesn't do anything Dim jSession As JAVASESSION Dim injectorClass As JAVACLASS Dim injector As JavaObject Set jSession = New JAVASESSION injectCode = rawDXL Set injectorClass = jSession .GetClass ( "DominoXPathInjector" ) Set injector = injectorClass . CreateObject 'Now set the document Call injector .setDocument (rawDXL ) 'and execute the function injectCode = injector .injectCode (codeSnippet , xPath , 4 ) End Function
provided by Julian Robichaux at nsftools.com.
* Sample Code without warranty, use at your own risk
* (C) 2008, stephan@wissel.net
* Proper error handling omitted for clarity
*/
import java.io.ByteArrayOutputStream;
import java.io.StringReader;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import javax.xml.xpath.*;
import org.w3c.dom.*;
import org.xml.sax.InputSource;
public class XPathInjector {
public static final int IMPORT_BEFORE = 0;
public static final int IMPORT_AFTER = 1;
public static final int IMPORT_REPLACE = 2;
public static final int IMPORT_FIRSTCHILD = 3;
public static final int IMPORT_LASTCHILD = 4;
Document doc;
private DocumentBuilder getDocumentBuilder() throws ParserConfigurationException {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setValidating(false);
documentBuilderFactory.setSchema(null);
documentBuilderFactory.setNamespaceAware(false);
documentBuilderFactory.setIgnoringComments(false);
documentBuilderFactory.setIgnoringElementContentWhitespace(false);
documentBuilderFactory.setXIncludeAware(false);
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
return documentBuilder;
}
private NodeList getMachingNodes(String xPathString) {
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
XPathExpression expr;
try {
expr = xpath.compile(xPathString);
Object result = expr.evaluate(doc, XPathConstants.NODESET);
return (NodeList) result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private Node getNodeFromString(String codeFragment) {
String workString = "<wrapper>" + codeFragment + "</wrapper>";
InputSource in = new InputSource(new StringReader(workString));
try {
DocumentBuilder documentBuilder = this.getDocumentBuilder();
Document miniDoc = documentBuilder.parse(in);
Node wrapper = doc.importNode(miniDoc.getDocumentElement(), true);
return wrapper;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public String injectCode(String codeFragment, String xPath, int importOption) {
Node codeToInsert = this.getNodeFromString(codeFragment);
NodeList replaceCandidates = this.getMachingNodes(xPath);
boolean appendToNode = true;
if (replaceCandidates != null) {
for (int i = 0, size = replaceCandidates.getLength(); i < size; i++) {
Node curNode = replaceCandidates.item(i);
Node referenceNode = null;
if (importOption == XPathInjector.IMPORT_BEFORE) {
appendToNode = false;
referenceNode = curNode;
} else if (importOption == XPathInjector.IMPORT_AFTER) {
if (curNode.getNextSibling() == null) {
referenceNode = curNode.getParentNode();
appendToNode = true;
} else {
referenceNode = curNode.getNextSibling();
appendToNode = false;
}
} else if (importOption == XPathInjector.IMPORT_FIRSTCHILD) {
if (curNode.getFirstChild() == null) {
referenceNode = curNode;
appendToNode = true;
} else {
referenceNode = curNode.getFirstChild();
appendToNode = false;
}
} else if (importOption == XPathInjector.IMPORT_LASTCHILD) {
referenceNode = curNode;
appendToNode = true;
} else if (importOption == XPathInjector.IMPORT_REPLACE) {
if (curNode.getNextSibling() == null) {
referenceNode = curNode.getParentNode();
appendToNode = true;
} else {
referenceNode = curNode.getNextSibling();
appendToNode = false;
}
curNode.getParentNode().removeChild(curNode);
} else {
return this.toString();
}
NodeList newNodes = codeToInsert.getChildNodes();
for (int k = 0, insertSize = newNodes.getLength(); k < insertSize; k++) {
if (appendToNode) {
referenceNode.appendChild(newNodes.item(k));
} else {
referenceNode.getParentNode().insertBefore(newNodes.item(i), referenceNode);
}
}
}
}
return this.toString();
}
public void setDocument(String docString) {
InputSource in = new InputSource(new StringReader(docString));
try {
DocumentBuilder documentBuilder = this.getDocumentBuilder();
this.doc = documentBuilder.parse(in);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public String toString() {
try {
StreamResult result = null;
ByteArrayOutputStream byteResult = new ByteArrayOutputStream();
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
DOMSource source = new DOMSource(doc);
result = new StreamResult(byteResult);
transformer.transform(source, result);
return byteResult.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
Posted by Stephan H Wissel on 21 March 2008 | Comments (0) | categories: Show-N-Tell Thursday