FileDocCategorySizeDatePackage
MessageDenormalizerImpl.javaAPI DocGlassfish v2 API26882Fri May 04 22:30:28 BST 2007com.sun.enterprise.jbi.serviceengine.util.soap

MessageDenormalizerImpl

public class MessageDenormalizerImpl extends Object implements MessageDenormalizer
This Basic Profile 1.0 aware implementation is used to denormalize a JBI Normalized Message and convert it into a SOAP message format.
author
Sun Microsystems, Inc.

Fields Summary
private static final String
PAYLOAD_NAMESPACE_PREFIX
Namespace prefix for the payload.
private static final String
SOAP_NAMESPACE_PREFIX
SOAP Namespace prefix.
private static final String
XML_SCHEMA_INSTANCE_NAMESPACE_PREFIX
XML Schema Instance prefix.
private MessageFactory
mMessageFactory
Internal handle to the message factory
private Logger
mLogger
Internal handle to the logger instance
private StringTranslator
mStringTranslator
Internal handle to String Translator instance.
private Transformer
mTransformer
Internal handle to the transformer instance
Constructors Summary
public MessageDenormalizerImpl()
Creates a new instance of MessageDenormalizerImpl.


               
     
    
        try
        {
            mLogger = Logger.getLogger(this.getClass().getPackage().getName());
            mStringTranslator = new StringTranslator(this.getClass().getPackage().getName(), this.getClass().getClassLoader());
            mMessageFactory = MessageFactory.newInstance();

            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            mTransformer = transformerFactory.newTransformer();
            mTransformer.setOutputProperty("method", "xml");
            mTransformer.setOutputProperty("omit-xml-declaration", "yes");
        }
        catch (Exception exception)
        {
            // This should not happen. In case it does, log the exception and
            // set the factory object to null
	    mLogger.severe( mStringTranslator.getString("SBC_MESSAGE_FACTORY_CREATION_FAILURE") );
	    mLogger.severe( mStringTranslator.getString("SBC_ERROR_DETAILS", exception.toString()) );
            mMessageFactory = null;
            mTransformer = null;
        }
    
Methods Summary
protected voidcloseWriter(java.io.Writer writer)
Closes the writer instance. This method handles any exceptions thrown while handling this request.

param
writer writer instance.

        if (writer != null)
        {
            try
            {
                writer.close();
            }
            catch (Exception ioException)
            {
                // This should not happen. In case it does do nothing
		mLogger.warning( mStringTranslator.getString("SBC_CLOSE_OUTPUT_STREAM") );
		mLogger.warning( mStringTranslator.getString("SBC_ERROR_DETAILS", ioException.toString()) );
            }
        }
    
protected javax.xml.soap.SOAPMessagecreateSOAPMessage(java.io.ByteArrayOutputStream byteStream)
Uses the provided input data to create a javax.xml.soap.SOAPMessage instance.

param
byteStream Stream which contains the soap messages information as bytes.
return
SOAP Message object
throws
SOAPException if soap message object cannot be created.
throws
IOException if soap message object cannot be created.

        if (mLogger.isLoggable(Level.FINEST))
        {
	    mLogger.finest( mStringTranslator.getString("SBC_DEONRMALIZED_MESSAGE_DETAILS", byteStream.toString()) );
        }

        // Create a soap message
        SOAPMessage soapMessage = mMessageFactory.createMessage();

        // Populate the fault message in the soap Message
        byte[] data = byteStream.toByteArray();
        ByteArrayInputStream soapInputStream = new ByteArrayInputStream(data);
        StreamSource streamSource = new StreamSource(soapInputStream);
        soapMessage.getSOAPPart().setContent(streamSource);
        soapInputStream.close();

        return soapMessage;
    
private voiddenormalizeAttachments(javax.xml.soap.SOAPMessage soapMessage, javax.jbi.messaging.NormalizedMessage normalizedMessage)
Denormalizes the attachments present in the JBI Normalized Message and adds them to the javax.xml.soap.SoapMessage instance.

