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 java.io.Serializable;
20 import javax.jms.JMSException;
21 import javax.jms.Session;
22 import javax.jms.Topic;
23 import javax.jms.TopicConnection;
24 import javax.jms.TopicConnectionFactory;
25 import javax.jms.TopicPublisher;
26 import javax.jms.TopicSession;
27 import javax.naming.Context;
28 import javax.naming.NamingException;
29
30 import org.apache.logging.log4j.core.appender.ManagerFactory;
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 try {
108 super.send(object, info.session, info.publisher);
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 topicBindingName;
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 topicBindingName,
157 final String userName, 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.topicBindingName = topicBindingName;
165 this.userName = userName;
166 this.password = password;
167 }
168 }
169
170 private static TopicInfo 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 TopicConnectionFactory factory = (TopicConnectionFactory) lookup(context, factoryBindingName);
175 TopicConnection conn;
176 if (userName != null) {
177 conn = factory.createTopicConnection(userName, password);
178 } else {
179 conn = factory.createTopicConnection();
180 }
181 final TopicSession sess = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
182 final Topic topic = (Topic) lookup(context, queueBindingName);
183 final TopicPublisher publisher = sess.createPublisher(topic);
184 conn.start();
185 return new TopicInfo(conn, sess, publisher);
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 TopicInfo {
202 private final TopicConnection conn;
203 private final TopicSession session;
204 private final TopicPublisher publisher;
205
206 public TopicInfo(final TopicConnection conn, final TopicSession session, final TopicPublisher publisher) {
207 this.conn = conn;
208 this.session = session;
209 this.publisher = publisher;
210 }
211 }
212
213
214
215
216 private static class JMSTopicManagerFactory implements ManagerFactory<JMSTopicManager, FactoryData> {
217
218 @Override
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 }