1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.net.jms;
18
19 import java.io.Serializable;
20
21 import javax.jms.JMSException;
22 import javax.jms.Queue;
23 import javax.jms.QueueConnection;
24 import javax.jms.QueueConnectionFactory;
25 import javax.jms.QueueSender;
26 import javax.jms.QueueSession;
27 import javax.jms.Session;
28 import javax.naming.Context;
29 import javax.naming.NamingException;
30
31 import org.apache.logging.log4j.core.appender.ManagerFactory;
32
33
34
35
36 public class JmsQueueManager extends AbstractJmsManager {
37
38 private static final JMSQueueManagerFactory FACTORY = new JMSQueueManagerFactory();
39
40 private QueueInfo info;
41 private final String factoryBindingName;
42 private final String queueBindingName;
43 private final String userName;
44 private final String password;
45 private final Context context;
46
47
48
49
50
51
52
53
54
55
56
57 protected JmsQueueManager(final String name, final Context context, final String factoryBindingName,
58 final String queueBindingName, final String userName, final String password,
59 final QueueInfo info) {
60 super(name);
61 this.context = context;
62 this.factoryBindingName = factoryBindingName;
63 this.queueBindingName = queueBindingName;
64 this.userName = userName;
65 this.password = password;
66 this.info = info;
67 }
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83 public static JmsQueueManager getJmsQueueManager(final String factoryName, final String providerURL,
84 final String urlPkgPrefixes, final String securityPrincipalName,
85 final String securityCredentials, final String factoryBindingName,
86 final String queueBindingName, final String userName,
87 final String password) {
88
89 if (factoryBindingName == null) {
90 LOGGER.error("No factory name provided for JmsQueueManager");
91 return null;
92 }
93 if (queueBindingName == null) {
94 LOGGER.error("No topic name provided for JmsQueueManager");
95 return null;
96 }
97
98 final String name = "JMSQueue:" + factoryBindingName + '.' + queueBindingName;
99 return getManager(name, FACTORY, new FactoryData(factoryName, providerURL, urlPkgPrefixes,
100 securityPrincipalName, securityCredentials, factoryBindingName, queueBindingName, userName, password));
101 }
102
103 @Override
104 public synchronized void send(final Serializable object) throws Exception {
105 if (info == null) {
106 info = connect(context, factoryBindingName, queueBindingName, userName, password, false);
107 }
108 try {
109 super.send(object, info.session, info.sender);
110 } catch (final Exception ex) {
111 cleanup(true);
112 throw ex;
113 }
114 }
115
116 @Override
117 public void releaseSub() {
118 if (info != null) {
119 cleanup(false);
120 }
121 }
122
123 private void cleanup(final boolean quiet) {
124 try {
125 info.session.close();
126 } catch (final Exception e) {
127 if (!quiet) {
128 LOGGER.error("Error closing session for " + getName(), e);
129 }
130 }
131 try {
132 info.conn.close();
133 } catch (final Exception e) {
134 if (!quiet) {
135 LOGGER.error("Error closing connection for " + getName(), e);
136 }
137 }
138 info = null;
139 }
140
141
142
143
144 private static class FactoryData {
145 private final String factoryName;
146 private final String providerURL;
147 private final String urlPkgPrefixes;
148 private final String securityPrincipalName;
149 private final String securityCredentials;
150 private final String factoryBindingName;
151 private final String queueBindingName;
152 private final String userName;
153 private final String password;
154
155 public FactoryData(final String factoryName, final String providerURL, final String urlPkgPrefixes,
156 final String securityPrincipalName, final String securityCredentials,
157 final String factoryBindingName, final String queueBindingName, final String userName,
158 final String password) {
159 this.factoryName = factoryName;
160 this.providerURL = providerURL;
161 this.urlPkgPrefixes = urlPkgPrefixes;
162 this.securityPrincipalName = securityPrincipalName;
163 this.securityCredentials = securityCredentials;
164 this.factoryBindingName = factoryBindingName;
165 this.queueBindingName = queueBindingName;
166 this.userName = userName;
167 this.password = password;
168 }
169 }
170
171 private static QueueInfo connect(final Context context, final String factoryBindingName,
172 final String queueBindingName, final String userName, final String password,
173 final boolean suppress) throws Exception {
174 try {
175 final QueueConnectionFactory factory = (QueueConnectionFactory) lookup(context, factoryBindingName);
176 QueueConnection conn;
177 if (userName != null) {
178 conn = factory.createQueueConnection(userName, password);
179 } else {
180 conn = factory.createQueueConnection();
181 }
182 final QueueSession sess = conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
183 final Queue queue = (Queue) lookup(context, queueBindingName);
184 final QueueSender sender = sess.createSender(queue);
185 conn.start();
186 return new QueueInfo(conn, sess, sender);
187 } catch (final NamingException ex) {
188 LOGGER.warn("Unable to locate connection factory " + factoryBindingName, ex);
189 if (!suppress) {
190 throw ex;
191 }
192 } catch (final JMSException ex) {
193 LOGGER.warn("Unable to create connection to queue " + queueBindingName, ex);
194 if (!suppress) {
195 throw ex;
196 }
197 }
198 return null;
199 }
200
201
202 private static class QueueInfo {
203 private final QueueConnection conn;
204 private final QueueSession session;
205 private final QueueSender sender;
206
207 public QueueInfo(final QueueConnection conn, final QueueSession session, final QueueSender sender) {
208 this.conn = conn;
209 this.session = session;
210 this.sender = sender;
211 }
212 }
213
214
215
216
217 private static class JMSQueueManagerFactory implements ManagerFactory<JmsQueueManager, FactoryData> {
218
219 @Override
220 public JmsQueueManager createManager(final String name, final FactoryData data) {
221 try {
222 final Context ctx = createContext(data.factoryName, data.providerURL, data.urlPkgPrefixes,
223 data.securityPrincipalName, data.securityCredentials);
224 final QueueInfo info = connect(ctx, data.factoryBindingName, data.queueBindingName, data.userName,
225 data.password, true);
226 return new JmsQueueManager(name, ctx, data.factoryBindingName, data.queueBindingName,
227 data.userName, data.password, info);
228 } catch (final NamingException ex) {
229 LOGGER.error("Unable to locate resource", ex);
230 } catch (final Exception ex) {
231 LOGGER.error("Unable to connect", ex);
232 }
233
234 return null;
235 }
236 }
237 }