param
soapMessage soap message.
param
normalizedMessage normalized message instance.

        if ( normalizedMessage != null )
        {
            Iterator attachmentIter = normalizedMessage.getAttachmentNames().iterator();
            for (; attachmentIter.hasNext();)
            {
                String attachmentIdentifier = (String) attachmentIter.next();
                DataHandler dataHandler =
                            normalizedMessage.getAttachment( attachmentIdentifier);
                AttachmentPart attachment =
                    soapMessage.createAttachmentPart( dataHandler);
                attachment.setContentId ( attachmentIdentifier);
                attachment.setContentType ( dataHandler.getContentType());
                soapMessage.addAttachmentPart ( attachment );
            }
        }
    
public SOAPWrapperdenormalizeFaultMessage(javax.jbi.messaging.Fault faultMessage)
Converts a JBI Fault mesage to a standard javax.xml.soap.SOAPMessage message instance. It uses the default Server fault code for denormalization.

param
faultMessage JBI fault message.
return
a new SOAPWrapper instance which contains the SOAP fault Message.

        return denormalizeFaultMessage(faultMessage, SOAPConstants.SERVER_FAULT_CODE);
    
public SOAPWrapperdenormalizeFaultMessage(javax.jbi.messaging.Fault faultMessage, java.lang.String faultCode)
Converts a JBI Fault mesage to a SOAP Message using the specified fault code.

param
faultMessage JBI fault message.
param
faultCode fault code to be used in the fault message
return
a new SOAPWrapper instance which contains the SOAP fault Message.

        SOAPWrapper wrapper = null;
        Writer writer = null;

	mLogger.fine( mStringTranslator.getString("SBC_DENORMALIZE_FAULT_MESSAGE") );

        try
        {
            // Create the ws-i compliant fault message from the exception
            ByteArrayOutputStream bufferedStream = new ByteArrayOutputStream();
            String messageFaultCode = (String) faultMessage.getProperty(
                                        SOAPConstants.FAULT_CODE_PROPERTY_NAME);
            String faultString = (String) faultMessage.getProperty(
                                        SOAPConstants.FAULT_STRING_PROPERTY_NAME);

            if ( messageFaultCode != null )
            {
                // Override the fault code with the message fault code.
                faultCode = messageFaultCode;
            }

            if ( faultString == null )
            {
                faultString = mStringTranslator.getString("SBC_DEFAULT_FAULT_STRING");
            }
            writer = new OutputStreamWriter(bufferedStream, "UTF-8");
            writeEnvelopeHeader(writer);
            writer.write("<" + SOAP_NAMESPACE_PREFIX + ":Body>");
            writer.write(
                "<" + SOAP_NAMESPACE_PREFIX + ":Fault " +
                XML_SCHEMA_INSTANCE_NAMESPACE_PREFIX + ":type=\"" +
                SOAP_NAMESPACE_PREFIX + ":Fault\"" + "><faultcode>" +
                SOAP_NAMESPACE_PREFIX + ":" + faultCode + "</faultcode>");
            writer.write("<faultstring>" + faultString + "</faultstring>");
            writeFaultDetail(faultMessage, writer);
            writer.write("</" + SOAP_NAMESPACE_PREFIX + ":Fault>");
            writer.write("</" + SOAP_NAMESPACE_PREFIX + ":Body>");
            writeEnvelopeFooter(writer);
            writer.flush();

            // Create a soap message
            SOAPMessage soapMessage = createSOAPMessage(bufferedStream);

            // Create a SOAP wrapper with service url as null
            wrapper = new SOAPWrapper(soapMessage);
            wrapper.setStatus(SOAPConstants.JBI_FAULT);
        }
        catch (RuntimeException runtimeException)
        {
	    mLogger.severe( mStringTranslator.getString( "SBC_SOAP_FAULT_GENERATION_FAILURE_RT_EXP") );
        }
        catch (Exception exception)
        {
            // This should not happen. In case it does do nothing. Log message
	    mLogger.severe( mStringTranslator.getString("SBC_SOAP_FAULT_GENERATION_FAILURE") );
        }
        finally
        {
            closeWriter(writer);
        }

	mLogger.fine( mStringTranslator.getString("SBC_SUCCESS_DENORMALIZE_FAULT") );

        return wrapper;
    
