001    package biz.hammurapi.jms.adapter.converters;
002    
003    import java.io.StringReader;
004    import java.io.StringWriter;
005    import java.util.Map;
006    
007    import javax.jms.JMSException;
008    import javax.jms.Message;
009    import javax.jms.Session;
010    import javax.jms.TextMessage;
011    
012    import org.apache.xmlbeans.XmlObject;
013    
014    import biz.hammurapi.jms.adapter.Converter;
015    import biz.hammurapi.jms.adapter.JmsAdapter;
016    import biz.hammurapi.xml.dom.DOMUtils;
017    import biz.hammurapi.xmlbeans.XmlObjectSerializable;
018    
019    /**
020     * Converts object to message and vice versa using XML Beans.
021     * Falls back to dom serialization and domConfigFactory if no XML Beans types are available.
022     * @author Pavel
023     *
024     */
025    public class XmlBeansConverter implements Converter {
026    
027            /**
028             * Parses message content to XmlObject. If message content contains excepiton then this method
029             * tries to throw exception of the same type with the same message.
030             */
031            public Object convert(Message message, Map properties) throws Exception {               
032                    XmlObject ret = XmlObject.Factory.parse(new StringReader(((TextMessage) message).getText()));
033                    if (ret instanceof biz.hammurapi.invocation.ExceptionDocument) {
034                            biz.hammurapi.invocation.Exception xex = ((biz.hammurapi.invocation.ExceptionDocument) ret).getException();
035                            if (!JmsAdapter.isBlank(xex.getType())) {
036                                    Exception toThrow = null;                               
037                                    try {
038                                            Class exceptionClass = Class.forName(xex.getType());
039                                            if (Exception.class.isAssignableFrom(exceptionClass)) {
040                                                    if (!JmsAdapter.isBlank(xex.getMessage())) {
041                                                            toThrow = (Exception) exceptionClass 
042                                                                    .getConstructor(new Class[] {String.class})
043                                                                    .newInstance(new String[] {xex.getMessage()});
044                                                    } else {
045                                                            toThrow = (Exception) exceptionClass.newInstance();
046                                                    }
047                                            }
048                                    } catch (Exception e) {
049                                            toThrow = new JMSException("Remote exception "+xex.getType()+": "+xex.getMessage());
050                                    }                                       
051                                    throw toThrow == null ? new JMSException("Remote exception "+xex.getType()+": "+xex.getMessage()) : toThrow;
052                            }
053                            throw new JMSException("Remote exception: "+xex.getMessage());
054                    }
055                    return ret;
056            }
057    
058            /**
059             * Writes XmlObjects using save() method. Uses DOM serialization for other objects.
060             * Converts XmlBeansSerializabe to XmlObjects.
061             */
062            public Message convert(Object obj, Session session, Map properties, Message request) throws Exception {
063                    TextMessage ret = session.createTextMessage();
064                    if (obj instanceof XmlObject) {
065                            StringWriter sw = new StringWriter();
066                            ((XmlObject) obj).save(sw);
067                            sw.close();
068                            ret.setText(sw.toString());
069                    } else if (obj instanceof XmlObjectSerializable) {
070                            StringWriter sw = new StringWriter();
071                            ((XmlObjectSerializable) obj).toXmlObject().save(sw);
072                            sw.close();
073                            ret.setText(sw.toString());
074                    } else {
075                            ret.setText(DOMUtils.toXmlString(obj, "request"));
076                    }
077                    if (request!=null) {
078                            ret.setJMSCorrelationID(request.getJMSMessageID());
079                    }
080                    return ret;
081            }
082    
083            public Message convert(Exception e, Session session, Map properties, Message request) throws Exception {
084                    biz.hammurapi.invocation.ExceptionDocument doc = biz.hammurapi.invocation.ExceptionDocument.Factory.newInstance(); 
085                    biz.hammurapi.invocation.Exception xex = doc.addNewException();
086                    exceptionToXml(e, xex);
087                                    
088                    StringWriter sw = new StringWriter();
089                    doc.save(sw);
090                    sw.close();
091                    
092                    TextMessage ret = session.createTextMessage();
093                    ret.setText(sw.toString());
094                    if (request!=null) {
095                            ret.setJMSCorrelationID(request.getJMSMessageID());
096                    }
097                    return ret;
098            }
099            
100            static void exceptionToXml(Throwable ex, biz.hammurapi.invocation.Exception xex) {
101                    xex.setType(ex.getClass().getName());
102                    if (ex.getMessage()!=null) {
103                            xex.setMessage(ex.getMessage());
104                    }
105                    
106                    StackTraceElement[] trace = ex.getStackTrace();
107                    if (trace!=null) {
108                            for (int i=0; i<trace.length; ++i) {
109                                    biz.hammurapi.invocation.StackFrame xFrame = xex.addNewStackFrame();
110                                    xFrame.setDeclaringClass(trace[i].getClassName());
111                                    xFrame.setFile(trace[i].getFileName());
112                                    xFrame.setLine(trace[i].getLineNumber());
113                                    xFrame.setMethod(trace[i].getMethodName());
114                            }
115                    }
116                    
117                    if (ex.getCause()!=null) {
118                            exceptionToXml(ex.getCause(), xex.addNewCause());
119                    }
120                    
121            }       
122    
123    }