001: /**
002: *
003: * Licensed to the Apache Software Foundation (ASF) under one or more
004: * contributor license agreements. See the NOTICE file distributed with
005: * this work for additional information regarding copyright ownership.
006: * The ASF licenses this file to You under the Apache License, Version 2.0
007: * (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */package org.apache.openejb.core.mdb;
018:
019: import javax.jms.Connection;
020: import javax.jms.ConnectionFactory;
021: import javax.jms.JMSException;
022: import javax.jms.Message;
023: import javax.jms.MessageListener;
024: import javax.jms.MessageProducer;
025: import javax.jms.ObjectMessage;
026: import javax.jms.Session;
027: import java.io.Serializable;
028: import java.lang.reflect.InvocationTargetException;
029: import java.lang.reflect.Method;
030: import java.util.Map;
031: import java.util.TreeMap;
032:
033: public class MdbInvoker implements MessageListener {
034: private final Map<String, Method> signatures = new TreeMap<String, Method>();
035: private final Object target;
036: private Connection connection;
037: private Session session;
038: private ConnectionFactory connectionFactory;
039:
040: public MdbInvoker(ConnectionFactory connectionFactory, Object target)
041: throws JMSException {
042: this .target = target;
043: this .connectionFactory = connectionFactory;
044: for (Method method : target.getClass().getMethods()) {
045: String signature = MdbUtil.getSignature(method);
046: signatures.put(signature, method);
047: }
048: }
049:
050: public synchronized void destroy() {
051: MdbUtil.close(session);
052: session = null;
053: MdbUtil.close(connection);
054: connection = null;
055: }
056:
057: private synchronized Session getSession() throws JMSException {
058: connection = connectionFactory.createConnection();
059: connection.start();
060: session = connection.createSession(false,
061: Session.AUTO_ACKNOWLEDGE);
062: return session;
063: }
064:
065: public void onMessage(Message message) {
066: if (!(message instanceof ObjectMessage))
067: return;
068:
069: try {
070: Session session = getSession();
071: if (session == null)
072: throw new IllegalStateException(
073: "Invoker has been destroyed");
074:
075: if (message == null)
076: throw new NullPointerException(
077: "request message is null");
078: if (!(message instanceof ObjectMessage))
079: throw new IllegalArgumentException(
080: "Expected a ObjectMessage request but got a "
081: + message.getClass().getName());
082: ObjectMessage objectMessage = (ObjectMessage) message;
083: Serializable object = objectMessage.getObject();
084: if (object == null)
085: throw new NullPointerException(
086: "object in ObjectMessage is null");
087: if (!(object instanceof Map)) {
088: if (message instanceof ObjectMessage)
089: throw new IllegalArgumentException(
090: "Expected a Map contained in the ObjectMessage request but got a "
091: + object.getClass().getName());
092: }
093: Map request = (Map) object;
094:
095: String signature = (String) request.get("method");
096: Method method = signatures.get(signature);
097: Object[] args = (Object[]) request.get("args");
098:
099: boolean exception = false;
100: Object result = null;
101: try {
102: result = method.invoke(target, args);
103: } catch (IllegalAccessException e) {
104: result = e;
105: exception = true;
106: } catch (InvocationTargetException e) {
107: result = e.getCause();
108: if (result == null)
109: result = e;
110: exception = true;
111: }
112:
113: MessageProducer producer = null;
114: try {
115: // create response
116: Map<String, Object> response = new TreeMap<String, Object>();
117: if (exception) {
118: response.put("exception", "true");
119: }
120: response.put("return", result);
121:
122: // create response message
123: ObjectMessage resMessage = session
124: .createObjectMessage();
125: resMessage.setJMSCorrelationID(objectMessage
126: .getJMSCorrelationID());
127: resMessage.setObject((Serializable) response);
128:
129: // send response message
130: producer = session.createProducer(objectMessage
131: .getJMSReplyTo());
132: producer.send(resMessage);
133: } catch (Exception e) {
134: e.printStackTrace();
135: } finally {
136: MdbUtil.close(producer);
137: destroy();
138: }
139: } catch (Throwable e) {
140: e.printStackTrace();
141: }
142: }
143: }
|