1 /***
2 *
3 * Copyright 2005 LogicBlaze, Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 **/
18 package org.logicblaze.lingo.jms.marshall;
19
20 import org.apache.commons.logging.Log;
21 import org.apache.commons.logging.LogFactory;
22 import org.logicblaze.lingo.LingoInvocation;
23 import org.logicblaze.lingo.jms.Requestor;
24 import org.springframework.remoting.support.RemoteInvocation;
25 import org.springframework.remoting.support.RemoteInvocationResult;
26
27 import javax.jms.JMSException;
28 import javax.jms.Message;
29 import javax.jms.ObjectMessage;
30 import javax.jms.Session;
31 import javax.jms.TextMessage;
32
33 import java.io.Serializable;
34
35 /***
36 * Represents the strategy of marshalling of requests and responses in and out
37 * of JMS messages
38 *
39 * @version $Revision: 1.5 $
40 */
41 public class DefaultMarshaller implements Marshaller {
42
43 private static final Log log = LogFactory.getLog(DefaultMarshaller.class);
44
45 private boolean ignoreInvalidMessages;
46
47 private String stickySessionID;
48
49 public Message createRequestMessage(Requestor requestor, LingoInvocation invocation) throws JMSException {
50 ObjectMessage message = requestor.getSession().createObjectMessage(invocation);
51 appendMessageHeaders(message, requestor, invocation);
52 return message;
53 }
54
55 public Message createResponseMessage(Session session, RemoteInvocationResult result, Message requestMessage) throws JMSException {
56 ObjectMessage answer = session.createObjectMessage(result);
57 addResponseMessageHeaders(answer, result, requestMessage);
58 return answer;
59 }
60
61 public RemoteInvocationResult extractInvocationResult(Message message) throws JMSException {
62 handleInvocationResultHeaders(message);
63 if (message instanceof ObjectMessage) {
64 ObjectMessage objectMessage = (ObjectMessage) message;
65 Object body = objectMessage.getObject();
66 if (body instanceof RemoteInvocationResult) {
67 return (RemoteInvocationResult) body;
68 }
69 }
70 return onInvalidClientMessage(message);
71 }
72
73 public RemoteInvocation readRemoteInvocation(Message message) throws JMSException {
74 handleInvocationHeaders(message);
75 if (message instanceof ObjectMessage) {
76 ObjectMessage objectMessage = (ObjectMessage) message;
77 Object body = objectMessage.getObject();
78 if (body instanceof RemoteInvocation) {
79 return (RemoteInvocation) body;
80 }
81 }
82 return onInvalidMessage(message);
83 }
84
85 public Message createObjectMessage(Session session, Object value) throws JMSException {
86 Message message = null;
87 if (value instanceof String) {
88 message = session.createTextMessage((String) value);
89 }
90 else {
91 message = session.createObjectMessage((Serializable) value);
92 }
93 appendMessageHeaders(message, session, value);
94 return message;
95 }
96
97 public Object readMessage(Message message) throws JMSException {
98 handleMessageHeaders(message);
99 if (message instanceof ObjectMessage) {
100 ObjectMessage objectMessage = (ObjectMessage) message;
101 return objectMessage.getObject();
102 }
103 else if (message instanceof TextMessage) {
104 TextMessage textMessage = (TextMessage) message;
105 return textMessage.getText();
106 }
107 return onInvalidMessage(message);
108 }
109
110
111
112 public boolean isIgnoreInvalidMessages() {
113 return ignoreInvalidMessages;
114 }
115
116 /***
117 * Sets whether invalidly formatted messages should be silently ignored or
118 * not
119 */
120 public void setIgnoreInvalidMessages(boolean ignoreInvalidMessages) {
121 this.ignoreInvalidMessages = ignoreInvalidMessages;
122 }
123
124
125
126 protected RemoteInvocationResult onInvalidClientMessage(Message message) throws JMSException {
127 throw new JMSException("Invalid response message: " + message);
128 }
129
130 /***
131 * Handle invalid messages by just logging, though a different
132 * implementation may wish to throw exceptions
133 */
134 protected RemoteInvocation onInvalidMessage(Message message) {
135 String text = "Invalid message will be discarded: " + message;
136 log.info(text);
137 if (!ignoreInvalidMessages) {
138 throw new RuntimeException(text);
139 }
140 return null;
141 }
142
143 /***
144 * A strategy method for derived classes to allow them a plugin point to
145 * perform custom header processing
146 */
147 protected void appendMessageHeaders(Message message, Requestor requestor, LingoInvocation invocation) throws JMSException {
148 if (invocation.getMetadata().isStateful()) {
149 message.setStringProperty("JMSXGroupID", getStickySessionID());
150 }
151 }
152
153 protected void appendMessageHeaders(Message message, Session session, Object value) {
154 }
155
156 protected String getStickySessionID() {
157 if (stickySessionID == null) {
158 stickySessionID = "hey";
159
160 throw new RuntimeException("TODO: Not Implemented Yet!");
161 }
162 return stickySessionID;
163 }
164
165 /***
166 * A strategy for derived classes to allow them to plug in custom header
167 * processing for responses
168 */
169 protected void addResponseMessageHeaders(ObjectMessage answer, RemoteInvocationResult result, Message requestMessage) throws JMSException {
170 }
171
172 /***
173 * A strategy method to allow derived classes to process the headers in a
174 * special way
175 */
176 protected void handleInvocationHeaders(Message message) {
177 }
178
179 /***
180 * A strategy method to allow derived classes to process the headers in a
181 * special way
182 */
183 protected void handleInvocationResultHeaders(Message message) {
184 }
185
186 /***
187 * A strategy method to allow derived classes to process the headers in a
188 * special way
189 */
190 protected void handleMessageHeaders(Message message) {
191 }
192
193 }