View Javadoc
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 }