public SOAPWrapperdenormalizeMessage(javax.jbi.messaging.NormalizedMessage normalizedMessage, Operation operation, boolean isResponse)
Converts a JBI normalized message to a javax.jbi.soap.SOAPMessage instance. The SOAP Header information is extracted from the NormalizedMessage property "SoapHeader" and the SOAP Body content is extracted from the Normalized Message content. Any attachments present in the NormalizedMessage are also denormalized and added to the created javax.jbi.soap.SOAPMessage instance.

param
normalizedMessage message to be denormalized.
param
operation operation invoked
param
isResponse indicates if a response messages needs to be generated
return
the SOAP Message.

        SOAPWrapper wrapper = null;
        Writer writer = null;
	mLogger.fine( mStringTranslator.getString("SBC_DENORMALIZE_JBI_MESSAGE") );

        try
        {
            // Create a SOAP Message
            ByteArrayOutputStream bufferedStream = new ByteArrayOutputStream();
            writer = new OutputStreamWriter(bufferedStream, "UTF-8");

            writeEnvelopeHeader(writer);

            if ( normalizedMessage != null)
            {
                // Writer the header to the writer instance.
                writeHeader(normalizedMessage, writer);
            }

            // Extract the body information from the Normalized Message
            writeBody(normalizedMessage, operation, isResponse, writer);
            writeEnvelopeFooter(writer);
            writer.flush();

            // Create a soap message
            SOAPMessage soapMessage = createSOAPMessage(bufferedStream);

            // Denormalize Attachments
            denormalizeAttachments ( soapMessage, normalizedMessage);
            // Create a soap response wrapper
            wrapper = new SOAPWrapper(soapMessage);

            if (normalizedMessage instanceof Fault)
            {
                wrapper.setStatus(SOAPConstants.JBI_FAULT);
            }
            else
            {
                wrapper.setStatus(SOAPConstants.JBI_SUCCESS);
            }
        }
        catch (RuntimeException runtimeException)
        {
	    mLogger.severe( mStringTranslator.getString("SBC_DENORMALIZE_JBI_MESSAGE_FAILURE_RT_EXP") );
            // Create a soap fault wrapper
            wrapper = denormalizeMessage(runtimeException);
        }
        catch (Exception exception)
        {
	    mLogger.warning( mStringTranslator.getString("SBC_DENORMALIZE_JBI_MESSAGE_FAILURE_EXP") );
	    mLogger.warning( mStringTranslator.getString("SBC_ERROR_DETAILS", exception.toString()) );
	    mLogger.warning( mStringTranslator.getString("SBC_CREATE_SOAP_FAULT") );

            // Create a soap fault wrapper
            wrapper = denormalizeMessage(exception);
        }
        finally
        {
            closeWriter(writer);
        }

	mLogger.fine( mStringTranslator.getString("SBC_SUCCESS_DENORMALIZE_JBI_MESSAGE") );

        return wrapper;
    
public SOAPWrapperdenormalizeMessage(java.lang.Exception exception)
Converts an exception to a SOAP Message. It uses the default Server fault code for denormalization.

param
exception exception instance
return
denormalized exception object

        return denormalizeMessage(exception, SOAPConstants.SERVER_FAULT_CODE);
    
public SOAPWrapperdenormalizeMessage(java.lang.Exception exception, java.lang.String faultCode)
Converts an exception to a SOAP Message using the provided faultCode. The code expects the faultcode passed to be part of the soap namespace.

