/*
* Copyright(c) 2005 Center for E-Commerce Infrastructure Development, The
* University of Hong Kong (HKU). All Rights Reserved. This software is licensed
* under the GNU GENERAL PUBLIC LICENSE Version 2.0 [1] [1]
* http://www.gnu.org/licenses/gpl.txt
*/
package hk.hku.cecid.corvus.partnership;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import hk.hku.cecid.piazza.commons.Sys;
import hk.hku.cecid.piazza.commons.dao.DAOException;
import hk.hku.cecid.piazza.commons.dao.DAOFactory;
import hk.hku.cecid.ebms.spa.dao.PartnershipDAO;
import hk.hku.cecid.ebms.spa.dao.PartnershipDVO;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.xml.sax.SAXException;
/**
* The <code>EbmsPartnership</code> is the utilities for maintaining the partnership
* of EbMS. In current version, it support addition or deletion of the partnership.
*
* @author kochiu, Twinsen Tsang (modifiers)
*
* @see #createEbmsPartnership(String)
* @see #removeEbmsPartnership(String)
*/
public class EbmsPartnership {
/**
* The entry point for CLI.
*
* @param args
* The arguments have two parametes. The first one is the partnership maintenance
* which is either "-a" (add) or "-d" (delete). The second one is the
* xml file containing the partnership information. They are located
* at the "conf/ebms.xml" relative to the program folders.
*/
public static void main(String[] args){
if (args.length < 2) { printUsage(); return; }
String option = args[0];
String xmlFile = args[1];
try {
if ("-a".equals(option)) {
boolean result = createEbmsPartnership(xmlFile);
System.out.println( result ? "Added partnership successfully." : "Cannot add partnership.");
} else if ("-d".equals(option)){
boolean result = removeEbmsPartnership(xmlFile);
System.out.println( result ? "Removed partnership successfully." : "Cannont remove partnership.");
} else {
printUsage();
}
} catch (Exception e){
e.printStackTrace();
}
}
private static void printUsage() {
System.out.println("Usage : java EbmsPartnership -options <xml_file_path>");
System.out.println("Options :");
System.out.println("\t -a \t Add partnership");
System.out.println("\t -d \t Delete partnership");
}
/**
* Create a EbMS partnership with the configuration defined in the <code>XMLFile</code>.
*
* @param xmlFile
* The partnership XML instance file. It is located at "/data/ebms.xml".
* @return
* true if the removal operation ran successfully.
* @throws DAOException
* Error in persistence connectivity.
* @throws DocumentException
* Error in reading the parameter in the <code>xmlFile</code>.
* @throws SAXException
* Error in parsing the <code>xmlFile</code>.
* @throws IOException
*/
public static boolean createEbmsPartnership(String xmlFile)
throws DAOException, DocumentException, SAXException, IOException
{
Element e = getRootElementFromFile(xmlFile);
// Checking whether there is any field violating the EbMS specification.
List errors = fieldChecking(e);
if (errors.size() > 0){
for (int i = 0; i < errors.size(); i++)
System.out.println(errors.get(i));
return false;
}
/*
* Create an DAOFactory for creating EbMS partnership, you may refer
* to the configuration file for the setting of "ebms-daofactory" at
* "conf/partnership.ebms-dao.xml"
*/
DAOFactory ebmsDAOFactory = (DAOFactory) Sys.main.getComponent("ebms-daofactory");
// Create the EbMS partnership DAO and DVO.
PartnershipDAO partnershipDao = (PartnershipDAO) ebmsDAOFactory.createDAO(PartnershipDAO.class);
PartnershipDVO dvo = (PartnershipDVO) partnershipDao.createDVO();
String pID = e.attributeValue("id");
dvo.setPartnershipId(pID);
// There is the same database record found in the persistence, warning the user for
// overwriting the record.
if (partnershipDao.retrieve(dvo)){
System.out.println("Existing partnership with id: " + pID + " found. Removing it.");
partnershipDao.remove(dvo);
// create again.
dvo = (PartnershipDVO) partnershipDao.createDVO();
}
Element params = e.element("parameters");
String endpoint = params.elementText("transportEndpoint");
String protocol = endpoint.substring(0, endpoint.indexOf(":"));
dvo.setPartnershipId(pID);
dvo.setCpaId (params.elementText("cpaId"));
dvo.setService (params.elementText("service"));
dvo.setAction (params.elementText("action"));
dvo.setTransportProtocol (protocol);
dvo.setTransportEndpoint (endpoint);
dvo.setIsHostnameVerified (params.elementText("hostnameVerfiedInSsl"));
// The possible value of "syncReplyMode" is
// "mshSignalsOnly" (same connection response)
// "none" (different connection response)
dvo.setSyncReplyMode("true".equalsIgnoreCase(params
.elementText("syncReplyMode")) ? "mshSignalsOnly" : "none");
// The possible value of "acknowledgementRequested" is
// "always" (ACK is requested)
// "never" (ACK is not requested)
dvo.setAckRequested("true".equalsIgnoreCase(params
.elementText("acknowledgementRequested")) ? "always" : "never");
// The possible value of "acknowledgementSignedRequest" is
// "always" (ACK is required to sign before send back to sender)
// "never" (ACK is not required to sign)
dvo.setAckSignRequested("true".equalsIgnoreCase(params
.elementText("acknowledgementSignedRequest")) ? "always" : "never");
// The possible value of "duplicateElimination" is
// "always" (eliminate duplicate message)
// "never" (does not eliminate duplicate message)
dvo.setDupElimination("true".equalsIgnoreCase(params
.elementText("duplicateElimination")) ? "always" : "never");
// The possible value of "messageOrder" is
// "Guaranteed" (guaranteed the message(s) sent is in order)
// NotGuaranteed" (vice versa)
dvo.setMessageOrder("true".equalsIgnoreCase(params
.elementText("messageOrder")) ? "Guaranteed" : "NotGuaranteed");
// The flag whether digital signatures is required for outgoing delivery.
dvo.setSignRequested (params.elementText("signingRequired"));
// The flag whether encryption is required for outgoing delivery (SMTP only).
dvo.setEncryptRequested (params.elementText("encryptionRequired"));
dvo.setSignCert (Utilities.loadCert(params.elementText("certificateForVerification")));
dvo.setEncryptCert (Utilities.loadCert(params.elementText("certificateForEncryption")));
// General delivery information
dvo.setRetries (Integer.parseInt(params.elementText("maximumRetries")));
dvo.setRetryInterval(Integer.parseInt(params.elementText("retryInterval")));
dvo.setDisabled ("false");
// Create the partnership.
partnershipDao.create(dvo);
return true;
}
/**
* Checking whether there is any field in the partnership xml file
* violating the EbMS specification.
*
* @param root The root element in the partnership xml file.
* @return A list of string containing the error description. Empty list if no error has been found.
*/
private static List fieldChecking(Element root) {
Element params = root.element("parameters");
List errors = new ArrayList();
// When digital signatures is required for acknowledgment, the request of acknowledgment MUST
// be set. Also it is required to provide the cerificate for verification the acknolwedgment.
if (Utilities.getBooleanValue(params, "acknowledgementSignedRequest")){
if (!Utilities.getBooleanValue(params, "acknowledgementRequested")){
errors.add("Acknowledgement Requested must be set to 'true' to enable the Acknowledgement Signed Requested");
}
try {
if (Utilities.loadCert(params.elementText("certificateForVerification")) == null){
errors.add("A certificate must be defined in Certificate For Verification to enable the Acknowledgement Signed Requested");
}
} catch (IOException e1) {
errors.add("The certificate defined in Certificate For Verification cannot load to enable the Acknowledgement Signed Requested. Details : " + e1.getMessage());
}
}
// When acknowledgment is requested for delivery, the mechanism of eleminating duplicates EbXML Message
// MUST be set.
if (Utilities.getBooleanValue(params, "duplicateElimination")) {
if (!Utilities.getBooleanValue(params, "acknowledgementRequested")) {
errors.add("Acknowledgement Requested must be set to 'true' to enable the Duplicate Elimination");
}
}
// When message ordering is requested for delivery, it is implied that the transaction MUST
// requires acknolwedgment, duplicate elimination and using asynchronous reply mode.
if (Utilities.getBooleanValue(params, "messageOrder")) {
if (!Utilities.getBooleanValue(params, "acknowledgementRequested")) {
errors.add("Acknowledgement Requested must be set to 'true' to enable the Message Order");
}
if (!Utilities.getBooleanValue(params, "duplicateElimination")) {
errors.add("Duplicate Elimination must be set to 'true' to enable the Message Order");
}
if (Utilities.getBooleanValue(params, "syncReplyMode")) {
errors.add("Sync Reply Mode must be set to 'false' to enable the Message Order");
}
}
// When the transaction requires data encryption (SMTP only), it MUST provides the public
// certificate for doing such things.
if (Utilities.getBooleanValue(params, "encryptionRequired")) {
try {
if (Utilities.loadCert(params.elementText("certificateForEncryption")) == null){
errors.add("A certificate must be defined in Certificate For Encryption to enable the Message Encryption");
}
} catch (IOException e1) {
errors.add("The certificate defined in Certificate For Encryption cannot load to enable the Message Encryption. Details : " + e1.getMessage());
}
}
return errors;
}
/**
* Remove a particular partnership defined in the <code>xmlFile</code>.<br/><br/>
*
* Only the attributes <id> in the <code>xmlFile</code> will be used
* for removing partnership.
*
* @param xmlFile
* The partnership XML instance file. It is located at "/data/ebms.xml".
* @return
* true if the removal operation ran successfully.
* @throws DAOException
* Error in persistence connectivity.
* @throws DocumentException
* Error in reading the parameter in the <code>xmlFile</code>.
* @throws SAXException
* Error in parsing the <code>xmlFile</code>.
* @throws IOException
*
*/
public static boolean removeEbmsPartnership(String xmlFile)
throws DAOException, DocumentException, SAXException, IOException
{
Element root = getRootElementFromFile(xmlFile);
/*
* Create an DAOFactory for creating EbMS partnership, you may refer
* to the configuration file for the setting of "ebms-daofactory" at
* "conf/partnership.ebms-dao.xml"
*/
DAOFactory ebmsDAOFactory = (DAOFactory) Sys.main.getComponent("ebms-daofactory");
// Create the EbMS partnership DAO and DVO.
PartnershipDAO partnershipDao = (PartnershipDAO) ebmsDAOFactory.createDAO(PartnershipDAO.class);
PartnershipDVO dvo = (PartnershipDVO) partnershipDao.createDVO();
String pidToRemove = root.attributeValue("id");
if (pidToRemove == null || "".equalsIgnoreCase(pidToRemove))
throw new DocumentException("Missing attribute <id> for deleting the partnership.");
// Set the id of the partnership to remove.
dvo.setPartnershipId(pidToRemove);
return partnershipDao.remove(dvo);
}
/**
* Read and parse the <code>xmlFile</code> and return the root element (document).
*
* @param xmlFile
* The partnership XML instance file. It is located at "/data/ebms.xml".
* @return The root element of the <code>xmlFile</code>.
* @throws SAXException
* Error in parsing the <code>xmlFile</code>.
* @throws DocumentException
* Error in reading the parameter in the <code>xmlFile</code>.
* @throws IOException
*/
private static Element getRootElementFromFile(String xmlFile)
throws SAXException, DocumentException, IOException
{
InputStream is = new FileInputStream(xmlFile);
SAXReader reader = new SAXReader();
// Setup the XSD validation features.
reader.setFeature("http://apache.org/xml/features/validation/schema",true);
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
reader.setProperty("http://apache.org/xml/properties/schema/external-schemaLocation", "data/ebms.xsd");
Document doc = reader.read(is);
return doc.getRootElement();
}
}