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.Session;
23 import javax.jms.Topic;
24 import javax.jms.TopicConnection;
25 import javax.jms.TopicConnectionFactory;
26 import javax.jms.TopicPublisher;
27 import javax.jms.TopicSession;
28 import javax.naming.Context;
29 import javax.naming.NamingException;
30 import java.io.Serializable;
31
32
33
34
35 public class JMSTopicManager extends AbstractJMSManager {
36
37 private static final JMSTopicManagerFactory FACTORY = new JMSTopicManagerFactory();
38
39 private TopicInfo info;
40 private final String factoryBindingName;
41 private final String topicBindingName;
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 protected JMSTopicManager(final String name, final Context context, final String factoryBindingName,
56 final String topicBindingName, final String userName, final String password,
57 final TopicInfo info) {
58 super(name);
59 this.context = context;
60 this.factoryBindingName = factoryBindingName;
61 this.topicBindingName = topicBindingName;
62 this.userName = userName;
63 this.password = password;
64 this.info = info;
65 }
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81 public static JMSTopicManager getJMSTopicManager(final String factoryName, final String providerURL,
82 final String urlPkgPrefixes, final String securityPrincipalName,
83 final String securityCredentials, final String factoryBindingName,
84 final String topicBindingName, final String userName,
85 final String password) {
86
87 if (factoryBindingName == null) {
88 LOGGER.error("No factory name provided for JMSTopicManager");
89 return null;
90 }
91 if (topicBindingName == null) {
92 LOGGER.error("No topic name provided for JMSTopicManager");
93 return null;
94 }
95
96 final String name = "JMSTopic:" + factoryBindingName + '.' + topicBindingName;
97 return getManager(name, FACTORY, new FactoryData(factoryName, providerURL, urlPkgPrefixes,
98 securityPrincipalName, securityCredentials, factoryBindingName, topicBindingName, userName, password));
99 }
100
101
102 @Override
103 public void send(final Serializable object) throws Exception {
104 if (info == null) {
105 info = connect(context, factoryBindingName, topicBindingName, userName, password, false);
106 }
107 super.send(object, info.session, info.publisher);
108 try {
109 super.send(object, info.session, info.publisher);
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 topicBindingName;
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 topicBindingName,
158 final String userName, 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.topicBindingName = topicBindingName;
166 this.userName = userName;
167 this.password = password;
168 }
169 }
170
171 private static TopicInfo 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 TopicConnectionFactory factory = (TopicConnectionFactory) lookup(context, factoryBindingName);
176 TopicConnection conn;
177 if (userName != null) {
178 conn = factory.createTopicConnection(userName, password);
179 } else {
180 conn = factory.createTopicConnection();
181 }
182 final TopicSession sess = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
183 final Topic topic = (Topic) lookup(context, queueBindingName);
184 final TopicPublisher publisher = sess.createPublisher(topic);
185 conn.start();
186 return new TopicInfo(conn, sess, publisher);
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 TopicInfo {
203 private final TopicConnection conn;
204 private final TopicSession session;
205 private final TopicPublisher publisher;
206
207 public TopicInfo(final TopicConnection conn, final TopicSession session, final TopicPublisher publisher) {
208 this.conn = conn;
209 this.session = session;
210 this.publisher = publisher;
211 }
212 }
213
214
215
216
217 private static class JMSTopicManagerFactory implements ManagerFactory<JMSTopicManager, FactoryData> {
218
219 public JMSTopicManager createManager(final String name, final FactoryData data) {
220 try {
221 final Context ctx = createContext(data.factoryName, data.providerURL, data.urlPkgPrefixes,
222 data.securityPrincipalName, data.securityCredentials);
223 final TopicInfo info = connect(ctx, data.factoryBindingName, data.topicBindingName, data.userName,
224 data.password, true);
225 return new JMSTopicManager(name, ctx, data.factoryBindingName, data.topicBindingName,
226 data.userName, data.password, info);
227 } catch (final NamingException ex) {
228 LOGGER.error("Unable to locate resource", ex);
229 } catch (final Exception ex) {
230 LOGGER.error("Unable to connect", ex);
231 }
232
233 return null;
234 }
235 }
236 }