param
exception exception instance
param
faultCode fault code
return
denormalized exception object

        SOAPWrapper wrapper = null;
        Writer writer = null;

	mLogger.fine( mStringTranslator.getString("SBC_DENORMALIZE_EXCEPTION") );

        try
        {
            // Create the ws-i compliant fault message from the exception
            ByteArrayOutputStream bufferedStream = new ByteArrayOutputStream();
            writer = new OutputStreamWriter(bufferedStream, "UTF-8");

            if (exception == null)
            {
		mLogger.warning( mStringTranslator.getString("SBC_NULL_OBJECT_DENORMALIZATION") );
            }

            writeEnvelopeHeader(writer);
            writer.write("<" + SOAP_NAMESPACE_PREFIX + ":Body>");
            writeFault(exception, faultCode, writer);
            writer.write("</" + SOAP_NAMESPACE_PREFIX + ":Body>");
            writeEnvelopeFooter(writer);
            writer.flush();

            // Create a soap message
            SOAPMessage soapMessage = createSOAPMessage(bufferedStream);

            // Create a SOAP wrapper with service url as null
            wrapper = new SOAPWrapper(soapMessage);
            wrapper.setStatus(SOAPConstants.JBI_ERROR);
        }
        catch (RuntimeException runtimeException)
        {
	    mLogger.severe( mStringTranslator.getString( "SBC_SOAP_FAULT_GENERATION_FAILURE_RT_EXP") );
        }
        catch (Exception denormalizationException)
        {
            // This should not happen. In case it does do nothing. Log message
	    mLogger.severe( mStringTranslator.getString("SBC_SOAP_FAULT_GENERATION_FAILURE") );
        }
        finally
        {
            closeWriter(writer);
        }

	mLogger.fine( mStringTranslator.getString("SBC_SUCCESS_DENORMALIZE_EXCEPTION") );

        return wrapper;
    
protected java.lang.StringsanitizeMessage(java.lang.String errorMessage)
Sanitizes the messages so that it can be properly read by an XML parser.

