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