I have the following code, that imports content.xml into document.xml and signs the document.xml root element.
try {
KeyingDataProvider kp = new FileSystemKeyStoreKeyingDataProvider(
"pkcs12",
"C:\\workspace\\tests\\my\\LG.pfx",
new FirstCertificateSelector(),
new DirectPasswordProvider("mykeypass"),
new DirectPasswordProvider("mykeypass"),
true);
XadesSigningProfile p = new XadesBesSigningProfile(kp);
XadesSigner signer = p.newSigner();
javax.xml.parsers.DocumentBuilderFactory factory = javax.xml.parsers.DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
javax.xml.parsers.DocumentBuilder builder = null;
builder = factory.newDocumentBuilder();
Document doc1 = builder.parse(new File("C:\\workspace\\tests\\document.xml"));
Document doc2 = builder.parse(new File("C:\\workspace\\tests\\content.xml"));
Node contentElement = doc2.getDocumentElement();
Node parentElement = doc1.getDocumentElement();
Node adoptedContentElement = doc1.adoptNode(contentElement);
parentElement.appendChild(adoptedContentElement);
Node nodeToSign = doc1.getDocumentElement().getFirstChild();
Node nodeToAttachSignature = doc1.getDocumentElement();
IndividualDataObjsTimeStampProperty dataObjsTimeStamp = new IndividualDataObjsTimeStampProperty();
AllDataObjsCommitmentTypeProperty globalCommitment = AllDataObjsCommitmentTypeProperty.proofOfApproval();
CommitmentTypeProperty commitment = CommitmentTypeProperty.proofOfCreation();
DataObjectDesc obj = new EnvelopedXmlObject(nodeToSign, "text/xml", null);
SignedDataObjects dataObjs = new SignedDataObjects(obj).withCommitmentType(globalCommitment);
signer.sign(dataObjs, nodeToAttachSignature);
Transformer transformer = TransformerFactory.newInstance().newTransformer();
Result output = new StreamResult(new File("C:\\workspace\\tests\\signedDocument.xml"));
Source input = new DOMSource(doc1);
transformer.transform(input, output);
} catch (KeyStoreException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (XadesProfileResolutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransformerConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransformerFactoryConfigurationError e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransformerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XAdES4jException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
that produces the signature like:
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="xmldsig-26102a68-cfea-43fd-a40e-9682ae7da4a1">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
The question is - how to remove namespace ds: from the signature elements?
I saw a line where the prefix "ds" is set in an example named CreateSignature, for the Apache Santuario library in Java.
ElementProxy.setDefaultPrefix(Constants.SignatureSpecNS, "ds");
In the book written by the developer of the library, he specifies how to define the signature, because XAdES4j is mostly to build the signature and not the whole document:
5.2 Signature Production: as previously discussed, a signature can be seen as having two parts: the first consists of the characteristics of
the signer and the signature operation itself; the second, the
resources being signed. If the signer is seen as a regular signature
producer, he’s likely to have a set of characteristics that are used
whenever a signature is created, i.e a signature profile. These
characteristics are fixed between signatures, while the signed
resources vary. Thus, producing a signature is to combine a profile
and a set of resources in order to create the final XML structure.
This process comes down to three major tasks: gather the needed
information (signature and data objects properties, algorithms, keying
data) in appropriate order; create the core signature structure using
the Apache XML Security API; and create the qualifying properties DOM
tree to be appended to the signature. Note that Apache XML Security
creates the DOM tree for the core signature structure. However, the
XAdES elements are unknown to the Apache API, which means that the
last task has to be completely supported by the library.
cited from: XAdES4j — a Java Library for XAdES Signature Services. By Luís Filipe dos Santos Gonçalves
By "removing namespace" I think you meaning removing the prefix. This is not somethign you can control via xades4j because the default prefixes are set by Apache Santuario and then used when creating a XMLSignature. The defaults seem to be set on the Init class; I'm not sure how/if to override the settings.
Try to put into your code:
Constants.setSignatureSpecNSprefix("");
Kindly use java version 6.32 or above to avoid appending ds: in signed XML
Related
I was trying to update the metadata of DAM Asset adding a new property-value using custom workflow. The below code works fine in the execute() method.
Resource metadata = resourceResolver.getResource(resourcePath);
ModifiableValueMap properties = metadata.adaptTo(ModifiableValueMap.class);
properties.put("360 degree", "true");
try {
metadata.getResourceResolver().commit();
} catch (PersistenceException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Updating the code as below the property-value is not being created.
Resource metadata = resourceResolver.getResource(resourcePath);
Node metanode = metadata.adaptTo(Node.class);
try {
metanode.setProperty("360 degree", "true", PropertyType.BOOLEAN);
} catch (RepositoryException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Am I missing something?
I guess you forget to call javax.jcr.Session#save.
But you should not use the JCR api when working in AEM, rely on the Sling API or even higher level apis (wcm in particular) if possible.
I have this spring boot java controller having code that utilizes the OpenKM document management API to search the document management system for documents and display results using Ajax, HTML, CSS and Jquery datatables on the front-end.
Due to the way the API was written, I cannot get a document object with its metadata in one call but will need to use an output of the first API operation's call as a filter for another API operation method in two nested for loops.
Additionally, I had to iterate the toString method of an API return object to retrieve the metadata information, as they were not accessible through the return object's properties.
The problem is the performance of this code. I would like to see if there is a way to optimize this code.
// Read the property or metadata to use in constituting the StoredDocument object
for (QueryResult queryResult : resultSet.getResults()) {
// Create a locally-scoped List<String>
List<String> listOfStoredDocumentProperties = new ArrayList<String>();
Document document = queryResult.getDocument();
String nodeId = document.getPath();
// Populate storedDocument object
storedDocument = new StoredDocument();
storedDocument.setAuthor(document.getAuthor());
storedDocument.setCreated(document.getCreated());
storedDocument.setLastModified(document.getLastModified());
storedDocument.setPath(document.getPath());
storedDocument.setPermissions(document.getPermissions());
storedDocument.setSize(document.getActualVersion().getSize());
storedDocument.setUuid(document.getUuid());
storedDocument.setVersionNumber(document.getActualVersion().getName());
// System.out.println(nodeId);
try {
listOfFormElement = okm.getPropertyGroupProperties(nodeId, documentVo.getGroupId());
int counterForTrackingDocDirectionPos = 0;
for (FormElement formElement : listOfFormElement) {
++counterForTrackingDocDirectionPos;
if (counterForTrackingDocDirectionPos == 4) {
String formElementString = formElement.toString();
// System.out.println("formElementString: " + formElementString);
System.out.println("name: " + formElement.getName());
System.out.println("formElement: " + formElement);
String transformedFormElementString = StringUtils.EMPTY;
try {
transformedFormElementString = formElementString.substring(0, formElementString.indexOf(", selected=true"));
// Read the string from a position that is 3 steps before the last position in the string.
transformedFormElementString = transformedFormElementString
.substring(transformedFormElementString.length() - 3, transformedFormElementString.length()).trim();
transformedFormElementString = transformedFormElementString.startsWith("=")
? transformedFormElementString.substring(1, transformedFormElementString.length()) : transformedFormElementString;
} catch (Exception ex) {
// To catch scenario where formElementString.indexOf(", selected=true") does not find the
// specified string. This happens when document direction is not set and therefore is
// selected=false for both the options IN and OUT.
transformedFormElementString = "NOT SET";
}
listOfStoredDocumentProperties.add(transformedFormElementString);
System.out.println("transformedFormElementString: " + transformedFormElementString);
} else {
String formElementString = formElement.toString();
String transformedFormElementString = formElementString.substring(formElementString.indexOf("value="),
formElementString.indexOf("data="));
// Remove the preceding 'value=' and the last 2 character-constituted string ", "
transformedFormElementString = transformedFormElementString.substring(6, transformedFormElementString.length() - 2).trim();
listOfStoredDocumentProperties.add(transformedFormElementString);
}
}
storedDocument.setCompanyName(listOfStoredDocumentProperties.get(0));
storedDocument.setProductLine(listOfStoredDocumentProperties.get(1));
storedDocument.setSubjectHeading(listOfStoredDocumentProperties.get(2));
storedDocument.setDocumentDirection(listOfStoredDocumentProperties.get(3));
storedDocument.setDocumentType(listOfStoredDocumentProperties.get(4));
storedDocument.setReferenceNumber(listOfStoredDocumentProperties.get(5));
storedDocument.setDate(ISO8601.parseBasic(listOfStoredDocumentProperties.get(6)).getTime().toString());
// Add the storedDocument object to the return list
listOfstoredDocuments.add(storedDocument);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchGroupException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (PathNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (RepositoryException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (DatabaseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnknowException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (WebserviceException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
The solution for it is extending the REST API. In the professional edition, the REST API is extensible with plugins architecture https://docs.openkm.com/kcenter/view/okm-6.4/creating-your-own-rest-plugin-(-extending-rest-api-).html, in the community this option still is not present. The idea is to build a method from server side what provide the exact data what really you need, creating high-level methods.
I need help understanding why the XML String does not convert into a CSV file. Why is the CSV Resut always empty?
Here is an example of a Java Code
public class transformCSV_1 {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
String xmlData = new String(
"<?xml version=\"1.0\"?><PurchaseOrder xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://localhost:8080/source/schemas/poSource/xsd/purchaseOrder.xsd\"><Reference>SBELL-2002100912333601PDT</Reference><Actions><Action><User>SVOLLMAN</User></Action></Actions><Requestor>Sarah J. Bell</Requestor><User>SBELL</User><CostCenter>S30</CostCenter><ShippingInstructions><name>Sarah J. Bell</name><address>400 Oracle Parkway Redwood Shores CA 94065 USA</address><telephone>650 506 7400</telephone></ShippingInstructions><SpecialInstructions>Air Mail</SpecialInstructions><LineItems><LineItem ItemNumber=\"1\"><Description>A Night to Remember</Description><Part Id=\"715515009058\" UnitPrice=\"39.95\" Quantity=\"2\"/></LineItem><LineItem ItemNumber=\"2\"><Description>The Unbearable Lightness Of Being</Description><Part Id=\"37429140222\" UnitPrice=\"29.95\" Quantity=\"2\"/></LineItem><LineItem ItemNumber=\"3\"><Description>Sisters</Description><Part Id=\"715515011020\" UnitPrice=\"29.95\" Quantity=\"4\"/></LineItem></LineItems></PurchaseOrder>");
String stylesheet = new String(
"<?xml version=\"1.0\" encoding=\"utf-8\"?><xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"><xsl:output method=\"text\" /><xsl:variable name=\"delimiter\" select=\"','\" /><!-- define an array containing the fields we are interested in --><xsl:variable name=\"fieldArray\"><field>Reference</field><field>User</field><field>Reject</field><field>Requestor</field></xsl:variable><xsl:param name=\"fields\" select=\"document('')/*/xsl:variable[#name='fieldArray']/*\" /><xsl:template match=\"/\"><!-- output the header row --><xsl:for-each select=\"$fields\"><xsl:if test=\"position() != 1\"><xsl:value-of select=\"$delimiter\"/></xsl:if><xsl:value-of select=\".\" /></xsl:for-each><!-- output newline --><xsl:text>
</xsl:text><xsl:apply-templates select=\"PurchaseOrder\"/></xsl:template><xsl:template match=\"PurchaseOrder\"><xsl:variable name=\"currNode\" select=\".\" /><!-- output the data row --><!-- loop over the field names and find the value of each one in the xml --><xsl:for-each select=\"$fields\"><xsl:if test=\"position() != 1\"><xsl:value-of select=\"$delimiter\"/></xsl:if><xsl:value-of select=\"$currNode/*[name() = current()]\" /></xsl:for-each><!-- output newline --><xsl:text>
</xsl:text></xsl:template></xsl:stylesheet>");
InputStream xmlSource = new ByteArrayInputStream(
xmlData.getBytes("UTF-8"));
InputStream styleSource = new ByteArrayInputStream(
stylesheet.getBytes("UTF-8"));
DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(xmlSource);
StreamSource stylesource = new StreamSource(styleSource);
Transformer transformer = TransformerFactory.newInstance()
.newTransformer(stylesource);
Source source = new DOMSource(document);
Result outputTarget = new StreamResult(new File("src/resultI.csv"));
transformer.transform(source, outputTarget);
} catch (TransformerConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransformerFactoryConfigurationError e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransformerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Best way is to use XSLT to "transform" the XML to CSV --> Can someone give me hint?
Consider to load the XSLT code from a file or URI (instead of from a string) as otherwise your approach of doing <xsl:param name="fields" select="document('')/*/xsl:variable[#name='fieldArray']/*" /> where document('') tries to pull in the XSLT code again is likely to fail, unless you set up a special resolver.
I have tried to write a code that prints the desired contents from an owl file. Here is my code:
public String execute()
{
OntModel m = ModelFactory.createOntologyModel( OntModelSpec.OWL_MEM );
// get an OntClass reference to one of the classes in the model
// note: ideally, we would delegate this step to Jena's schemagen tool
InputStream in = null;
try {
in = new FileInputStream("C:/OOAD-Softwares/workspace4/SemWeb/build/src/main/resources/semrailwaysv2.owl");
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} // or any windows path
m.read(in, null);
OntClass ontclass = m.getOntClass(SOURCE_URL+"#RailwayStation");
ExtendedIterator iterator = ontclass.listInstances();
while(iterator.hasNext())
{
Object obj = iterator.next();
System.out.println("Object : "+obj.toString());
}
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return SUCCESS;
}
Here I am able to get the number of instances of the desired class from my owl file by directly using the listInstances() method as an iterator without assigning, but I am unable to get the various property values for each instance. How should I proceed to do this? Also if I use the parameterized version of ExtendedIterator,
ExtendedIterator<OntClass> it = ontclass.listInstances();
is giving an error saying
The type ExtendedIterator is not generic; it cannot be parameterized with arguments <OntClass>
How should I proceed?
Edit
I have updated the code, still same problem.
I am tying to get the open source OWL-S API http://on.cs.unibas.ch/owls-api/ to use axis2. I have managed to get the requests sent correctly but when it comes to the response I am having trouble applying a transformation to it. In order to make my question easier to answer I am providing some standalone code which should run without having to import the project. To setup the DOMSource:
String xmlString = "<ns1:countResponse xmlns:ns1=\"http://www.test.de/pill-counter\"><ns1:value>0</ns1:value><ns1:value>0</ns1:value><ns1:value>1</ns1:value><ns1:value>0</ns1:value><ns1:value>0</ns1:value><ns1:value>0</ns1:value></ns1:countResponse>";
ByteArrayInputStream xmlStream = new ByteArrayInputStream(xmlString.getBytes());
OMElement test = null;
try {
StAXBuilder builder = new StAXOMBuilder(xmlStream);
test = (OMElement) builder.getDocument().getChildren().next();
} catch (XMLStreamException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
OMElement documentElement = null;
try {
documentElement = AXIOMUtil.stringToOM(DOOMAbstractFactory.getOMFactory(), xmlString);
} catch (XMLStreamException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
SAAJConverterFactory convFactory = (SAAJConverterFactory) FactoryRegistry.getFactory(org.apache.axis2.jaxws.message.factory.SAAJConverterFactory.class);
SAAJConverter conv = convFactory.getSAAJConverter();
//Create soap 1.1 message
SOAPMessage msg = MessageFactory.newInstance().createMessage();
SOAPPart sp = msg.getSOAPPart();
SOAPEnvelope se = sp.getEnvelope();
SOAPBody soapBody = se.getBody();
javax.xml.soap.SOAPFactory soapFactory = javax.xml.soap.SOAPFactory.newInstance();
response = conv.toSAAJ(documentElement, soapBody, soapFactory);
Node root = response;
And now to apply the transformation:
Transformer transformer = null;
try {
transformer = TransformerFactory.newInstance().newTransformer(new StreamSource(new StringReader("<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" xmlns:ns1=\"http://www.test.de/pill-counter\">\n\n\t<xsl:template match=\"/\">\n\t\t<xsl:value-of select=\"sum(*/ns1:value)\" />\n\t</xsl:template>\n</xsl:stylesheet>")));
} catch (TransformerConfigurationException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
} catch (TransformerFactoryConfigurationError e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
try {
transformer.transform(new DOMSource(root), new StreamResult(System.out));
} catch (TransformerException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
The result of running this code is a NullPointerException.
SystemId unknown; Line num.0; Column num.0; java.lang.NullPointerException
I have tried searching for a solution to this problem on Google, the Xalan-j mailing list and on this site with no luck. I have also tried with several other coding approaches and no luck. Any ideas from anyone?
I found another way to get this working by generating the Document from scratch:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
dbf.setValidating(false);
DocumentBuilder db = null;
try {
db = dbf.newDocumentBuilder();
} catch (ParserConfigurationException e3) {
// TODO Auto-generated catch block
e3.printStackTrace();
}
InputSource is = new InputSource(new StringReader(documentElement.toString()));
Document document = null;
try{
document=db.parse(is);
} catch (SAXException e3) {
// TODO Auto-generated catch block
e3.printStackTrace();
} catch (IOException e3) {
// TODO Auto-generated catch block
e3.printStackTrace();
}
To use the JAXP API on an Axiom tree you don't need to convert it first to SAAJ or DOM. Axiom is able to create a SAXSource that can be passed to JAXP. An example can be found here. That example uses the javax.xml.validation API, but for javax.xml.transform it works the same way.
Note that the example uses some APIs introduced in recent Axiom versions, but the feature already exists for quite some time. Depending on the Axiom version you are using, the code needs to be adapted to the older API. In particular, instead of calling getSAXSource (which was introduced in 1.2.13), you need to construct an org.apache.axiom.om.impl.jaxp.OMSource object and pass that to JAXP.
Have you considered using wsdl2java to construct stubs, rather that using the low-level API directly? This would let you easily manipulate the reponse in java. Using xslt seems like an unusual approach in this case.