/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.soa.esb.registry.systinet;
import java.util.Vector;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPPart;
import javax.xml.soap.SOAPMessage;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.juddi.datatype.RegistryObject;
import org.apache.juddi.datatype.response.DispositionReport;
import org.apache.juddi.datatype.response.ErrInfo;
import org.apache.juddi.datatype.response.Result;
import org.apache.juddi.error.BusyException;
import org.apache.juddi.error.FatalErrorException;
import org.apache.juddi.error.RegistryException;
import org.apache.juddi.error.UnsupportedException;
import org.apache.juddi.handler.HandlerMaker;
import org.apache.juddi.handler.IHandler;
import org.apache.juddi.registry.RegistryEngine;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import com.systinet.wasp.webservice.ServiceClientImpl;
import org.systinet.wasp.webservice.ServiceClient;
import com.systinet.wasp.client.XMLInvocationHelperImpl;
import org.systinet.wasp.client.XMLInvocationHelper;
import com.systinet.saaj.soap.WaspSOAPMessageFactoryImpl;
import org.systinet.uddi.client.base.UDDIObject;
import javax.xml.soap.SOAPElement;
import org.idoox.wasp.Context;
import org.idoox.webservice.client.WebServiceLookup;
import org.systinet.uddi.client.v2.Publish;
import org.systinet.uddi.client.v2.Inquire;
import org.systinet.uddi.client.base.UDDIObject;
import org.idoox.webservice.client.WebServiceLookup;
// imports of WASP security
import org.idoox.security.AuthResult;
import org.idoox.security.Credentials;
import org.idoox.security.PrincipalAuthenticator;
import org.idoox.security.client.Current;
import org.systinet.uddi.client.v2.UDDIException;
import org.jboss.soa.esb.common.Configuration;
import org.jboss.soa.esb.common.Environment;
import org.jboss.soa.esb.common.ModulePropertyManager;
/**
* RequestHandler makes a UDDI call and returns the UDDI response in a threaded manner.
*
* @author Tom Cunningham (tcunning@redhat.com)
*/
public class RequestHandler implements Runnable
{
// private reference to the webapp's logger.
private static Log log = LogFactory.getLog(RequestHandler.class);
// XML Document Builder
private static DocumentBuilder docBuilder = null;
private ServiceClient serviceClient;
private volatile String user;
private volatile String password;
private volatile String version;
private volatile String operation;
private volatile Element uddiReq;
private volatile Node response;
private volatile String exception;
private static final String FROM_XML = "fromXML";
private static final String TO_XML = "toXML";
private static final String DEFAULT_USER = "jbossesb";
private Inquire inquiry;
private Publish publish;
public RequestHandler() {
inquiry =
(Inquire) Context.getInstance(Inquire.class);
publish =
(Publish) Context.getInstance(Publish.class);
String esbuser = ModulePropertyManager.getPropertyManager(ModulePropertyManager.REGISTRY_MODULE).getProperty(Environment.REGISTRY_USER);
String esbpassword = ModulePropertyManager.getPropertyManager(ModulePropertyManager.REGISTRY_MODULE).getProperty(Environment.REGISTRY_PASSWORD);
setUser(esbuser);
setPassword (esbpassword);
}
/**
* Grab the local name of the UDDI request element
* from the UDDI Request. If a value isn't returned
* (either null or an empty String is returned) then
* throw a FatalError exception. This is probably a
* configuration problem related to the XML Parser
* that jUDDI is using.
* @param uddiReq
* @return
* @throws Exception
*/
public String getOperation(Element uddiReq) throws Exception
{
if (uddiReq == null)
throw new FatalErrorException("A UDDI request was not " +
"found in the SOAP message.");
String operation = uddiReq.getLocalName();
if ((operation == null) || (operation.trim().length() == 0))
throw new FatalErrorException("The UDDI service operation " +
"could not be identified.");
setOperation(operation);
return operation;
}
/**
* Grab the generic attribute value (version value). If
* one isn't specified or the value specified is not "2.0"
* then throw an exception (this value must be specified
* for all UDDI requests and currently only vesion 2.0
* UDDI requests are supported).
*
* @param uddiReq
* @return
* @throws Exception
*/
public String getVersion(Element uddiReq, String operation) throws Exception
{
String version = uddiReq.getAttribute("generic");
if (version == null)
throw new FatalErrorException("A UDDI generic attribute " +
"value was not found for UDDI request: "+operation+" (The " +
"'generic' attribute must be present)");
setVersion(version);
return version;
}
public void run()
{
try
{
RequestUtil util = RequestUtil.getInstance();
String api = util.getApi(operation);
if (util.INQUIRY_API.equals(api)) {
Class c = inquiry.getClass();
Method m = c.getMethod(operation,
(Class)util.getInquiryQueries().get(operation.toLowerCase()));
// Change the jUDDI UDDI req to a Systinet one
Class clazz = (Class)util.getInquiryQueries().get(operation.toLowerCase());
Object obj = clazz.newInstance();
Method fromXML = clazz.getMethod(FROM_XML, org.w3c.dom.Element.class);
UDDIObject uddiobj = (UDDIObject)fromXML.invoke(obj, uddiReq);
CallDemarcation.beginCall(user, password);
UDDIObject object = (UDDIObject) m.invoke(inquiry, uddiobj);
CallDemarcation.endCall();
DocumentBuilder docBuilder = getDocumentBuilder();
Document document = docBuilder.newDocument();
Class responseClass = (Class) util.getInquiryReturnTypes().get(operation.toLowerCase());
Method toXML = responseClass.getMethod(TO_XML, org.w3c.dom.Document.class);
Element elem = (Element) toXML.invoke(object, document);
document.appendChild(elem);
setResponse(document);
} else if (util.PUBLISH_API.equals(api)) {
Class c = publish.getClass();
Method m = c.getMethod(operation,
(Class)util.getPublishQueries().get(operation.toLowerCase()));
// Change the jUDDI UDDI req to a Systinet one
Class clazz = (Class)util.getPublishQueries().get(operation.toLowerCase());
Object obj = clazz.newInstance();
Method fromXML = clazz.getMethod(FROM_XML, org.w3c.dom.Element.class);
UDDIObject uddiobj = (UDDIObject)fromXML.invoke(obj, uddiReq);
CallDemarcation.beginCall(user, password);
UDDIObject object = (UDDIObject) m.invoke(publish, uddiobj);
CallDemarcation.endCall();
DocumentBuilder docBuilder = getDocumentBuilder();
Document document = docBuilder.newDocument();
Class responseClass = (Class) util.getPublishReturnTypes().get(operation.toLowerCase());
Method toXML = responseClass.getMethod(TO_XML, org.w3c.dom.Document.class);
Element pubElem = (Element) toXML.invoke(object, document);
document.appendChild(pubElem);
setResponse(document);
} else {
setException("Operation " + operation + " was not found in the inquiry "
+ "or the publication API.");
}
}
catch (RegistryException rex)
{
log.error(rex.getMessage());
// All RegistryException and subclasses of RegistryException
// should contain values for populating a SOAP Fault as well
// as a UDDI DispositionReport with specific information
// about the problem.
// SOAP Fault values
String faultCode = rex.getFaultCode();
String faultString = rex.getFaultString();
String faultActor = rex.getFaultActor();
// UDDI DispositionReport values
String errno = null;
String errCode = null;
String errText = null;
DispositionReport dispRpt = rex.getDispositionReport();
if (dispRpt != null)
{
Result result = null;
ErrInfo errInfo = null;
Vector results = dispRpt.getResultVector();
if ((results != null) && (!results.isEmpty()))
result = (Result)results.elementAt(0);
if (result != null)
{
errno = String.valueOf(result.getErrno()); // UDDI Result errno
errInfo = result.getErrInfo();
if (errInfo != null)
{
errCode = errInfo.getErrCode(); // UDDI ErrInfo errCode
errText = errInfo.getErrMsg(); // UDDI ErrInfo errMsg
}
}
}
// We should have everything we need to assemble
// the SOAPFault so lets piece it together and
// send it on it's way.
String fault = "faultCode=" + faultCode + ", faultString=" + faultString
+ ", faultActor=" + faultActor + ", errno=" + errno + ", errCode=" + errCode
+ ", errText=" + errText;
setException(fault);
}
catch(Exception ex) // Catch any other exceptions
{
log.error(ex.getMessage());
// Because something occured that Systinet wasn't expecting
// let's set default SOAP Fault values. Since SOAPExceptions
// here are most likely XML validation errors let's blame the
// client by placing "Client" in the Fault Code and pass
// the Exception message back to the client.
String faultCode = "Server";
String faultString = null;
String faultActor = null;
String errno = null;
String errCode = null;
String errText = null;
if (ex instanceof InvocationTargetException) {
InvocationTargetException ite = (InvocationTargetException) ex;
if (ite.getTargetException() != null) {
faultString = ite.getTargetException().getMessage();
if (ite.getTargetException() instanceof UDDIException) {
UDDIException uddi = (UDDIException) ite.getTargetException();
errno = (new Integer(uddi.getErrno())).toString();
errCode = uddi.getFaultCode();
errText = uddi.getFaultString();
}
}
} else {
faultString = ex.getMessage();
faultActor = null;
// Let's set default values for the UDDI DispositionReport
// here. While we didn't catch a RegistryException (or
// subclass) but we're going to be friendly and include a
// FatalError DispositionReport within the SOAP Fault anyway.
errno = String.valueOf(Result.E_FATAL_ERROR);
errCode = Result.lookupErrCode(Result.E_FATAL_ERROR);
errText = Result.lookupErrText(Result.E_FATAL_ERROR) +
" An internal UDDI server error has " +
"occurred. Please report this error " +
"to the UDDI server administrator.";
// We should have everything we need to assemble
// the SOAPFault so lets piece it together and
// send it on it's way.
}
String fault = "faultCode=" + faultCode + ", faultString=" + faultString
+ ", faultActor=" + faultActor + ", errno=" + errno + ", errCode=" + errCode
+ ", errText=" + errText;
setException(fault);
}
}
/**
*
*/
private DocumentBuilder getDocumentBuilder()
{
if (docBuilder == null)
docBuilder = createDocumentBuilder();
return docBuilder;
}
/**
*
*/
private synchronized DocumentBuilder createDocumentBuilder()
{
if (docBuilder != null)
return docBuilder;
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
//factory.setValidating(true);
docBuilder = factory.newDocumentBuilder();
}
catch(ParserConfigurationException pcex) {
pcex.printStackTrace();
}
return docBuilder;
}
public String getOperation() {
return operation;
}
public void setOperation(String operation) {
this.operation = operation;
}
public Node getResponse() {
return response;
}
public void setResponse(Node response) {
this.response = response;
}
public Element getUddiReq() {
return uddiReq;
}
public void setUddiReq(Element uddiReq) {
this.uddiReq = uddiReq;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getUsername() {
return user;
}
public void setUsername(String version) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getException() {
return exception;
}
public void setException(String exception) {
this.exception = exception;
}
}