1 /*
2 * The contents of this file are subject to the terms of the Common Development and
3 * Distribution License (the License). You may not use this file except in compliance with the
4 * License.
5 *
6 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
7 * specific language governing permission and limitations under the License.
8 *
9 * When distributing Covered Software, include this CDDL Header Notice in each file and include
10 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
11 * Header, with the fields enclosed by brackets [] replaced by your own identifying
12 * information: "Portions copyright [year] [name of copyright owner]".
13 *
14 * Copyright 2016 ForgeRock AS.
15 */
16
17 package org.forgerock.audit.handlers.jms;
18
19 import jakarta.jms.Connection;
20 import jakarta.jms.ConnectionFactory;
21 import jakarta.jms.JMSException;
22 import jakarta.jms.MessageProducer;
23 import jakarta.jms.Session;
24 import jakarta.jms.Topic;
25 import org.forgerock.json.resource.InternalServerErrorException;
26 import org.forgerock.json.resource.ResourceException;
27 import org.forgerock.util.Reject;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 /**
32 * Manages the Connection to the JMS services and does the JNDI lookup for the JMS configuration settings.
33 */
34 class JmsResourceManager {
35 private static final Logger logger = LoggerFactory.getLogger(JmsResourceManager.class);
36
37 private final ConnectionFactory connectionFactory;
38
39 /**
40 * Delivery mode for the MessageProducer to use.
41 *
42 * @see MessageProducer#setDeliveryMode(int)
43 */
44 private final DeliveryModeConfig deliveryMode;
45
46 /**
47 * Session acknowledgement mode for the Session to use.
48 * @see Connection#createSession(boolean, int)
49 */
50 private SessionModeConfig sessionMode;
51
52 /**
53 * The Current JMS broker connection, if open.
54 */
55 private Connection connection;
56
57 /**
58 * The JMS Topic used to publish the audit TextMessages.
59 */
60 private Topic topic;
61
62 /**
63 * Given the configuration, this builds an JMS InitialContext. If usage of JNDI isn't desired, then both the
64 * connectionFactory and the jmsTopic need to be populated.
65 *
66 * @param configuration The Audit Configuration.
67 * @param jmsContextManager The {@link JmsContextManager}.
68 * @throws InternalServerErrorException
69 */
70 public JmsResourceManager(JmsAuditEventHandlerConfiguration configuration, JmsContextManager jmsContextManager)
71 throws ResourceException {
72
73 Reject.ifNull(configuration.getDeliveryMode(), "JMS Delivery Mode is required");
74 Reject.ifNull(configuration.getSessionMode(), "JMS Session Mode is required");
75 sessionMode = configuration.getSessionMode();
76 deliveryMode = configuration.getDeliveryMode();
77
78
79 this.connectionFactory = jmsContextManager.getConnectionFactory();
80 this.topic = jmsContextManager.getTopic();
81 Reject.ifNull(this.connectionFactory, "Null ConnectionFactory is not permitted.");
82 Reject.ifNull(this.topic, "Null topic is not permitted.");
83
84 }
85
86 /**
87 * Opens the connection to the JMS services with the configured session mode.
88 * @throws JMSException
89 */
90 public void openConnection() throws JMSException {
91 connection = connectionFactory.createConnection();
92 connection.start();
93 logger.debug("JMS Connection created and started");
94 }
95
96 /**
97 * Closes the connection to the JMS services.
98 *
99 * @throws JMSException
100 */
101 public void closeConnection() throws JMSException {
102 if (null != connection) {
103 try {
104 connection.close();
105 logger.debug("JMS Connection closed");
106 } finally {
107 // Set to null too allow for early garbage collection, rather than waiting for next openConnection.
108 connection = null;
109 }
110 }
111 }
112
113 /**
114 * Creates and returns a jms session created from the connection with the sessionMode configured and without
115 * transaction management.
116 *
117 * @return a new session.
118 * @throws JMSException if trouble is encountered creating the session.
119 * @throws IllegalStateException if the connection hasn't been opened.
120 * @see Connection#createSession(boolean, int)
121 */
122 public Session createSession() throws JMSException {
123 if (null == connection) {
124 throw new IllegalStateException(
125 "JMS Connection not available to create session. The JMS Audit Service requires a restart.");
126 }
127 return connection.createSession(false, sessionMode.getMode());
128 }
129
130 /**
131 * Creates a producer from the passed in session using the configured JMS topic and deliveryMode.
132 *
133 * @param session the session to get the producer from.
134 * @return a new producer from the session with the destination set to the configured JMS topic.
135 * @throws JMSException if there is trouble creating the producer.
136 * @see Session#createProducer(jakarta.jms.Destination)
137 * @see MessageProducer#setDeliveryMode(int)
138 */
139 public MessageProducer createProducer(Session session) throws JMSException {
140 MessageProducer producer = session.createProducer(topic);
141 producer.setDeliveryMode(deliveryMode.getMode());
142 return producer;
143 }
144 }