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 javax.jms.Connection;
20  import javax.jms.ConnectionFactory;
21  import javax.jms.JMSException;
22  import javax.jms.MessageProducer;
23  import javax.jms.Session;
24  import javax.jms.Topic;
25  
26  import org.forgerock.json.resource.InternalServerErrorException;
27  import org.forgerock.json.resource.ResourceException;
28  import org.forgerock.util.Reject;
29  import org.slf4j.Logger;
30  import org.slf4j.LoggerFactory;
31  
32  /**
33   * Manages the Connection to the JMS services and does the JNDI lookup for the JMS configuration settings.
34   */
35  class JmsResourceManager {
36      private static final Logger logger = LoggerFactory.getLogger(JmsResourceManager.class);
37  
38      private final ConnectionFactory connectionFactory;
39  
40      /**
41       * Delivery mode for the MessageProducer to use.
42       *
43       * @see MessageProducer#setDeliveryMode(int)
44       */
45      private final DeliveryModeConfig deliveryMode;
46  
47      /**
48       * Session acknowledgement mode for the Session to use.
49       * @see Connection#createSession(boolean, int)
50       */
51      private SessionModeConfig sessionMode;
52  
53      /**
54       * The Current JMS broker connection, if open.
55       */
56      private Connection connection;
57  
58      /**
59       * The JMS Topic used to publish the audit TextMessages.
60       */
61      private Topic topic;
62  
63      /**
64       * Given the configuration, this builds an JMS InitialContext. If usage of JNDI isn't desired, then both the
65       * connectionFactory and the jmsTopic need to be populated.
66       *
67       * @param configuration The Audit Configuration.
68       * @param jmsContextManager The {@link JmsContextManager}.
69       * @throws InternalServerErrorException
70       */
71      public JmsResourceManager(JmsAuditEventHandlerConfiguration configuration, JmsContextManager jmsContextManager)
72              throws ResourceException {
73  
74          Reject.ifNull(configuration.getDeliveryMode(), "JMS Delivery Mode is required");
75          Reject.ifNull(configuration.getSessionMode(), "JMS Session Mode is required");
76          sessionMode = configuration.getSessionMode();
77          deliveryMode = configuration.getDeliveryMode();
78  
79  
80          this.connectionFactory = jmsContextManager.getConnectionFactory();
81          this.topic = jmsContextManager.getTopic();
82          Reject.ifNull(this.connectionFactory, "Null ConnectionFactory is not permitted.");
83          Reject.ifNull(this.topic, "Null topic is not permitted.");
84  
85      }
86  
87      /**
88       * Opens the connection to the JMS services with the configured session mode.
89       * @throws JMSException
90       */
91      public void openConnection() throws JMSException {
92          connection = connectionFactory.createConnection();
93          connection.start();
94          logger.debug("JMS Connection created and started");
95      }
96  
97      /**
98       * Closes the connection to the JMS services.
99       *
100      * @throws JMSException
101      */
102     public void closeConnection() throws JMSException {
103         if (null != connection) {
104             try {
105                 connection.close();
106                 logger.debug("JMS Connection closed");
107             } finally {
108                 // Set to null too allow for early garbage collection, rather than waiting for next openConnection.
109                 connection = null;
110             }
111         }
112     }
113 
114     /**
115      * Creates and returns a jms session created from the connection with the sessionMode configured and without
116      * transaction management.
117      *
118      * @return a new session.
119      * @throws JMSException if trouble is encountered creating the session.
120      * @throws IllegalStateException if the connection hasn't been opened.
121      * @see Connection#createSession(boolean, int)
122      */
123     public Session createSession() throws JMSException {
124         if (null == connection) {
125             throw new IllegalStateException(
126                     "JMS Connection not available to create session. The JMS Audit Service requires a restart.");
127         }
128         return connection.createSession(false, sessionMode.getMode());
129     }
130 
131     /**
132      * Creates a producer from the passed in session using the configured JMS topic and deliveryMode.
133      *
134      * @param session the session to get the producer from.
135      * @return a new producer from the session with the destination set to the configured JMS topic.
136      * @throws JMSException if there is trouble creating the producer.
137      * @see Session#createProducer(javax.jms.Destination)
138      * @see MessageProducer#setDeliveryMode(int)
139      */
140     public MessageProducer createProducer(Session session) throws JMSException {
141         MessageProducer producer = session.createProducer(topic);
142         producer.setDeliveryMode(deliveryMode.getMode());
143         return producer;
144     }
145 }