param
errorMessage error message to be sanitized.
return
sanitized error message.

        StringBuffer sanitizedBuffer = new StringBuffer();

        for (int i = 0; (errorMessage != null) && (i < errorMessage.length()); i++)
        {
            char currentChar = errorMessage.charAt(i);

            switch (currentChar)
            {
            case '"":
                sanitizedBuffer.append(""");

                break;

            case '&":
                sanitizedBuffer.append("&");

                break;

            case '<":
                sanitizedBuffer.append("<");

                break;

            case '>":
                sanitizedBuffer.append(">");

                break;

            default:
                sanitizedBuffer.append(currentChar);
            }
        }

        if (errorMessage == null)
        {
            return "INTERNAL SERVER ERROR";
        }
        else
        {
            return sanitizedBuffer.toString();
        }
    
protected voidwriteBody(javax.jbi.messaging.NormalizedMessage normalizedMessage, Operation operation, boolean isResponse, java.io.Writer writer)
This method extracts the payload from the Normalized Message and writes it using the writer stream. The payload content is enclosed between the SOAP:Body header and SOAP:Body footer information.

param
normalizedMessage normalized message
param
operation operation invoked
param
isResponse indicates if a response messages needs to be generated
param
writer writer object to be used
throws
Exception if the body cannot be written

        StringWriter stringWriter = null;

        try
        {
            boolean isEmptyResponse = isResponse && ( normalizedMessage == null );
            // Add the body information
            writeBodyHeader(operation, writer, isEmptyResponse);
            if ( normalizedMessage != null)
            {
                stringWriter = new StringWriter();
                Result result = new StreamResult(stringWriter);
                mTransformer.transform(normalizedMessage.getContent(), result);
                writer.write(stringWriter.toString());
            }
            writeBodyFooter(operation, writer, isEmptyResponse);
            writer.flush();
        }
        finally
        {
            closeWriter(stringWriter);
        }
    
protected voidwriteBodyFooter(Operation operation, java.io.Writer writer, boolean isEmptyResponse)
Uses writer object to write the SOAP:Body footer information. This method is invoked after the body payload has been written.

param
operation operation invoked
param
writer writer object.
param
isEmptyResponse indicates if a response messages needs to be generated
throws
Exception if body footer cannot be written


        if (  isEmptyResponse )
        {
            writer.write("</" + PAYLOAD_NAMESPACE_PREFIX + ":");
            writer.write(operation.getName() + "Response>");
        }
        writer.write("</" + SOAP_NAMESPACE_PREFIX + ":Body>");
        writer.flush();
    
protected voidwriteBodyHeader(Operation operation, java.io.Writer writer, boolean isEmptyResponse)
Uses the writer object to write the SOAP:Body header information. This method is invoked before the body payload is written.

param
operation operation invoked
param
writer writer object to be used
param
isEmptyResponse indicates if an empty response message needs to be generated
throws
Exception if body header cannot be written.

        writer.write("<" + SOAP_NAMESPACE_PREFIX + ":Body>");

        if ( isEmptyResponse)
        {
            writer.write("<" + PAYLOAD_NAMESPACE_PREFIX + ":");
            writer.write(operation.getName() + "Response");
            writer.write(" xmlns:" + PAYLOAD_NAMESPACE_PREFIX + "=\"");
            writer.write(operation.getOutputNamespace() + "\"");
            writer.write(">");
        }

        writer.flush();
    
protected voidwriteEnvelopeFooter(java.io.Writer writer)
Uses writer object to write the SOAP:Envelope footer information. This method is invoked after writing the envelope content ( header and body content).

param
writer writer object
throws
IOException if envelope footer information cannot be written.

        writer.write("</" + SOAP_NAMESPACE_PREFIX + ":Envelope>");
        writer.flush();
    
protected voidwriteEnvelopeHeader(java.io.Writer writer)
Uses writer object to write the SOAP:Envelope header information. This method is invoked before writing the envelope content ( header and body content).

param
writer writer object.
throws
IOException if envelope header information cannot be written.

        // Write the soap envelope
        writer.write(
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<" + SOAP_NAMESPACE_PREFIX +
            ":Envelope xmlns:" + SOAP_NAMESPACE_PREFIX +
            "=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:" +
            XML_SCHEMA_INSTANCE_NAMESPACE_PREFIX +
            "=\"http://www.w3.org/2001/XMLSchema-instance\">");
        writer.flush();
    
protected voidwriteFault(java.lang.Exception exception, java.lang.String faultCode, java.io.Writer writer)
Create the SOAP:Fault message based on the provided exception details and writes it using the writer instance.

param
exception exception thrown
param
faultCode fault code
param
writer writer object
throws
IOException if fault message cannot be generated.

        writer.write(
            "<" + SOAP_NAMESPACE_PREFIX + ":Fault><faultcode>" + SOAP_NAMESPACE_PREFIX +
            ":" + faultCode + "</faultcode>");

        if (exception != null)
        {
            writer.write("<faultstring>" +
                         sanitizeMessage(exception.getMessage()) + "</faultstring>");
        }

        writer.write("</" + SOAP_NAMESPACE_PREFIX + ":Fault>");
        writer.flush();
    
private voidwriteFaultDetail(javax.jbi.messaging.Fault faultMessage, java.io.Writer writer)
Writes the detailed fault message using the provided writer instance.

param
faultMessage JBI Fault object which contains the fault details.
param
writer writer object to be used.
throws
Exception if the fault detail vould not be written.

        StringWriter stringWriter = null;

        try
        {
            stringWriter = new StringWriter();

            Result result = new StreamResult(stringWriter);
            mTransformer.transform(faultMessage.getContent(), result);

            // Add the fault detail
            String detailString = stringWriter.toString().trim();

            if (!detailString.equals(""))
            {
                writer.write("<detail>");
                writer.write(detailString);
                writer.write("</detail>");
                writer.flush();
            }
        }
        finally
        {
            closeWriter(stringWriter);
        }
    
protected voidwriteHeader(javax.jbi.messaging.NormalizedMessage normalizedMessage, java.io.Writer writer)
The method extracts the header information from the Normalized Message property "SoapHeader" and writes it using the writer instance. The header information is expected to be propagated as a javax.xml.soap.SOAPHeader implementation instance.

param
normalizedMessage normalizedMessage
param
writer writer object to be used
throws
Exception if header cannot be used to write to the writer instance

        // Extract header information from the Normalized Message
        SOAPHeader soapHeader =
            (SOAPHeader) normalizedMessage.getProperty(
                SOAPConstants.HEADER_PROPERTY_NAME );
        StringWriter stringWriter = null;

        if ( soapHeader != null)
        {
            try
            {
                stringWriter = new StringWriter();

                Source source = new DOMSource( soapHeader );
                Result result = new StreamResult(stringWriter);
                mTransformer.transform(source, result);

                // Add the header information
                writer.write("<" + SOAP_NAMESPACE_PREFIX + ":Header>");
                writer.write(stringWriter.toString());
                writer.write("</" + SOAP_NAMESPACE_PREFIX + ":Header>");
                writer.flush();
            }
            finally
            {
                closeWriter(stringWriter);
            }
        }
        else
        {
	    mLogger.fine( mStringTranslator.getString("SBC_NO_HEADER") );
        }