├── .classpath
├── .gitignore
├── .project
├── .settings
├── org.eclipse.core.resources.prefs
├── org.eclipse.jdt.core.prefs
└── org.eclipse.m2e.core.prefs
├── LICENSE.txt
├── README.txt
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── mcafee
│ │ ├── AMQOps.java
│ │ ├── JmsAuthentication.java
│ │ ├── JmsDestination.java
│ │ ├── JmsDiggerException.java
│ │ ├── JmsDumpDestination.java
│ │ ├── JmsDurableSubscriberManipulator.java
│ │ ├── JmsHelper.java
│ │ ├── JmsInitialContextFactory.java
│ │ ├── JmsLoginInfo.java
│ │ ├── JmsMessageContentGenerator.java
│ │ ├── JmsMsgType.java
│ │ ├── JmsPasswordOps.java
│ │ ├── JmsWriter.java
│ │ ├── MessageCountUpdater.java
│ │ └── gui
│ │ ├── AmqOpsTab.java
│ │ ├── JMSDiggerAboutTab.java
│ │ ├── JmsAuthenticationTab.java
│ │ ├── JmsConfig.java
│ │ ├── JmsConfigTab.java
│ │ ├── JmsDiggerFrame.java
│ │ ├── JmsDumpDestinationTab.java
│ │ ├── JmsDurableSubscriberTab.java
│ │ ├── JmsGuiCommon.java
│ │ └── ProgressInfo.java
└── resources
│ ├── fs_icon_32.png
│ └── log4j.properties
└── test
└── java
└── com
└── mcafee
├── AMQOpsTest.java
├── FuzzAMQOps.java
├── IdGeneratorTest.java
├── JmsAuthenticationTest.java
├── JmsDumpDestinationTest.java
├── JmsDurableSubscriberManipulatorTest.java
├── JmsHelperTest.java
├── JmsInitialContextFactoryTest.java
├── JmsLoginInfoTest.java
└── JmsPasswordOpsTest.java
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | jmsdigger
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | net.sourceforge.metrics.builder
15 |
16 |
17 |
18 |
19 | org.eclipse.m2e.core.maven2Builder
20 |
21 |
22 |
23 |
24 |
25 | org.eclipse.jdt.core.javanature
26 | org.eclipse.m2e.core.maven2Nature
27 | net.sourceforge.metrics.nature
28 |
29 |
30 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.core.resources.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | encoding//src/main/java=UTF-8
3 | encoding//src/main/resources=UTF-8
4 | encoding//src/test/java=UTF-8
5 | encoding/=UTF-8
6 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
3 | org.eclipse.jdt.core.compiler.compliance=1.5
4 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
5 | org.eclipse.jdt.core.compiler.source=1.5
6 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.m2e.core.prefs:
--------------------------------------------------------------------------------
1 | activeProfiles=
2 | eclipse.preferences.version=1
3 | resolveWorkspaceProjects=true
4 | version=1
5 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
204 | ========================================
205 | Copyright (c) 2013, Gursev Singh Kalra (McAfee, Inc - Foundstone Professional Services)
206 | All rights reserved.
207 |
208 | Redistribution and use in source and binary forms, with or without
209 | modification, are permitted provided that the following conditions are
210 | met:
211 |
212 | * Redistributions of source code must retain the above copyright
213 | notice, this list of conditions and the following disclaimer.
214 | * Redistributions in binary form must reproduce the above
215 | copyright notice, this list of conditions and the following
216 | disclaimer in the documentation and/or other materials provided
217 | with the distribution.
218 | * Neither the name of the Gursev Singh Kalra nor the names of its
219 | contributors may be used to endorse or promote products derived
220 | from this software without specific prior written permission.
221 |
222 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
223 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
224 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
225 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
226 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
227 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
228 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
229 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
230 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
231 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
232 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/README.txt:
--------------------------------------------------------------------------------
1 | JMSDigger is an Enterprise Messaging Application assessment tool.
2 | The current release primarily focuses on ActiveMQ.
3 |
4 | Copyright (c) 2014, Gursev Singh Kalra - gursev.kalra@foundstone.com
5 | (McAfee, Inc - Foundstone Professional Services)
6 |
7 | Licensing
8 | =======================================================================
9 | JMSDigger license information is available in the file named "LICENSE.txt"
10 | in this directory. The license applies to all source code and resources
11 | contained in the JMSDigger tool.
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | com.mcafee
6 | jmsdigger
7 | 0.1.1.0-SNAPSHOT
8 | jar
9 |
10 | jmsdigger
11 | https://github.com/OpenSecurityResearch/jmsdigger
12 |
13 |
14 | UTF-8
15 |
16 |
17 |
18 |
19 | org.apache.activemq
20 | activemq-all
21 | 5.6.0
22 |
23 |
24 | junit
25 | junit
26 | 4.11
27 | test
28 |
29 |
30 | org.apache.directory.studio
31 | org.apache.commons.codec
32 | 1.6
33 |
34 |
35 |
36 | org.slf4j
37 | slf4j-api
38 | 1.7.2
39 |
40 |
41 | org.jasypt
42 | jasypt
43 | 1.9.0
44 |
45 |
46 | xstream
47 | xstream
48 | 1.2.2
49 |
50 |
51 | commons-lang
52 | commons-lang
53 | 20030203.000129
54 |
55 |
56 |
57 |
58 |
59 | org.apache.maven.plugins
60 | maven-jar-plugin
61 | 2.2
62 |
63 |
64 |
65 | org.apache.maven.plugins
66 | maven-assembly-plugin
67 | 2.2-beta-4
68 |
69 |
70 | jar-with-dependencies
71 |
72 |
73 |
74 | com.mcafee.gui.JmsDiggerFrame
75 |
76 |
77 |
78 |
79 |
80 | package
81 |
82 | single
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | McAfee, Inc.
91 |
92 |
93 | Gursev Singh Kalra
94 |
95 | JMSDigger is JMS API based Enterprise Messaging Application assessment tool.
96 |
97 |
--------------------------------------------------------------------------------
/src/main/java/com/mcafee/AMQOps.java:
--------------------------------------------------------------------------------
1 | package com.mcafee;
2 |
3 | import java.util.ArrayList;
4 |
5 | import javax.jms.Connection;
6 | import javax.jms.Destination;
7 | import javax.jms.JMSException;
8 | import javax.jms.MapMessage;
9 | import javax.jms.Message;
10 | import javax.jms.MessageConsumer;
11 | import javax.jms.MessageProducer;
12 | import javax.jms.Queue;
13 | import javax.jms.Session;
14 | import javax.jms.Topic;
15 | import javax.naming.InitialContext;
16 | import org.slf4j.Logger;
17 | import org.slf4j.LoggerFactory;
18 |
19 |
20 | /**
21 | * Based on explanation and code example from ActiveMQ tutorials hosted at
22 | * http://activemq.apache.org/statisticsplugin.html
23 | * @author Gursev Singh Kalra @ McAfee, Inc.
24 | */
25 | public class AMQOps {
26 | private static final Logger LOG = LoggerFactory.getLogger(AMQOps.class);
27 | private static final int TIMEOUT = 1000; // Time to wait for the Queue or Topic status to return since the query is typically blocking.
28 | private InitialContext ctx;
29 | private JmsLoginInfo loginInfo;
30 | private String cfName;
31 | ArrayList dstStats = new ArrayList();
32 | private Connection connection; // Connection to the broker to last for the entire querying cycle
33 | private Session session; // Session created for the connection. This may or may not change between different request
34 | private Queue replyToQueue; // to connect status responses
35 | private Message message; // message to be sent and initialized during init call
36 | private MessageConsumer messageConsumer; // To consumer receive incoming messages containing stats
37 | private MessageProducer messageProducer; // To send messages to the destination
38 | private boolean statsGenerated = false;
39 |
40 |
41 | boolean initialized = false;
42 |
43 | public AMQOps(InitialContext ctx, String connFactName, JmsLoginInfo loginInfo) {
44 | this.ctx = ctx;
45 | this.loginInfo = loginInfo;
46 | this.cfName = connFactName;
47 | }
48 |
49 | public AMQOps(InitialContext ctx, String connFactName) {
50 | this(ctx, connFactName, null);
51 | }
52 |
53 | /**
54 | * The init method initializes the object so it can be later used. It performs following actions
55 | * 1. Creates a new connection and corresponding session
56 | * 2. Creates a temporary queue to receive user response
57 | * 3. Sets a message Consumer
58 | * 4. Sets the message JMSReplyTo header to the temporary queue
59 | * 5. Starts the connection and sets the initialized instance variable to true
60 | * @throws JmsDiggerException
61 | */
62 | public void init() throws JmsDiggerException {
63 | LOG.debug("Entering init");
64 | if(ctx == null || JmsHelper.isStringNullOrEmpty(cfName))
65 | throw JmsHelper.buildJmsDiggerException("Null value for InitialContext or Connection Factory Name");
66 |
67 | connection = JmsHelper.createConnection(ctx, cfName, loginInfo);
68 |
69 | try {
70 | session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
71 | replyToQueue = session.createTemporaryQueue();
72 | messageConsumer = session.createConsumer(replyToQueue);
73 | message = session.createMessage();
74 | message.setJMSReplyTo(replyToQueue);
75 | messageProducer = session.createProducer(null);
76 | connection.start();
77 | } catch (JMSException ex) {
78 | LOG.info("Error occured while initializing AMQStats", ex);
79 | throw JmsHelper.buildJmsDiggerException("Error occured while initializing AMQStats", ex);
80 | }
81 |
82 | initialized = true;
83 | LOG.debug("Leaving init");
84 | }
85 |
86 | /**
87 | * This method returns the obtained statistics as String.
88 | * @return String
89 | * @throws JmsDiggerException
90 | */
91 | public String getStatsAsString() throws JmsDiggerException {
92 | if(!initialized)
93 | throw new IllegalArgumentException("No stats available");
94 |
95 | if(!statsGenerated)
96 | throw new IllegalStateException("No stats available");
97 |
98 | StringBuilder sb = new StringBuilder();
99 | sb.append("");
100 | for(MapMessage mm : dstStats) {
101 | sb.append(JmsHelper.mapMessageToString(mm));
102 | sb.append("\n=================================\n\n");
103 | }
104 | return sb.toString();
105 | }
106 |
107 | /**
108 | * Returns statistics of an ActiveMQ broker
109 | * @return ArrayList
110 | * @throws JmsDiggerException
111 | */
112 | public ArrayList getBrokerStats() throws JmsDiggerException {
113 | return getDestinationStats("ActiveMQ.Statistics.Broker", false, true);
114 | }
115 |
116 | /**
117 | * Returns statistics of a Subscription
118 | * @return ArrayList
119 | * @throws JmsDiggerException
120 | */
121 | public ArrayList getSubscriptionsStats() throws JmsDiggerException {
122 | return getDestinationStats("ActiveMQ.Statistics.Subscription", false, true);
123 |
124 | }
125 |
126 | /**
127 | * Returns status of Queue with given name. It optionally allows
128 | * you to query Queue status with or without ActiveMQ.Statistics.Destination prefix to the name
129 | *
130 | * @param qName Queue name
131 | * @param prepend - Prepends ActiveMQ.Statistics.Destination. to the Queue name if true, else the qName is queried raw
132 | * @return ArrayList
133 | * @throws JmsDiggerException
134 | */
135 |
136 | public ArrayList getQueueStats(String qName, boolean prepend) throws JmsDiggerException {
137 | return getDestinationStats(qName, prepend, true);
138 | }
139 |
140 | /**
141 | * Returns status of Topic with given name. It optionally allows
142 | * you to query Topic status with or without ActiveMQ.Statistics.Destination.
143 | *
144 | * @param tName - Topic name
145 | * @param prepend - Prepends ActiveMQ.Statistics.Destination. to the topic name if true, else the tName is queried raw
146 | * @return ArrayList
147 | * @throws JmsDiggerException
148 | */
149 |
150 | public ArrayList getTopicStats(String tName, boolean prepend) throws JmsDiggerException {
151 | return getDestinationStats(tName, prepend, false);
152 | }
153 |
154 | /**
155 | * This is the main (private) method to query the status and return to the caller.
156 | * @param qName - Queue Name
157 | * @param prepend - Boolean value that decides if ActiveMQ.Statistics.Destination. should be prepended to the qName
158 | * @param isQueue - the destination is a Queue if true, else it is a Topic
159 | * @return - ArrayList
160 | * @throws JmsDiggerException
161 | */
162 | private ArrayList getDestinationStats(String qName, boolean prepend, boolean isQueue) throws JmsDiggerException {
163 |
164 | statsGenerated = false; // set to false before every attempt to get status
165 | if(qName == null)
166 | throw new IllegalArgumentException("null Destination name passed to getDestinationStats");
167 |
168 | assertInitialization();
169 |
170 | if(prepend)
171 | qName = "ActiveMQ.Statistics.Destination." + qName;
172 |
173 | dstStats = new ArrayList();
174 |
175 | try {
176 | if(isQueue) {
177 | Queue queue = session.createQueue(qName);
178 | messageProducer.send(queue, message);
179 | } else {
180 | Topic topic = session.createTopic(qName);
181 | messageProducer.send(topic, message);
182 | }
183 | MapMessage stats;
184 | while((stats = (MapMessage) messageConsumer.receive(TIMEOUT)) != null) {
185 | dstStats.add(stats);
186 | }
187 | statsGenerated = true;
188 | return dstStats;
189 | } catch (JmsDiggerException ex) {
190 | throw ex;
191 | } catch (JMSException ex) {
192 | LOG.info("An error occured in getDestinationStats", ex);
193 | throw JmsHelper.buildJmsDiggerException("An error occured in getDestinationStats", ex);
194 | }
195 | }
196 |
197 | public void assertInitialization() {
198 | if(!initialized)
199 | throw new IllegalArgumentException(this.getClass().getName().toString() + "'s object is not initialized");
200 | }
201 |
202 | /**
203 | * Main method to create a Queue or Topic on the target ActiveMQ broker
204 | * @param dstName - Name of the destination
205 | * @param isQueue - Boolean value indicating that the destination is a Queue (when true) or a Topic (when false)
206 | * @return - Destination object
207 | * @throws JmsDiggerException
208 | */
209 |
210 | private Destination createDestination(String dstName, boolean isQueue) throws JmsDiggerException {
211 | if(JmsHelper.isStringNullOrEmpty(dstName))
212 | throw JmsHelper.buildJmsDiggerException("Invalid destination name parameter");
213 |
214 | assertInitialization();
215 |
216 | try {
217 | if(isQueue) {
218 | Queue q = session.createQueue(dstName);
219 | messageProducer.send(q, message);
220 | return q;
221 | } else {
222 | Topic t = session.createTopic(dstName);
223 | messageProducer.send(t, message);
224 | return t;
225 | }
226 | } catch (JMSException ex) {
227 | LOG.info("Destination " + dstName + " could not be created", ex);
228 | throw JmsHelper.buildJmsDiggerException("Destination " + dstName + " could not be created", ex);
229 | }
230 | }
231 |
232 | /**
233 | * Creates a Queue on ActiveMQ broker
234 | * @param queueName - Name of the queue
235 | * @return - Queue object
236 | * @throws JmsDiggerException
237 | */
238 |
239 | public Queue createQueue(String queueName) throws JmsDiggerException {
240 | return (Queue) createDestination(queueName, true);
241 | }
242 |
243 | /**
244 | * Creates a Topic on ActiveMQ broker
245 | * @param topicName - Name of the topic
246 | * @return - Topic object
247 | * @throws JmsDiggerException
248 | */
249 | public Topic createTopic(String topicName) throws JmsDiggerException {
250 | return (Topic) createDestination(topicName, false);
251 | }
252 |
253 | public void close() {
254 | try {
255 | messageProducer.close();
256 | messageConsumer.close();
257 | session.close();
258 | connection.close();
259 | } catch (JMSException e) {
260 | LOG.info("AMQOps done failed");
261 | }
262 |
263 | }
264 |
265 | }
266 |
--------------------------------------------------------------------------------
/src/main/java/com/mcafee/JmsAuthentication.java:
--------------------------------------------------------------------------------
1 | package com.mcafee;
2 |
3 | import javax.jms.Connection;
4 | import javax.jms.ConnectionFactory;
5 | import javax.jms.JMSException;
6 | import javax.naming.InitialContext;
7 |
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 |
11 | /**
12 | * This class allows you to check if a Messaging broker supports
13 | * anonymous authentication and also helps validated user credentials
14 | * @author Gursev Singh Kalra @ McAfee, Inc.
15 | *
16 | */
17 | public class JmsAuthentication {
18 | private static final Logger LOG = LoggerFactory.getLogger(JmsAuthentication.class);
19 | private InitialContext initialContext;
20 | private String cfName; //Connection Factory Name
21 | private JMSException exception;
22 |
23 | public JMSException getException() {
24 | return exception;
25 | }
26 |
27 | public JmsAuthentication(InitialContext initialContext, String cfName) throws JmsDiggerException {
28 | if(initialContext == null)
29 | throw new JmsDiggerException("InitialContext was null");
30 | this.initialContext = initialContext;
31 | this.cfName = cfName;
32 | }
33 |
34 | /**
35 | * Checks if the provided loginInfo (username/password) is valid.
36 | * IMPORTANT: When anonymous authentication is enabled, any username and password combination allows
37 | * access.
38 | * @param loginInfo
39 | * @return boolean
40 | * @throws JMSException
41 | */
42 | public boolean isLoginInfoValid(JmsLoginInfo loginInfo) throws JmsDiggerException
43 | {
44 | LOG.debug("Entering isLoginInfoValid method");
45 | return chkAuthBool(loginInfo);
46 | }
47 |
48 |
49 | /**
50 | * Checks if the initialContext allows anonymous authentication
51 | * @return boolean
52 | * @throws JMSException
53 | */
54 | public boolean isAnonymousAuthAlowed() throws JmsDiggerException
55 | {
56 | LOG.debug("Entering isAnonymousAuthAlowed method");
57 | return chkAuthBool(null);
58 | }
59 |
60 | /**
61 | * This is the main method that performs all the lifting and validates user credentials or the
62 | * anonymous authentication support. The return value is true or false.
63 | * @param loginInfo
64 | * @return boolean
65 | * @throws JmsDiggerException
66 | */
67 | private boolean chkAuthBool(JmsLoginInfo loginInfo) throws JmsDiggerException
68 | {
69 | LOG.debug("Entering chkAuth method");
70 | boolean authStatus = false;
71 | ConnectionFactory connFact = null;
72 | Connection conn = null;
73 |
74 | connFact = JmsHelper.getConnectionFactory(initialContext, cfName);
75 | //ConnectionFactory cf = jConnFact.getConnectionFactory(cfName, result)
76 |
77 | try
78 | {
79 | if(loginInfo == null)
80 | {
81 | //Attempt an anonymous connection
82 | conn = connFact.createConnection();
83 | }
84 | else
85 | {
86 | //Attempt an connection with username and password
87 | conn = connFact.createConnection(loginInfo.getUsername(), loginInfo.getPassword());
88 | }
89 | conn.start();
90 | // It was also observed that JMSSecurityException was not thrown as suggested by the API documentation.
91 | // But, JMSException was thrown (generated by java.lang.SecurityException).
92 | authStatus = true;
93 | }
94 | catch(JMSException ex) // JmsSecurityException inherits from JmsException.
95 | {
96 | exception = ex;
97 | if(loginInfo == null)
98 | LOG.info("Anonymous authentication was rejected", ex);
99 | else
100 | LOG.info("Invalid " + loginInfo, ex);
101 | authStatus = false;
102 | }
103 | finally
104 | {
105 | if(conn != null)
106 | {
107 | try{
108 | conn.close();
109 | }
110 | catch(JMSException ex){
111 | LOG.debug("Connection could not be closed", ex);
112 | }
113 | }
114 | }
115 |
116 | LOG.debug("Leaving chkAuth method");
117 | return authStatus;
118 | }
119 |
120 | }
121 |
--------------------------------------------------------------------------------
/src/main/java/com/mcafee/JmsDestination.java:
--------------------------------------------------------------------------------
1 | package com.mcafee;
2 |
3 | /**
4 | * Defines the type of JMS destination
5 | * @author Gursev Singh Kalra @ McAfee, Inc.
6 | *
7 | */
8 | public enum JmsDestination {
9 | QUEUE,
10 | TOPIC,
11 | CONNECTIONFACTORY,
12 | DURABLESUBSCRIBER,
13 | BROKER,
14 | SUBSCRIPTION
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/mcafee/JmsDiggerException.java:
--------------------------------------------------------------------------------
1 | package com.mcafee;
2 |
3 | import javax.jms.JMSException;
4 |
5 | /**
6 | * This is the main exception class for the JMSDigger Tool
7 | * @author Gursev Singh Kalra @ McAfee, Inc.
8 | *
9 | */
10 | public class JmsDiggerException extends JMSException {
11 |
12 | private static final long serialVersionUID = 1L;
13 |
14 | public JmsDiggerException(String msg) {
15 | super(msg);
16 | }
17 |
18 | public JmsDiggerException(String msg, String errCode) {
19 | super(msg, errCode);
20 | }
21 |
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/mcafee/JmsDumpDestination.java:
--------------------------------------------------------------------------------
1 | package com.mcafee;
2 |
3 | import java.io.FileNotFoundException;
4 | import java.io.IOException;
5 | import java.util.Enumeration;
6 |
7 | import javax.jms.Connection;
8 | import javax.jms.ConnectionFactory;
9 | import javax.jms.Destination;
10 | import javax.jms.InvalidSelectorException;
11 | import javax.jms.JMSException;
12 | import javax.jms.Message;
13 | import javax.jms.MessageListener;
14 | import javax.jms.Queue;
15 | import javax.jms.QueueBrowser;
16 | import javax.jms.QueueSession;
17 | import javax.jms.Session;
18 | import javax.jms.Topic;
19 | import javax.jms.TopicSession;
20 | import javax.jms.TopicSubscriber;
21 | import javax.naming.InitialContext;
22 | import javax.naming.NamingException;
23 |
24 | import org.slf4j.Logger;
25 | import org.slf4j.LoggerFactory;
26 |
27 | /**
28 | * This class writes the contents of a JMS destination (Queue, Topic and DurableSubscribers) \
29 | * to the local file system using the JMSWriter object.
30 | * @author Gursev Singh Kalra @ McAfee, Inc.
31 | *
32 | */
33 |
34 | public class JmsDumpDestination implements MessageListener {
35 | private static final Logger LOG = LoggerFactory.getLogger(JmsDumpDestination.class);
36 | private static String filenameIdentifier = "qDump";
37 | private static final int TIMEOUT = 2000; // 2 second timeout for synchronously receiving messages
38 |
39 | private int msgCountToDump = 0;
40 | private JmsLoginInfo loginInfo;
41 | private boolean initialized;
42 | private JmsDestination dstType;
43 |
44 | private JmsWriter jmsWriter;
45 | private InitialContext ctx;
46 |
47 | private String msgSelector;
48 | private String dstName;
49 | private String targetDirectory;
50 |
51 | private ConnectionFactory connFact;
52 | private String connFactName;
53 | private Connection connection;
54 | private Destination dst;
55 | private int msgsWritten = 0;
56 | private int msgsTraversed = 0;
57 | private boolean dumpComplete;
58 |
59 | // For durable subscriber dumps
60 | private String durableSubscriberName;
61 | private String clientId;
62 | private MessageCountUpdater messageCountUpdater;
63 |
64 | /**
65 | * Main constructor the initialize the JMS Destination dumps
66 | * @param ctx - Initial Context
67 | * @param dstName - Destination name
68 | * @param connFactName - Name of the connection factory
69 | * @param msgSelector - Message selector
70 | * @param loginInfo - Login Info
71 | */
72 | public JmsDumpDestination(InitialContext ctx, String dstName, String connFactName, String msgSelector, JmsLoginInfo loginInfo)
73 | {
74 | if(ctx == null || dstName == null || connFactName == null)
75 | throw new IllegalArgumentException("Unexpected null object passed to JmsDumpQueue constructor");
76 | this.ctx = ctx;
77 | this.dstName = dstName;
78 | this.msgSelector = msgSelector;
79 | this.connFactName = connFactName;
80 | this.loginInfo = loginInfo;
81 | this.initialized = false;
82 | this.dumpComplete = false;
83 | }
84 |
85 | public void setTargetDirectory(String targetDirectory) {
86 | this.targetDirectory = targetDirectory;
87 | }
88 |
89 | public boolean isDumpComplete() {
90 | return this.dumpComplete;
91 | }
92 |
93 | public void setMessageCountUpdater(MessageCountUpdater messageCountUpdater) {
94 | this.messageCountUpdater = messageCountUpdater;
95 | }
96 | /**
97 | * Initialize JMS destination dump with anonymous authentication and no message selector
98 | * @param ctx - Initial Context
99 | * @param dstName - Destination name
100 | * @param connFactName - Connection factory name
101 | * @throws NamingException
102 | * @throws JMSException
103 | */
104 | public JmsDumpDestination(InitialContext ctx, String dstName, String connFactName)
105 | {
106 | this(ctx, dstName, connFactName, null, null);
107 | }
108 |
109 | /**
110 | * Initialize JMS destination dump with anonymous authentication and a message selector
111 | * @param ctx
112 | * @param dstName
113 | * @param connFactName
114 | * @param msgSelector
115 | */
116 | public JmsDumpDestination(InitialContext ctx, String dstName, String connFactName, String msgSelector)
117 | {
118 | this(ctx, dstName, connFactName, msgSelector, null);
119 | }
120 |
121 | /**
122 | * Set only when you want your client to use a client Id. The value cannot be null.
123 | * @param clientId
124 | */
125 | public void setClientId(String clientId) {
126 | if(clientId == null) {
127 | LOG.info("Null client ID provided");
128 | throw new IllegalArgumentException("Null client ID provided");
129 | }
130 | this.clientId = clientId;
131 | }
132 |
133 |
134 | /**
135 | * Set only when you want to dump a durable subscriber. Both clientID and Durable subscriber name must
136 | * be set for the durable subscriber dump functionality to work. If not, an exception will be thrown
137 | * during the initialization phased with init.
138 | * @param durableSubscriberName
139 | */
140 | public void setDurableSubscriberName(String durableSubscriberName) {
141 | if(durableSubscriberName == null) {
142 | LOG.info("Null durable subscriber name provided provided");
143 | throw new IllegalArgumentException("Null durable subscriber name provided");
144 | }
145 | this.durableSubscriberName = durableSubscriberName;
146 | }
147 |
148 |
149 |
150 |
151 | /**
152 | * The init method initiates three types of processing
153 | * 1. Queue Dump - Via Queue Browsers
154 | * 2. Topic Dumps
155 | * 3. Durable Subscriber Dumps
156 | *
157 | * For a Topic, the algorithm to choose a destination when dst is a Topic instance
158 | * is as follows based on "clientId" and "durableSubscriberName" values
159 | *
160 | *
161 | * -------------------------------------------------------------
162 | * clientId | durableSubscriberName | LookFor |
163 | * -------------------------------------------------------------
164 | * null/empty | null/empty | Topic |
165 | * null/empty | value | Throw Error |
166 | * value | null/empty | Topic |
167 | * value | value | Dump Durable Subscriber |
168 | * --------------------------------------------------------------
169 | */
170 |
171 | public void init() throws JmsDiggerException {
172 | LOG.debug("Entering init method");
173 | try {
174 | dst = (Destination) ctx.lookup(dstName);
175 |
176 | if(dst == null)
177 | throw new IllegalArgumentException(dstName + " not found in JNDI");
178 |
179 | if(dst instanceof Queue) {
180 | dstType = JmsDestination.QUEUE;
181 | filenameIdentifier = "queue-" + dstName;
182 | }
183 | else {
184 | if(dst instanceof Topic) {
185 | if(JmsHelper.isStringNullOrEmpty(durableSubscriberName)) {
186 | dstType = JmsDestination.TOPIC;
187 | filenameIdentifier = "topic-" + dstName;
188 | } else {
189 | if(JmsHelper.isStringNullOrEmpty(clientId)) {
190 | LOG.info("clientId cannot be null when durableSubscriberName has a value");
191 | throw new IllegalArgumentException("clientId cannot be null when durableSubscriberName has a value");
192 | } else {
193 | dstType = JmsDestination.DURABLESUBSCRIBER;
194 | filenameIdentifier = "durableSubscriber-" + dstName;
195 | }
196 | }
197 | } else {
198 | throw new IllegalArgumentException(dstName + " is neither a Queue nor a Topic");
199 | }
200 | }
201 |
202 | connFact = (ConnectionFactory) ctx.lookup(this.connFactName);
203 |
204 | jmsWriter = new JmsWriter(targetDirectory, filenameIdentifier);
205 | if(loginInfo == null)
206 | connection = (Connection) connFact.createConnection();
207 | else
208 | connection = (Connection) connFact.createConnection(loginInfo.getUsername(), loginInfo.getPassword());
209 |
210 | // Set clientId - This is very important for durable subscriber identification
211 | if(clientId != null)
212 | connection.setClientID(clientId);
213 | } catch (JmsDiggerException e) {
214 | throw e;
215 | } catch (NamingException e) {
216 | LOG.info("Either a Queue or Destination name not found", e);
217 | throw JmsHelper.buildJmsDiggerException("Either a Queue or Destination name not found", e);
218 | } catch (JMSException e) {
219 | LOG.info("Could not create a connection", e);
220 | throw JmsHelper.buildJmsDiggerException("Could not create a connection", e);
221 | }
222 |
223 | msgsWritten = 0;
224 | initialized = true;
225 | LOG.debug("Leaving init method");
226 |
227 | }
228 |
229 | /**
230 | * Initializes the number of messages that objects of this class will
231 | * attempt to dump to the local filesystem. If value of count paramter is
232 | * less than 0, the value is left unchanged.
233 | * @param count
234 | */
235 | public void setMsgCountToDump(int count) {
236 | LOG.debug("Entering setMsgCountToDump method");
237 | if(count >= 0)
238 | msgCountToDump = count;
239 | LOG.debug("Leaving setMsgCountToDump method");
240 |
241 | }
242 |
243 | public int getMsgsWritten() {
244 | return msgsWritten;
245 | }
246 |
247 | /**
248 | * Dumps contents of a Queue. Creates a QueueBrowser, gets the enumeration and writes messages.
249 | * @throws FileNotFoundException
250 | * @throws IOException
251 | * @throws JmsDiggerException
252 | * @throws InterruptedException
253 | */
254 | private void initQueueDump() throws FileNotFoundException, IOException, JmsDiggerException, InterruptedException {
255 | LOG.debug("Entering initQueueDump method");
256 |
257 | QueueSession qSession = null;
258 | QueueBrowser qBrowser = null;
259 | Enumeration qEnum = null;
260 | jmsWriter.init();
261 |
262 | try {
263 | qSession = (QueueSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
264 | if(msgSelector == null)
265 | qBrowser = qSession.createBrowser((Queue)dst);
266 | else
267 | qBrowser = qSession.createBrowser((Queue)dst, msgSelector);
268 | connection.start();
269 | boolean breakout = false;
270 | while(msgsTraversed <= msgCountToDump || msgCountToDump == 0) {
271 | qEnum = qBrowser.getEnumeration();
272 | if(!qEnum.hasMoreElements()) {
273 | Thread.sleep(2 * 1000); // Wait and try to get more elements
274 | continue;
275 | }
276 | Message msg = null;
277 | while(qEnum.hasMoreElements()) {
278 | msg = (Message) qEnum.nextElement();
279 | try {
280 | jmsWriter.writeMsg(msg);
281 | msgsWritten++;
282 |
283 | /**
284 | * Update the count in GUI
285 | */
286 | if(messageCountUpdater != null) {
287 | messageCountUpdater.setCount(msgsWritten);
288 | Thread t = new Thread(messageCountUpdater);
289 | t.start();
290 | }
291 | } catch(JmsDiggerException ex) {
292 | //Swallow exceptions for failed write messages
293 | }
294 | msgsTraversed++;
295 | if(msgsTraversed >= msgCountToDump && msgCountToDump != 0) {
296 | breakout = true; // never break out when msgCountToDump is 0
297 | dumpComplete = true;
298 | break; // break from inner while loop
299 | }
300 | }
301 | if(breakout)
302 | break; // break from outer while loop
303 | }
304 | } catch (InvalidSelectorException ex) {
305 | LOG.info("Message selector exception encountered", ex);
306 | throw JmsHelper.buildJmsDiggerException("Message selector exception encountered", ex);
307 | } catch (JMSException ex) {
308 | LOG.info("A JMSException occured while creating a QueueBrowser", ex);
309 | throw JmsHelper.buildJmsDiggerException("A JMSException occured while creating a QueueBrowser", ex);
310 | }
311 |
312 |
313 |
314 | try {
315 | qBrowser.close();
316 | qSession.close();
317 | } catch (JMSException e) {
318 | LOG.info("qBroswer or qSession close failed ", e);
319 | //Swallow the exception on close.
320 | }
321 |
322 | if(msgsTraversed > msgsWritten) {
323 | LOG.info("Messages Traversed " + msgsTraversed, ", Messages Written: " + msgsWritten);
324 | throw JmsHelper.buildJmsDiggerException("Not all messages were written. Check log for more details");
325 | }
326 | LOG.debug("Leaving initQueueDump method");
327 | }
328 |
329 |
330 | /**
331 | * Write one message at a time. The object of this class is set as a message listener for Topics
332 | * Every message is received by this method is in turn written unless the number of messages
333 | * written exceeds the target.
334 | */
335 | public void onMessage(Message msg){
336 | LOG.debug("Entering onMessage method");
337 | if(msgCountToDump == 0 || msgsTraversed < msgCountToDump) {
338 | msgsTraversed++;
339 | try {
340 | jmsWriter.writeMsg(msg);
341 | msgsWritten++;
342 | /**
343 | * Update the count in GUI
344 | */
345 | if(messageCountUpdater != null) {
346 | messageCountUpdater.setCount(msgsWritten);
347 | Thread t = new Thread(messageCountUpdater);
348 | t.start();
349 | }
350 | } catch (JmsDiggerException e) {
351 | LOG.info("Message write failed", e);
352 | }
353 | } else {
354 | this.dumpComplete = true;
355 | }
356 | LOG.debug("Leaving onMessage method");
357 | }
358 |
359 | /**
360 | * Dump contents of a topic.
361 | * @throws JmsDiggerException
362 | * @throws FileNotFoundException
363 | * @throws IOException
364 | */
365 | private void initTopicDump() throws JmsDiggerException, FileNotFoundException, IOException {
366 | LOG.debug("Entering initTopicDump method");
367 | TopicSession tSession;
368 | TopicSubscriber tSubscriber;
369 | jmsWriter.init();
370 |
371 | try {
372 | tSession = (TopicSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
373 | tSubscriber = tSession.createSubscriber((Topic)dst);
374 |
375 | //Set the current object as message listener. All messages will be sent to onMessage method
376 | tSubscriber.setMessageListener(this);
377 | connection.start(); // start the connection - very important
378 | } catch (JMSException e) {
379 | LOG.info("Failure while initiating a Topic Dump", e);
380 | throw JmsHelper.buildJmsDiggerException("Failure while initiating a Topic Dump", e);
381 | }
382 |
383 | //IMPORTANT: The subscriber and session must not be closed as closing them will cause the
384 | // onMessage listener to be dysfunctional and no messages will be received.
385 | LOG.debug("Leaving initTopicDump method");
386 | }
387 |
388 |
389 | /**
390 | * Dump contents of a durable subscriber. The reads are synchronous and block for duration specified
391 | * in the TIMEOUT (milliseconds) static variable.
392 | * @throws FileNotFoundException
393 | * @throws IOException
394 | * @throws JmsDiggerException
395 | */
396 |
397 | private void initDurableSubscriberDump() throws FileNotFoundException, IOException, JmsDiggerException {
398 | // Lot of duplicate code between initTopicDump and initDurableSubscriberDump.
399 | //TODO: Potentially combine these functions -- REVIEW and DECIDE.
400 |
401 | LOG.debug("Entering initDurableSubscriberDump method");
402 | Message msg;
403 | TopicSession tSession;
404 | TopicSubscriber tSubscriber;
405 | jmsWriter.init();
406 |
407 | try {
408 | tSession = (TopicSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
409 | tSubscriber = tSession.createDurableSubscriber((Topic)dst, durableSubscriberName);
410 | connection.start();
411 | while(true) {
412 | msg = tSubscriber.receive(TIMEOUT); //Synchronous read, returns null when no message is received during TIMEOUT time
413 |
414 | //Ensure that null message is not passed to JmsWriter as it will throw an IllegalArgumentException
415 | if(msg == null) {
416 | continue;
417 | }
418 | if(msgCountToDump == 0 || msgsTraversed < msgCountToDump) {
419 | try {
420 | jmsWriter.writeMsg(msg);
421 | msgsWritten++;
422 | /**
423 | * Update the count in GUI
424 | */
425 | if(messageCountUpdater != null) {
426 | messageCountUpdater.setCount(msgsWritten);
427 | Thread t = new Thread(messageCountUpdater);
428 | t.start();
429 | }
430 | } catch (JmsDiggerException ex) {
431 | LOG.info("Message write failed ", ex);
432 | //Swallow single message write failure exception
433 | }
434 |
435 | msgsTraversed++;
436 | } else {
437 | this.dumpComplete = true;
438 | break;
439 | }
440 | }
441 | } catch (JMSException e) {
442 | LOG.info("Failure while performing a Durable Subscriber Dump", e);
443 | throw JmsHelper.buildJmsDiggerException("Failure while performing a Durable Subscriber Dump", e);
444 | }
445 |
446 | try {
447 | tSubscriber.close();
448 | tSession.close();
449 | } catch (JMSException ex) {
450 | //Swallow the close exception
451 | }
452 |
453 | LOG.debug("Leaving initDurableSubscriberDump method");
454 | }
455 |
456 | /**
457 | * The public method that initiates the message dump from different types of destinations based on the
458 | * destination type determined by the init call.
459 | * @throws IllegalAccessException
460 | * @throws JmsDiggerException
461 | * @throws FileNotFoundException
462 | * @throws IOException
463 | * @throws InterruptedException
464 | */
465 |
466 | public void dump() throws IllegalAccessException, JmsDiggerException, FileNotFoundException, IOException, InterruptedException
467 | {
468 | LOG.debug("Entering dump method");
469 | if(!initialized)
470 | throw new IllegalAccessException("dump method called without initializing");
471 |
472 | if(dstType == JmsDestination.QUEUE)
473 | initQueueDump();
474 | else {
475 | if(dstType == JmsDestination.TOPIC)
476 | initTopicDump();
477 | else {
478 | if(dstType == JmsDestination.DURABLESUBSCRIBER)
479 | initDurableSubscriberDump();
480 | else {
481 | LOG.info(dstName + "is neither a Queue nor Topic or a Durable Subscriber");
482 | throw new IllegalArgumentException(dstName + "is neither a Queue nor Topic or a Durable Subscriber");
483 | }
484 | }
485 | }
486 | LOG.debug("Leaving dump method");
487 | }
488 |
489 | /**
490 | * Important to call the close method to close all the file handles
491 | * for the jmsWriter and also close the JMS connection.
492 | * @throws JMSException
493 | * @throws IOException
494 | */
495 |
496 | public void close() throws JMSException, IOException
497 | {
498 | LOG.debug("Entering close method");
499 | jmsWriter.close();
500 | connection.close();
501 | LOG.debug("Leaving close method");
502 |
503 | }
504 |
505 | }
506 |
--------------------------------------------------------------------------------
/src/main/java/com/mcafee/JmsDurableSubscriberManipulator.java:
--------------------------------------------------------------------------------
1 | package com.mcafee;
2 |
3 | import java.util.ArrayList;
4 |
5 | import javax.jms.Connection;
6 | import javax.jms.InvalidDestinationException;
7 | import javax.jms.JMSException;
8 | import javax.jms.Session;
9 | import javax.jms.Topic;
10 | import javax.jms.TopicSubscriber;
11 | import javax.naming.InitialContext;
12 | import javax.naming.NamingException;
13 |
14 | import org.slf4j.Logger;
15 | import org.slf4j.LoggerFactory;
16 |
17 | /**
18 | * This class provides capability to perform various operations related to durable subscribers.
19 | * Given a Topic name, credentials (optional), durable subscriber name, the class can be used to perform the following actions:
20 | * 1. Create random and named durable subscribers
21 | * 2. Erase durable subscribers
22 | * 3. Create large number of durable subscribers with random names
23 | * @author Gursev Singh Kalra @ McAfee, Inc.
24 | *
25 | */
26 | public class JmsDurableSubscriberManipulator {
27 | private static final Logger LOG = LoggerFactory.getLogger(JmsDurableSubscriberManipulator.class);
28 | private InitialContext ctx;
29 | private Topic topic = null;
30 | private JmsLoginInfo loginInfo;
31 | private String cfName;
32 | private String topicName;
33 | private Connection connection; // Connection to the broker to last for the entire querying cycle
34 | private Session session; // Session created for the connection. This may or may not change between different request
35 | private boolean initialized = false;
36 |
37 | private void assertInitialization() {
38 | if(!initialized)
39 | throw new IllegalArgumentException(this.getClass().getName().toString() + "'s object is not initialized");
40 | }
41 |
42 | public JmsDurableSubscriberManipulator(InitialContext ctx, String topicName, String connFactName) {
43 | this(ctx, topicName, connFactName, null);
44 |
45 | }
46 |
47 | public JmsDurableSubscriberManipulator(InitialContext ctx, String topicName, String connFactName, JmsLoginInfo loginInfo) {
48 | this.ctx = ctx;
49 | this.loginInfo = loginInfo;
50 | this.cfName = connFactName;
51 | this.topicName = topicName;
52 | }
53 |
54 | public void init() throws JmsDiggerException {
55 | init(null);
56 | }
57 |
58 | /**
59 | * Creates a connection, session and starts the connection.
60 | * clientId is set if provided. This is typically used for creating a durable subscriber.
61 | * @param clientId
62 | * @throws JmsDiggerException
63 | */
64 | public void init(String clientId) throws JmsDiggerException {
65 | LOG.debug("Entering init");
66 | if(ctx == null || JmsHelper.isStringNullOrEmpty(cfName))
67 | throw JmsHelper.buildJmsDiggerException("Null value for InitialContext or Connection Factory Name");
68 |
69 | if(clientId == null)
70 | connection = JmsHelper.createConnection(ctx, cfName, loginInfo );
71 | else
72 | connection = JmsHelper.createConnection(ctx, cfName, loginInfo, clientId);
73 |
74 | try {
75 | topic = (Topic) ctx.lookup(topicName);
76 | session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
77 | connection.start();
78 | } catch (JMSException ex) {
79 | LOG.info("Error occured while initializing", ex);
80 | throw JmsHelper.buildJmsDiggerException("Error occured while initializing AMQStats", ex);
81 | } catch (NamingException ex) {
82 | LOG.info(topicName + " not found ", ex);
83 | throw JmsHelper.buildJmsDiggerException(topicName + " not found", ex);
84 | }
85 |
86 | initialized = true;
87 | LOG.debug("Leaving init");
88 | }
89 |
90 | /**
91 | * Creates "count" number of subscribers for a Topic. Typically to be used during DoS
92 | * by file system exhaustion. The attack may work like this:
93 | * 1. Connect to a Topic
94 | * 2. Create durable subscribers
95 | * 3. Continue to Send large PERSISTENT messages with longer expiry time to the topic.
96 | *
97 | * @param count - number of TopicSubscribers to create
98 | * @return ArrayList - An arraylist of all TopicSubscribers created
99 | * @throws JmsDiggerException
100 | */
101 | public ArrayList createDurableSubscribers(int count) throws JmsDiggerException {
102 | ArrayList aList = new ArrayList();
103 | if(count <= 0)
104 | throw new IllegalArgumentException("Count cannot be negative");
105 |
106 | for(int i = 0; i < count; i++) {
107 | TopicSubscriber ts = createDurableSubscriber(JmsHelper.getRandomString());
108 | aList.add(ts);
109 | }
110 | return aList;
111 | }
112 |
113 | /**
114 | * Creates a durable topic subscriber with a random name.
115 | * @return TopicSubscriber
116 | * @throws JmsDiggerException
117 | */
118 | public TopicSubscriber createRandDurableSubscriber() throws JmsDiggerException {
119 | return createDurableSubscriber(JmsHelper.getRandomString());
120 | }
121 |
122 | /**
123 | * Creates a durable subscriber with a specified name.
124 | * The durable subscriber created can be connected to later on to retrieve content.
125 | * @param name - Name of the topic subscriber
126 | * @return TopicSubscriber - The topic subscriber object
127 | * @throws JmsDiggerException
128 | */
129 |
130 | public TopicSubscriber createDurableSubscriber(String name) throws JmsDiggerException {
131 | return createDurableSubscriber(name, "", false);
132 | }
133 |
134 | /**
135 | * A Wrapper around createDurableSubscriber with three arguments.
136 | * The noLocal is set to false for every call.
137 | * @param durableSubscriberName
138 | * @param messageSelector
139 | * @return
140 | * @throws JmsDiggerException
141 | */
142 | public TopicSubscriber createDurableSubscriber(String durableSubscriberName, String messageSelector) throws JmsDiggerException {
143 | return createDurableSubscriber(durableSubscriberName, messageSelector, false);
144 | }
145 |
146 | /**
147 | * This call creates a Durable Subscriber for a topic. It is mandatory to initialize
148 | * with init before making this call. If not, the call will fail.
149 | * @param durableSubscriberName - Name of the durable subscriber
150 | * @param messageSelector - The message selector. Can be null, blank or contain a valid value
151 | * @param noLocal - Enable or disable messages generated from same host
152 | * @return TopicSubscriber - Returns the topic subscriber created
153 | * @throws JmsDiggerException - Throws for any errors
154 | */
155 | public TopicSubscriber createDurableSubscriber(String durableSubscriberName, String messageSelector, boolean noLocal) throws JmsDiggerException {
156 | LOG.debug("Entering createDurableSubscriber");
157 | assertInitialization();
158 |
159 | if(JmsHelper.isStringNullOrEmpty(durableSubscriberName))
160 | throw new IllegalArgumentException("Durable subscriber name cannot be null or blank");
161 |
162 | try {
163 | return session.createDurableSubscriber(topic, durableSubscriberName, messageSelector, noLocal);
164 | } catch (JMSException ex) {
165 | LOG.info("An error has occured while creating durable subscriber", ex);
166 | throw JmsHelper.buildJmsDiggerException("An error has occured while creating durable subscriber", ex);
167 | }
168 | }
169 |
170 | /**
171 | * Erases a durable subscriber.
172 | * @param durableSuscriberName
173 | * @throws JmsDiggerException
174 | */
175 | public void eraseDurableSubscriber(String durableSuscriberName) throws JmsDiggerException {
176 | LOG.debug("Entering eraseDurableSubscriber");
177 | assertInitialization();
178 | try {
179 | session.unsubscribe(durableSuscriberName);
180 | } catch (InvalidDestinationException ex) {
181 | LOG.info("No durable subscriber exists with name " + durableSuscriberName);
182 | throw JmsHelper.buildJmsDiggerException("No durable subscriber exists with name " + durableSuscriberName);
183 | } catch (JMSException ex) {
184 | LOG.info("Error occured while erasing a durable subscriber", ex);
185 | throw JmsHelper.buildJmsDiggerException("Error occured while erasing a durable subscriber", ex);
186 | }
187 | LOG.debug("Leaving eraseDurableSubscriber");
188 | }
189 |
190 | /**
191 | * Close the JMS session and the connection
192 | */
193 | public void close() {
194 | try {
195 | session.close();
196 | connection.close();
197 | } catch (JMSException e) {
198 | LOG.info("AMQOps done failed");
199 | }
200 | }
201 | }
202 |
--------------------------------------------------------------------------------
/src/main/java/com/mcafee/JmsHelper.java:
--------------------------------------------------------------------------------
1 | package com.mcafee;
2 |
3 | import java.io.IOException;
4 | import java.io.PrintWriter;
5 | import java.io.StringWriter;
6 | import java.math.BigInteger;
7 | import java.util.Enumeration;
8 | import java.util.Random;
9 |
10 | import javax.jms.Connection;
11 | import javax.jms.ConnectionFactory;
12 | import javax.jms.Destination;
13 | import javax.jms.JMSException;
14 | import javax.jms.MapMessage;
15 | import javax.jms.Session;
16 | //import javax.naming.Context;
17 | import javax.naming.InitialContext;
18 | import javax.naming.NamingException;
19 |
20 | import org.apache.commons.codec.binary.Hex;
21 | import org.slf4j.Logger;
22 | import org.slf4j.LoggerFactory;
23 |
24 | /**
25 | * This is a helper class that offers various functionalities:
26 | * 1. Creates random strings with getRandomString method
27 | * 2. Obtain a destination object with getDestination
28 | * 3. Converts byte array to hex String with byteArrayToHexString
29 | * 4. Converts a MapMessage to string with mapMessageToString method
30 | * 5. Creates a JMS connection and returns the connection object with createConnection method
31 | * 6. Breaks a string to character array with stringToCharArrayString
32 | * 7. Build JmsDiggerException with two overloaded methods with name buildJmsDiggerException
33 | * 8. Creates a connection factory from initial context and connection factory name with getConnectionFactory method
34 | * 9. Creates ActiveMQ's initial context with getActiveMQInitialContext method
35 | * @author Gursev Singh Kalra @ McAfee, Inc.
36 | *
37 | */
38 | public class JmsHelper {
39 |
40 | private static final Logger LOG = LoggerFactory.getLogger(JmsHelper.class);
41 | private static Random random = new Random();
42 |
43 | /**
44 | * Generates and returns a random string
45 | * @return String
46 | */
47 | public static String getRandomString() {
48 | return new BigInteger(64, random).toString(16);
49 | }
50 |
51 | /**
52 | * Converts exception's stack trace to a string for easy printing and consumption
53 | * @param ex
54 | * @return
55 | */
56 | public static String exceptionStacktraceToString(Exception ex) {
57 | StringWriter sWriter = new StringWriter();
58 | PrintWriter pWriter = new PrintWriter(sWriter);
59 | ex.printStackTrace(pWriter);
60 | String result = sWriter.toString();
61 | pWriter.close();
62 | try {
63 | sWriter.close();
64 | } catch (IOException e) {
65 | // Eating it up
66 | }
67 | return result;
68 | }
69 |
70 | /**
71 | * Obtains a Destination object. Any generated exception is added to the cause.
72 | * @param ctx - InitialContext
73 | * @param destName - Destination Name
74 | * @return - Destination Object
75 | * @throws JmsDiggerException
76 | */
77 | public static Destination getDestination(InitialContext ctx, String destName) throws JmsDiggerException
78 | {
79 | LOG.debug("Entering getDestination method");
80 | Destination dest = null;
81 | if(ctx == null || isStringNullOrEmpty(destName))
82 | {
83 | LOG.info("Either InitialContext or Destination Name is null");
84 | throw new JmsDiggerException("Either InitialContext or Destination Name is null");
85 | }
86 |
87 | try
88 | {
89 | dest = (Destination)(ctx.lookup(destName));
90 | }
91 | catch(ClassCastException ex)
92 | {
93 | LOG.info("The returned object for name " + destName + " was not of type Destination", ex);
94 | throw buildJmsDiggerException("The returned object for name " + destName + " was not of type Destination", ex);
95 | }
96 | catch(NamingException ne)
97 | {
98 | LOG.info("No destination found with name " + destName, ne);
99 | throw buildJmsDiggerException("No destination found with name " + destName, ne);
100 | }
101 |
102 | LOG.debug("Leaving getDestination method");
103 | return dest;
104 |
105 | }
106 |
107 | /**
108 | * Convert a byte array to hex string
109 | * Converts a byte array to string representation of hex digits
110 | * Example conversion -> { 0x12, 0x23, 0x32, 0xA5 }
111 | * @param b
112 | * @return
113 | */
114 | public static String byteArrayToHexString(byte[] b) {
115 |
116 | StringBuilder sb = new StringBuilder();
117 | if (b.length == 0)
118 | return "{ }";
119 |
120 | String str = Hex.encodeHexString(b);
121 | String[] twoCharArray = str.split("(?<=\\G.{2})");
122 |
123 | sb.append("{ ");
124 | for (String s : twoCharArray)
125 | sb.append("0x" + s + ", ");
126 |
127 | sb.deleteCharAt(sb.length() - 2);
128 | sb.append("}");
129 | return sb.toString();
130 | }
131 |
132 | /**
133 | * Convers a map message to a string with a custom header
134 | * @param msg - The MapMessage
135 | * @return string representation of the message
136 | * @throws JmsDiggerException
137 | */
138 | public static String mapMessageToString(MapMessage msg) throws JmsDiggerException {
139 | return mapMessageToString(msg, null);
140 | }
141 |
142 | /**
143 | * Convers a map message to a string with a custom header
144 | * @param msg - The MapMessage
145 | * @param customHdr - The header to be used for separating message
146 | * @return string representation of the message
147 | * @throws JmsDiggerException
148 | */
149 | public static String mapMessageToString(MapMessage msg, String customHdr) throws JmsDiggerException {
150 | Enumeration e = null;
151 | StringBuilder sb = new StringBuilder();
152 | String name;
153 | Object value;
154 |
155 | try {
156 | e = ((MapMessage) msg).getMapNames();
157 |
158 | if (e.hasMoreElements()) {
159 | if(customHdr != null)
160 | sb.append(customHdr + "\n");
161 |
162 | while (e.hasMoreElements()) {
163 | name = e.nextElement().toString();
164 | sb.append("\t" + name + " : ");
165 | value = msg.getObject(name);
166 | if (value instanceof byte[])
167 | sb.append(JmsHelper.byteArrayToHexString((byte[]) value) + "\n");
168 | else
169 | sb.append(value + "\n");
170 | }
171 | }
172 | } catch(JMSException ex) {
173 | throw buildJmsDiggerException("An exception occured while creating String representation of MapMessage");
174 | }
175 | return sb.toString();
176 | }
177 |
178 |
179 | /**
180 | * This method returns a connection or null if connection could not be generated.
181 | * @param ctx - Initial Context
182 | * @param cfName - ConnectionFactory name
183 | * @param loginInfo - JmsLoginInfo object with username and password
184 | * @param clientId - Client ID to be used
185 | * @return
186 | * @throws JmsDiggerException
187 | */
188 | public static Connection createConnection(InitialContext ctx, String cfName, JmsLoginInfo loginInfo, String clientId) throws JmsDiggerException {
189 | LOG.debug("Entering getConnection method");
190 | Connection conn = null;
191 | ConnectionFactory connFact = getConnectionFactory(ctx, cfName);
192 |
193 | try
194 | {
195 | if(loginInfo == null)
196 | conn = connFact.createConnection();
197 | else
198 | conn = connFact.createConnection(loginInfo.getUsername(), loginInfo.getPassword());
199 | //conn.setClientID(getRandomString());
200 | if(clientId != null)
201 | conn.setClientID(clientId);
202 | // A new session is created as ActiveMQ does not initiate a new connection unless session creation is attempted.
203 | // The connection is valid and usable only if it allows session creation.
204 | Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
205 |
206 | //Close the session if it gets created as it is not needed.
207 | if(sess != null)
208 | sess.close();
209 | }
210 | catch(JMSException e)
211 | {
212 | LOG.info("Connection to the broker failed", e);
213 | throw buildJmsDiggerException("Connection to the broker failed", e);
214 | }
215 |
216 | LOG.debug("Leaving getConnection method");
217 | return conn;
218 | }
219 |
220 |
221 | /**
222 | * Convert a string to its character representation
223 | * @param str
224 | * @return
225 | */
226 | public static String stringToCharArrayString(String str) {
227 | StringBuilder sb = new StringBuilder();
228 | if(str == null)
229 | throw new IllegalArgumentException("String cannot be null");
230 | if(isStringNullOrEmpty(str))
231 | return "";
232 |
233 | sb.append("{");
234 | char[] c = str.toCharArray();
235 | for(char chr : c) {
236 | sb.append("\""+chr+"\"");
237 | sb.append("=> ");
238 | sb.append((int)chr);
239 | sb.append(", ");
240 | }
241 | sb.append("}");
242 | return sb.toString();
243 |
244 | }
245 |
246 | public static Connection createConnection(InitialContext ctx, String cfName, JmsLoginInfo loginInfo) throws JmsDiggerException {
247 | return createConnection(ctx, cfName, loginInfo, null);
248 | }
249 |
250 | /**
251 | * This belongs to Unit tests. TODO move it to unit test code
252 | * @return
253 | * @throws JmsDiggerException
254 | */
255 | public static InitialContext getActiveMQInitialContextForUnitTest() throws JmsDiggerException
256 | {
257 | JmsInitialContextFactory contextFactory = new JmsInitialContextFactory("org.apache.activemq.jndi.ActiveMQInitialContextFactory", "vm://localhost?broker.persistent=false");
258 | contextFactory.addConnectionFactory("ConnectionFactory");
259 | contextFactory.addQueue("submissions", "jms.submissions");
260 | InitialContext ctx = contextFactory.getInitialContext();
261 | return ctx;
262 | }
263 |
264 | /**
265 | * Returns InitialContext for ActiveMQ
266 | * @return InitialContext
267 | * @throws JmsDiggerException
268 | */
269 | public static InitialContext getActiveMQInitialContext() throws JmsDiggerException
270 | {
271 | JmsInitialContextFactory contextFactory = new JmsInitialContextFactory("org.apache.activemq.jndi.ActiveMQInitialContextFactory", "tcp://192.168.127.130:61616");
272 | contextFactory.addConnectionFactory("ConnectionFactory");
273 | contextFactory.addQueue("submissions", "jms.submissions");
274 | InitialContext ctx = contextFactory.getInitialContext();
275 | return ctx;
276 | }
277 |
278 |
279 | /**
280 | * This method returns connection created with anonymous authentication.
281 | * @param ctx - Initial Context
282 | * @param cfName - ConnectionFactory name
283 | * @param result - JmsResposne object, primarily a DAO to carry back details on failure.
284 | * @return
285 | * @throws JmsDiggerException
286 | */
287 | public static Connection createConnection(InitialContext ctx, String cfName) throws JmsDiggerException
288 | {
289 | return createConnection(ctx, cfName, null);
290 | }
291 |
292 | /**
293 | * Build a JMSDiggerException when another exception has occured and we want to wrap
294 | * that exception with JMSDiggerException
295 | * @param msg - The message
296 | * @param cause - Cause exception
297 | * @return
298 | */
299 | public static JmsDiggerException buildJmsDiggerException(String msg, Throwable cause) {
300 | JmsDiggerException je = new JmsDiggerException(msg);
301 | je.initCause(cause);
302 | return je;
303 |
304 | }
305 |
306 | /**
307 | * Build a JMSDiggerException when another exception has occured and we want to wrap
308 | * that exception with JMSDiggerException
309 | * @param msg - The message
310 | * @return
311 | */
312 | public static JmsDiggerException buildJmsDiggerException(String msg) {
313 | JmsDiggerException je = new JmsDiggerException(msg);
314 | return je;
315 | }
316 |
317 | /**
318 | * This method returns a connection factory from initial context and connection factory name
319 | * @param ctx - Initial Context
320 | * @param cfName - Connection factory name
321 | * @return - ConnectionFactory
322 | * @throws JmsDiggerException
323 | */
324 | public static ConnectionFactory getConnectionFactory(InitialContext ctx, String cfName) throws JmsDiggerException
325 | {
326 | LOG.debug("Entering getConnectionFactory method");
327 | if(ctx == null)
328 | {
329 | throw new JmsDiggerException("InitialContext parameter was null");
330 | }
331 |
332 | //Doing this because of the way ActiveMQ handles local resolution of Connection Factory names
333 | if(isStringNullOrEmpty(cfName))
334 | {
335 | cfName = "ConnectionFactory";
336 | }
337 |
338 | ConnectionFactory cf = null;
339 | try
340 | {
341 | cf = (ConnectionFactory)(ctx.lookup(cfName));
342 | }
343 | catch(ClassCastException ex)
344 | {
345 | LOG.info(cfName + " is not of type ConnectionFactory", ex);
346 | //The returned object can be of type Destination
347 | throw buildJmsDiggerException(cfName + " is not of type ConnectionFactory", ex);
348 | }
349 | catch(NamingException ne)
350 | {
351 | LOG.info("No Connection Factory with name " + cfName + " identified", ne);
352 | throw buildJmsDiggerException("No Connection Factory with name " + cfName + " identified", ne);
353 | }
354 |
355 | LOG.debug("Leaving getConnectionFactory method");
356 | return cf;
357 | }
358 |
359 | /**
360 | * String value is checked against null or with spaces
361 | * @param str
362 | * @return true or false
363 | */
364 | public static boolean isStringNullOrEmpty(String str)
365 | {
366 | if(str == null || str.trim().equals(""))
367 | return true;
368 | return false;
369 | }
370 | }
371 |
--------------------------------------------------------------------------------
/src/main/java/com/mcafee/JmsInitialContextFactory.java:
--------------------------------------------------------------------------------
1 | package com.mcafee;
2 | import java.util.Properties;
3 |
4 | //import javax.naming.Context;
5 | import javax.naming.InitialContext;
6 | import javax.naming.NamingException;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 |
10 | /**
11 | * This class enables generation of InitailContexts. It does not use username or password from
12 | * the environment but relies on programmatically providing these values.
13 | * If someone wants to add username and password the following properties can be added
14 | * via addRawPropertyToEnv method.
15 | *
16 | * java.naming.security.principal -- for username
17 | * java.naming.security.credentials -- for password
18 | * @author Gursev Singh Kalra @ McAfee, Inc.
19 | *
20 | */
21 |
22 | public class JmsInitialContextFactory {
23 | private static final Logger LOG = LoggerFactory.getLogger(JmsInitialContextFactory.class);
24 |
25 | private boolean editable;
26 | private Properties env = new Properties();
27 | private String connectionFactoryName;
28 |
29 | public JmsInitialContextFactory() {
30 | editable = true;
31 | }
32 |
33 | /**
34 | * This constructor initializes the environment with InitialContextFactory name and the provider URL.
35 | * These are mandatory parameters as there is no point initializing if these values are not available
36 | *
37 | * @param initialContextFactory
38 | * @param providerUrl
39 | */
40 | public JmsInitialContextFactory(String initialContextFactory, String providerUrl)
41 | {
42 | env.setProperty("java.naming.factory.initial", initialContextFactory);
43 | env.setProperty("java.naming.provider.url", providerUrl);
44 | editable = true;
45 | }
46 |
47 | public String getConnectionFactoryName() {
48 | return connectionFactoryName;
49 | }
50 |
51 | /**
52 | * This method takes two parameters to add a new Queue to the Context Environment.
53 | * The topicName parameter takes the name of the Queue, prepends it with "queue." before populating it in the environment.
54 | * This is required because that is how the destination name resolution happens. Queues must be prepended by "queue.".
55 | * The displayName is the name that gets displayed when connection is established.
56 | * @param queueName
57 | * @param displayName
58 | */
59 | public void addQueue(String queueName, String displayName) {
60 | if(this.editable == false)
61 | return;
62 | env.setProperty("queue." + queueName, displayName);
63 | }
64 |
65 |
66 | /**
67 | * This method allows more control over what gets added.
68 | * One can choose to not use "topic." or "queue." prependers when adding to the environment variable env
69 | * @param destination
70 | * @param displayName
71 | */
72 | public void addRawPropertyToEnv(String property, String displayName) {
73 | if(this.editable == false)
74 | return;
75 | env.setProperty(property, displayName);
76 | }
77 |
78 | /**
79 | * This method takes two parameters to add a new Topic to the Context Environment.
80 | * The topicName parameter takes the name of the Topic, prepends it with "topic." before populating it in the environment.
81 | * This is required because that is how the resolution happens. Queues must be prepended by "queue.".
82 | * The displayName is the name that gets displayed when connection is established.
83 | * @param topicName
84 | * @param displayName
85 | */
86 |
87 | public void addTopic(String topicName, String displayName) {
88 | if(this.editable == false)
89 | return;
90 | env.setProperty("topic." + topicName, displayName);
91 | }
92 |
93 | /**
94 | * This method adds connectionFactoryNames to the initial context.
95 | * For connection factory lookup to work, the name must be registered here. If no registration is performed,
96 | * "ConnectionFactory" is the default name that can be used to access the ConnectionFactory from the JNDI service
97 | * @param connectionFactoryName
98 | */
99 | public void addConnectionFactory(String connectionFactoryName)
100 | {
101 | if(this.editable == false)
102 | return;
103 | this.connectionFactoryName = connectionFactoryName;
104 | env.setProperty("connectionFactoryNames", connectionFactoryName);
105 | }
106 |
107 |
108 | /**
109 | * This method generates an Initial context, marks the InitialContextFactory object as non-editable before returning the
110 | * InitialContext
111 | * @param result
112 | * @return
113 | * @throws JmsDiggerException
114 | */
115 | public InitialContext getInitialContext() throws JmsDiggerException {
116 | LOG.debug("Entering getInitialContext");
117 |
118 | InitialContext ctx = null;
119 |
120 | // Default "connectionFactoryNames" to "ConnectionFactory" if not initialized
121 | // "ConnectionFactory" is overwritten when the value of "connectionFactoryNames" is set previously. So if a program
122 | // tries to access "ConnectionFactory" after "connectionFactoryNames" is set to something, javax.naming.NameNotFoundException
123 | // is thrown
124 | if(env.getProperty("connectionFactoryNames") == null)
125 | {
126 | this.connectionFactoryName = "ConnectionFactory";
127 | env.setProperty("connectionFactoryNames", "ConnectionFactory");
128 | }
129 |
130 | try
131 | {
132 | ctx = new InitialContext(this.env);
133 | }
134 | catch (NamingException ne)
135 | {
136 | LOG.info("Initial Context could not be created", ne);
137 | throw JmsHelper.buildJmsDiggerException("Initial Context could not be created", ne);
138 | }
139 |
140 | this.editable = false;
141 | LOG.debug("Leaving getInitialContext");
142 | return ctx;
143 | }
144 |
145 | }
146 |
--------------------------------------------------------------------------------
/src/main/java/com/mcafee/JmsLoginInfo.java:
--------------------------------------------------------------------------------
1 | package com.mcafee;
2 |
3 | /**
4 | *
5 | * @author Gursev Singh Kalra @ McAfee, Inc.
6 | *
7 | */
8 | public class JmsLoginInfo {
9 | private String username;
10 | private String password;
11 | public String getUsername() {
12 | return username;
13 | }
14 | public void setUsername(String username) {
15 | this.username = username;
16 | }
17 | public String getPassword() {
18 | return password;
19 | }
20 | public void setPassword(String password) {
21 | this.password = password;
22 | }
23 | public JmsLoginInfo(String username, String password) {
24 | super();
25 | this.username = username;
26 | this.password = password;
27 | }
28 |
29 | public String toString()
30 | {
31 | String uname;
32 | String passwd;
33 |
34 | uname = (username == null)? "null":username;
35 | passwd = (password == null)? "null":password;
36 | return "Username: \"" +uname+"\", Password: \"" +passwd + "\"";
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/mcafee/JmsMessageContentGenerator.java:
--------------------------------------------------------------------------------
1 | package com.mcafee;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.util.Hashtable;
5 | import java.util.Random;
6 |
7 | /**
8 | *
9 | * @author Gursev Singh Kalra @ McAfee, Inc.
10 | *
11 | */
12 | class Person {
13 | private String name;
14 | private int age;
15 |
16 |
17 | public Person(String name, int age) {
18 | super();
19 | this.name = name;
20 | this.age = age;
21 | }
22 |
23 | public String getName() {
24 | return name;
25 | }
26 |
27 | public int getAge() {
28 | return age;
29 | }
30 |
31 | }
32 |
33 | /**
34 | * This class generates content for JMS messages.
35 | * @author Gursev Singh Kalra
36 | *
37 | */
38 | public class JmsMessageContentGenerator {
39 |
40 | private static final char[] printable = {
41 | 'a','b','c','d','e','f','g','h','i','j',
42 | 'k','l','m','n','o','p','q','r','s','t',
43 | 'u','v','w','x','y','z','A','B','C','D',
44 | 'E','F','G','H','I','J','K','L','M','N',
45 | 'O','P','Q','R','S','T','U','V','W','X',
46 | 'Y','Z','0','1','2','3','4','5','6','7',
47 | '8','9','`','!','@','#','$','%','^','&',
48 | '*','(',')','-','=','_','+','[',']','\\',
49 | '|','}','{',';','\'',':','"','/','.','\'',
50 | '<','>','?','~'
51 | };
52 |
53 | private static final char[] alnum = {
54 | 'a','b','c','d','e','f','g','h','i','j',
55 | 'k','l','m','n','o','p','q','r','s','t',
56 | 'u','v','w','x','y','z','A','B','C','D',
57 | 'E','F','G','H','I','J','K','L','M','N',
58 | 'O','P','Q','R','S','T','U','V','W','X',
59 | 'Y','Z','0','1','2','3','4','5','6','7',
60 | '8','9'
61 | };
62 |
63 | private static final Random random = new Random();
64 | private static final int LEN = 50;
65 | private int max_value = 256;
66 |
67 | /**
68 | * Generate and return alphanumeric string
69 | * @return
70 | */
71 | public String getAlnumString() {
72 | return getPrintableString(random.nextInt(LEN)); // do not want to return zero length strings
73 | }
74 |
75 | public void setMaxValue(int i) {
76 | max_value = i;
77 | }
78 |
79 | /**
80 | * Get alphanumeric string with a particular length
81 | * @param length
82 | * @return
83 | */
84 | public String getAlnumString(int length) {
85 | int plen = alnum.length;
86 | StringBuilder sb = new StringBuilder();
87 | for(int i = 0 ; i < length; i++) {
88 | sb.append(alnum[random.nextInt(plen)]);
89 | }
90 | return sb.toString();
91 | }
92 |
93 |
94 | /**
95 | * generates String with length upto 50 characters.
96 | * For longer Strings, use getPrintableString(int length) method
97 | * @return
98 | */
99 | public String getPrintableString() {
100 | return getPrintableString(random.nextInt(LEN)); // do not want to return zero length strings
101 | }
102 |
103 | /**
104 | * Create a printable string
105 | * @param length
106 | * @return
107 | */
108 | public String getPrintableString(int length) {
109 | int plen = printable.length;
110 | StringBuilder sb = new StringBuilder();
111 | for(int i = 0 ; i < length; i++) {
112 | sb.append(printable[random.nextInt(plen)]);
113 | }
114 | return sb.toString();
115 | }
116 |
117 |
118 | public String getString() {
119 | return getString(random.nextInt(LEN) + 1);
120 |
121 | }
122 |
123 | /**
124 | * Creates a string with all characters less than max_value
125 | * @param length
126 | * @return
127 | */
128 | public String getString(int length) {
129 | StringBuilder sb = new StringBuilder();
130 | for(int i = 0 ; i < length; i++) {
131 | sb.append((char)(random.nextInt(max_value)));
132 | }
133 | return sb.toString();
134 | }
135 |
136 |
137 | /**
138 | * Create a byte array with random length
139 | * @return
140 | */
141 | public byte[] getByteAray() {
142 | return getByteAray(random.nextInt(LEN) + 1);
143 | }
144 |
145 | /**
146 | * Create a byte array with length
147 | * @param length - length of the byte array
148 | * @return
149 | */
150 | public byte[] getByteAray(int length) {
151 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
152 | for(int i = 0 ; i < length; i++) {
153 | baos.write(random.nextInt(256));
154 | }
155 | return baos.toByteArray();
156 | }
157 |
158 | /**
159 | * Creates a Person object and returns
160 | * @return
161 | */
162 | public Object getObject() {
163 | return new Person(getPrintableString(), random.nextInt(LEN));
164 |
165 | }
166 |
167 | /**
168 | * creates a HashTable object of random length
169 | * @return HashTable
170 | */
171 | public Hashtable getMap() {
172 | return getMap(random.nextInt(LEN));
173 | }
174 |
175 | /**
176 | * creates a HashTable object of specified length
177 | * @param size - size of the HashTable
178 | * @return HashTable
179 | */
180 | public Hashtable getMap(int size) {
181 | Hashtable map = new Hashtable();
182 | for(int i = 0 ; i < size; i ++)
183 | map.put(getPrintableString(), getString());
184 | return map;
185 | }
186 |
187 |
188 | }
189 |
--------------------------------------------------------------------------------
/src/main/java/com/mcafee/JmsMsgType.java:
--------------------------------------------------------------------------------
1 | package com.mcafee;
2 |
3 | /**
4 | *
5 | * @author Gursev Singh Kalra @ McAfee, Inc.
6 | *
7 | */
8 | public enum JmsMsgType {
9 | BYTES,
10 | TEXT,
11 | STREAM,
12 | MAP,
13 | OBJECT,
14 | MESSAGE
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/mcafee/JmsPasswordOps.java:
--------------------------------------------------------------------------------
1 | package com.mcafee;
2 |
3 | import java.util.ArrayList;
4 | import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
5 | import org.jasypt.exceptions.EncryptionOperationNotPossibleException;
6 |
7 | /**
8 | *
9 | * @author Gursev Singh Kalra @ McAfee, Inc.
10 | *
11 | */
12 | public class JmsPasswordOps {
13 | private ArrayList passwords = new ArrayList();
14 | private StandardPBEStringEncryptor decryptor = new StandardPBEStringEncryptor();
15 |
16 | public void addPassword(String password) {
17 | if(password == null)
18 | throw new IllegalArgumentException("Password cannot be null");
19 | this.passwords.add(password);
20 | }
21 |
22 | public void addPasswordList(ArrayList passwords) {
23 | if(passwords == null || passwords.size() == 0)
24 | throw new IllegalArgumentException("Password ArrayList cannot be null or of zero length");
25 |
26 | //Perform a deep copy
27 | for(String pass: passwords) {
28 | if(pass != null)
29 | this.passwords.add(pass);
30 | }
31 | }
32 |
33 | public void clearPasswords() {
34 | this.passwords.clear();
35 | }
36 |
37 |
38 | public String decryptOne(String encPassword, String key) {
39 | String result = null;
40 | if(JmsHelper.isStringNullOrEmpty(encPassword) || key == null || key.equals("")) {
41 | throw new IllegalArgumentException("EncryptedText or password cannot be null or empty");
42 | }
43 |
44 | decryptor = new StandardPBEStringEncryptor();
45 |
46 | try {
47 | decryptor.setPassword(key);
48 | result = decryptor.decrypt(encPassword);
49 | } catch (EncryptionOperationNotPossibleException ex) {
50 | //Absorb this exception
51 | }
52 | return result;
53 | }
54 |
55 | public String decrypt(String encryptedText) {
56 | String result = null;
57 | if(encryptedText == null)
58 | throw new IllegalArgumentException("Encrypted text cannot be null");
59 |
60 | if(passwords.size() == 0)
61 | throw new IllegalArgumentException("No password list provided");
62 |
63 | for(String pass : passwords) {
64 | //New object is required for each decryption attempt
65 | decryptor = new StandardPBEStringEncryptor();
66 | try {
67 | decryptor.setPassword(pass);
68 | result = decryptor.decrypt(encryptedText);
69 | } catch (EncryptionOperationNotPossibleException ex) {
70 | //Absorb this exception to be able to run through a large number of passwords
71 | }
72 | }
73 | // A null value for the result indicates that encrypted
74 | // text could not be decrypted with the provided passwords
75 | return result;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/java/com/mcafee/JmsWriter.java:
--------------------------------------------------------------------------------
1 | package com.mcafee;
2 |
3 | import java.io.File;
4 | import java.io.FileNotFoundException;
5 | import java.io.FileOutputStream;
6 | import java.io.IOException;
7 | import java.io.PrintWriter;
8 | import java.util.Date;
9 |
10 | import javax.jms.BytesMessage;
11 | import javax.jms.JMSException;
12 | import javax.jms.MapMessage;
13 | import javax.jms.Message;
14 | import javax.jms.MessageEOFException;
15 | import javax.jms.ObjectMessage;
16 | import javax.jms.StreamMessage;
17 | import javax.jms.TextMessage;
18 |
19 | import org.apache.commons.codec.binary.Hex;
20 | import org.slf4j.Logger;
21 | import org.slf4j.LoggerFactory;
22 |
23 | import com.thoughtworks.xstream.XStream;
24 |
25 | /**
26 | * Objects of this class write Message and its data to flat files. It determines
27 | * the type of message and then writes data as per different headers. Types of
28 | * messages supported are:
29 | * 1. Message
30 | * 2. TextMessage
31 | * 3. ObjectMessage
32 | * 4. BytesMessage
33 | * 5. Stream Message
34 | * 6. MapMessage
35 | *
36 | * @author Gursev Singh Kalra @ McAfee, Inc.
37 | *
38 | */
39 |
40 | public class JmsWriter {
41 |
42 | private static final Logger LOG = LoggerFactory.getLogger(JmsWriter.class);
43 |
44 | private static String fileSeparator;
45 | private String targetDir;
46 | private boolean targetDirExists;
47 | private static String msgSeparator; // used as a separator between messages
48 | // being dumped
49 | private String msgDumpFilePath;
50 | private PrintWriter msgDumpFileHandle;
51 |
52 | private XStream jmsXstream;
53 |
54 | private int textMsgsWritten = 0;
55 | private int bytesMsgsWritten = 0;
56 | private int objMsgsWritten = 0;
57 | private int streamMsgsWritten = 0;
58 | private int mapMsgsWritten = 0;
59 | private int msgsWritten = 0;
60 |
61 | private String identifier;
62 |
63 | static {
64 | msgSeparator = "\n~-~-~-~-~-~-~-~-~-~~-~-~-~-~-~-~-~-~-~" + (new Date()).getTime() + "\n";
65 | }
66 |
67 | public JmsWriter(String targetDir, String identifier) throws JmsDiggerException {
68 | this.targetDir = targetDir;
69 | targetDirExists = false;
70 | fileSeparator = System.getProperty("file.separator");
71 | try {
72 | (new File(targetDir)).mkdirs();
73 | } catch (Exception ex) {
74 | LOG.error("Target directory could not be created", ex);
75 | throw JmsHelper.buildJmsDiggerException("Target directory could not be created");
76 | }
77 | jmsXstream = new XStream();
78 | this.identifier = identifier;
79 | }
80 |
81 | public void init() throws FileNotFoundException, IOException {
82 | LOG.debug("Entering init");
83 | initFileHandles();
84 | LOG.debug("Leaving init");
85 | }
86 |
87 | private void initFileHandles() throws FileNotFoundException, IOException {
88 | // time in seconds since epoch
89 | LOG.debug("Entering initFileHandles");
90 | long dt = ((new Date()).getTime());
91 | msgDumpFilePath = targetDir + fileSeparator + identifier + "-MessageDump-" + dt + ".txt";
92 |
93 | try {
94 | msgDumpFileHandle = new PrintWriter(new FileOutputStream(msgDumpFilePath), true);
95 | msgDumpFileHandle.println("#########################################################################\nJMS Destination message dump generated by JMSDigger\n#########################################################################\n");
96 | } catch (FileNotFoundException ex) {
97 | LOG.error("Output file handle could not be creatd", ex);
98 | throw ex;
99 | }
100 |
101 | LOG.debug("Leaving initFileHandles");
102 | }
103 |
104 | private String byteArrayToHexString(byte[] b) {
105 | LOG.debug("Entering byteArrayToHexString");
106 | // Converts a byte array to string representation of hex digits
107 | // { 0x12, 0x23, 0x32, 0xA5 }
108 | StringBuilder sb = new StringBuilder();
109 | if (b.length == 0)
110 | return "{ }";
111 |
112 | String str = Hex.encodeHexString(b);
113 | String[] twoCharArray = str.split("(?<=\\G.{2})");
114 |
115 | sb.append("{ ");
116 | for (String s : twoCharArray)
117 | sb.append("0x" + s + ", ");
118 |
119 | sb.deleteCharAt(sb.length() - 2);
120 | sb.append("}");
121 | LOG.debug("Leaving byteArrayToHexString");
122 | return sb.toString();
123 | }
124 |
125 | private String getBytesMessageContentAsString(BytesMessage msg) throws JmsDiggerException {
126 | LOG.debug("Entering writeBytesMessage");
127 | int len = -1;
128 | byte[] body;
129 |
130 | try {
131 | len = (int) msg.getBodyLength();
132 | if (len == 0) {
133 | return "{ }";
134 | }
135 |
136 | body = new byte[len];
137 | msg.readBytes(body);
138 | } catch (JMSException ex) {
139 | LOG.info("An error occured while retreving content from ByteMessage", ex);
140 | throw JmsHelper.buildJmsDiggerException("An error occured while retreving content from ByteMessage", ex);
141 | }
142 | LOG.debug("Leaving writeBytesMessage");
143 | return byteArrayToHexString(body);
144 |
145 | }
146 |
147 | private String getStreamMessageContentAsString(StreamMessage msg) throws JmsDiggerException {
148 | LOG.debug("Entering writeStreamMessage");
149 | StringBuilder sb = new StringBuilder();
150 | sb.append("{ ");
151 | Object o;
152 |
153 | try {
154 | while (true) {
155 | o = msg.readObject();
156 | if (o instanceof byte[])
157 | sb.append(byteArrayToHexString((byte[]) o));
158 | else
159 | sb.append(o);
160 | sb.append(", ");
161 | }
162 | } catch (MessageEOFException ex) {
163 | sb.deleteCharAt(sb.length() - 2);
164 | // Do nothing. End of StreamMessage content has reached.
165 | } catch (JMSException ex) {
166 | LOG.info("An error occured while reading Object from StreamMessage", ex);
167 | throw JmsHelper.buildJmsDiggerException("An error occured while reading Object from StreamMessage", ex);
168 | }
169 |
170 | sb.append("}");
171 | LOG.debug("Leaving writeStreamMessage");
172 | return sb.toString();
173 | }
174 |
175 | private String getMapMessageContentAsString(MapMessage msg) throws JmsDiggerException {
176 | LOG.debug("Entering writeMapMessage");
177 | try {
178 | return(JmsHelper.mapMessageToString(msg, "[+] MapMessage name-value pairs : "));
179 | } catch (JMSException ex) {
180 | LOG.info("An error occured while reading MapMessage", ex);
181 | throw JmsHelper.buildJmsDiggerException("An error occured while reading MapMessage", ex);
182 | }
183 | }
184 |
185 |
186 | /**
187 | * Analyze the message type against all the JMS message types supported and
188 | * write metadata as per the message type
189 | *
190 | * @param msg
191 | * @param result
192 | * @throws JmsDiggerException
193 | * @throws IOException
194 | */
195 | public void writeMsg(Message msg) throws JmsDiggerException {
196 | LOG.debug("Entering writeMsg");
197 | if (msg == null)
198 | throw new IllegalArgumentException("Message parameter is null");
199 |
200 | JmsMsgType type = null;
201 | StringBuilder messageContent = new StringBuilder();
202 |
203 | try {
204 | if (msg instanceof BytesMessage) {
205 | LOG.debug("Message Type : BytesMessage");
206 | type = JmsMsgType.BYTES;
207 | messageContent.append("[+] Message Type : BytesMessage");
208 | messageContent.append("\n");
209 | messageContent.append("[+] Message Bytes as an Array: \n");
210 | messageContent.append(getBytesMessageContentAsString((BytesMessage) msg));
211 | messageContent.append("\n");
212 | bytesMsgsWritten++;
213 | }
214 |
215 | if (type == null && msg instanceof TextMessage) {
216 | LOG.debug("Message Type : TextMessage");
217 | type = JmsMsgType.TEXT;
218 | messageContent.append("[+] Message Type : TextMessage");
219 | messageContent.append("\n");
220 | messageContent.append("[+] Extracted Text\n");
221 | messageContent.append(((TextMessage)msg).getText());
222 | messageContent.append("\n");
223 | textMsgsWritten++;
224 | }
225 |
226 | if (type == null && msg instanceof StreamMessage) {
227 | LOG.debug("Message Type : StreamMessage");
228 | type = JmsMsgType.STREAM;
229 | messageContent.append("[+] Message Type : StreamMessage");
230 | messageContent.append("\n");
231 | messageContent.append("[+] Extracted Stream\n");
232 | messageContent.append(getStreamMessageContentAsString((StreamMessage) msg));
233 | messageContent.append("\n");
234 | streamMsgsWritten++;
235 | }
236 |
237 | if (type == null && msg instanceof MapMessage) {
238 | LOG.debug("Message Type : MapMessage");
239 | type = JmsMsgType.MAP;
240 | messageContent.append("[+] Message Type : MapMessage");
241 | messageContent.append("\n");
242 | messageContent.append(getMapMessageContentAsString((MapMessage) msg));
243 | messageContent.append("\n");
244 | mapMsgsWritten++;
245 | }
246 |
247 | if (type == null && msg instanceof ObjectMessage) {
248 | LOG.debug("Message Type : ObjectMessage");
249 | type = JmsMsgType.OBJECT;
250 | messageContent.append("[+] Message Type : ObjectMessage");
251 | messageContent.append("\n");
252 | objMsgsWritten++;
253 | }
254 |
255 | if (type == null && msg instanceof Message) {
256 | LOG.debug("Message Type : Message");
257 | type = JmsMsgType.MESSAGE;
258 | messageContent.append("[+] Message Type : Message");
259 | messageContent.append("\n");
260 | }
261 |
262 | messageContent.append("[+] Message Properties in XML (including binary dump in content/data element)\n");
263 | messageContent.append(jmsXstream.toXML(msg));
264 | messageContent.append("\n");
265 | messageContent.append(msgSeparator);
266 | msgDumpFileHandle.println(messageContent.toString());
267 | msgsWritten++;
268 | } catch (JMSException ex) {
269 | LOG.info("A JMS operation failed", ex);
270 | throw JmsHelper.buildJmsDiggerException("A JMS operation failed", ex);
271 | }
272 | LOG.debug("Leaving writeMsg");
273 | }
274 |
275 | private String getWriteCountBreakup() {
276 | StringBuilder sb = new StringBuilder();
277 | sb.append("ObjectMessages written: " + objMsgsWritten + ", ");
278 | sb.append("BytesMessages written: " + bytesMsgsWritten + ", ");
279 | sb.append("StreamMessages written: " + streamMsgsWritten + ", ");
280 | sb.append("MapMessages written: " + mapMsgsWritten + ", ");
281 | sb.append("TextMessages written: " + textMsgsWritten);
282 | return sb.toString();
283 | }
284 |
285 | public void close() throws IOException {
286 | LOG.debug("Entering close");
287 | if (msgsWritten == 0)
288 | msgDumpFileHandle.println("No messages were written");
289 |
290 | msgDumpFileHandle.flush();
291 | msgDumpFileHandle.close();
292 |
293 | LOG.debug(getWriteCountBreakup());
294 | LOG.debug("Leaving close");
295 | }
296 |
297 | }
--------------------------------------------------------------------------------
/src/main/java/com/mcafee/MessageCountUpdater.java:
--------------------------------------------------------------------------------
1 | package com.mcafee;
2 | import java.awt.EventQueue;
3 | import javax.swing.JLabel;
4 |
5 | /**
6 | *
7 | * @author Gursev Singh Kalra @ McAfee, Inc.
8 | *
9 | */
10 | public class MessageCountUpdater implements Runnable {
11 | private JLabel progressLabel;
12 | private int count;
13 |
14 |
15 |
16 | public MessageCountUpdater(JLabel progressLabel) {
17 | this.progressLabel = progressLabel;
18 | }
19 |
20 | public void setCount(int count) {
21 | this.count = count;
22 | }
23 |
24 | public void run() {
25 | EventQueue.invokeLater(new Runnable() {
26 | public void run() {
27 | progressLabel.setText(Integer.toString(count));
28 | }
29 | });
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/mcafee/gui/JMSDiggerAboutTab.java:
--------------------------------------------------------------------------------
1 | package com.mcafee.gui;
2 |
3 | import java.awt.GridBagConstraints;
4 | import java.awt.GridBagLayout;
5 |
6 | import javax.swing.BorderFactory;
7 | import javax.swing.JPanel;
8 | import javax.swing.JTextArea;
9 | import javax.swing.border.Border;
10 | import javax.swing.border.EtchedBorder;
11 |
12 | public class JMSDiggerAboutTab extends JPanel{
13 |
14 | /**
15 | *
16 | */
17 | private static final long serialVersionUID = 1L;
18 | private String title;
19 |
20 | public String getTitle() {
21 | return this.title;
22 | }
23 | public JMSDiggerAboutTab() {
24 | this.title = "About";
25 | JPanel aboutPanel = new JPanel(new GridBagLayout());
26 | Border border = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
27 | aboutPanel.setBorder(border);
28 | JTextArea aboutTextArea = new JTextArea("\n JMSDigger is an Enterprise Messaging Application Assessment tool. \n\n Author: Gursev Singh Kalra (gursev.kalra@foundstone.com)\n McAfee, Inc - Foundstone Professional Services. \n\n Source code: \n https://github.com/OpenSecurityResearch/jmsdigger\n ");
29 | aboutTextArea.setEditable(false);
30 | GridBagConstraints gbc = new GridBagConstraints();
31 | gbc.gridx = 0;
32 | gbc.gridy = 0;
33 | aboutPanel.add(aboutTextArea, gbc);
34 | this.add(aboutPanel);
35 | }
36 |
37 |
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/mcafee/gui/JmsAuthenticationTab.java:
--------------------------------------------------------------------------------
1 | package com.mcafee.gui;
2 |
3 | import java.awt.Dimension;
4 | import java.awt.GridBagConstraints;
5 | import java.awt.GridBagLayout;
6 | import java.awt.Insets;
7 | import java.awt.event.ActionEvent;
8 | import java.awt.event.ActionListener;
9 | import java.io.File;
10 | import java.io.FileInputStream;
11 | import java.io.FileNotFoundException;
12 | import java.util.ArrayList;
13 | import java.util.Enumeration;
14 | import java.util.List;
15 | import java.util.Scanner;
16 | import java.util.concurrent.ExecutionException;
17 |
18 | import javax.naming.InitialContext;
19 | import javax.swing.BorderFactory;
20 | import javax.swing.DefaultListModel;
21 | import javax.swing.JButton;
22 | import javax.swing.JFileChooser;
23 | import javax.swing.JLabel;
24 | import javax.swing.JList;
25 | import javax.swing.JPanel;
26 | import javax.swing.JProgressBar;
27 | import javax.swing.JScrollPane;
28 | import javax.swing.JTextArea;
29 | import javax.swing.JTextField;
30 | import javax.swing.SwingWorker;
31 | import javax.swing.border.Border;
32 | import javax.swing.border.EtchedBorder;
33 |
34 | import org.slf4j.Logger;
35 | import org.slf4j.LoggerFactory;
36 |
37 | import com.mcafee.JmsAuthentication;
38 | import com.mcafee.JmsDiggerException;
39 | import com.mcafee.JmsHelper;
40 | import com.mcafee.JmsLoginInfo;
41 |
42 | /**
43 | *
44 | * @author Gursev Singh Kalra @ McAfee, Inc.
45 | *
46 | */
47 | public class JmsAuthenticationTab extends JPanel {
48 |
49 | private static final Logger LOG = LoggerFactory.getLogger(JmsAuthenticationTab.class);
50 | private static int space = 5;
51 | private String title;
52 | private JFileChooser fileChooser;
53 |
54 | public String getTitle() {
55 | return title;
56 | }
57 |
58 | /**
59 | *
60 | */
61 | private static final long serialVersionUID = 1L;
62 | private JTextField singleUserInput ;
63 | private JTextField singlePassInput;
64 | private JButton goSingleUser;
65 | private JList usernameList;
66 | private JButton loadUserIdsButton;
67 | private JButton clearUserIdsButton;
68 | private JList passwordList;
69 | private JButton loadPasswordsButton;
70 | private JButton clearPasswordsButton;
71 | private JButton goBruteforceButton;
72 | private JTextArea outputArea;
73 | private JProgressBar progressBar;
74 | private JmsConfigTab jmsConfigTab;
75 | private AuthenticationWorker authenticationWorker;
76 |
77 |
78 | public JmsAuthenticationTab(JmsConfigTab jmsConfigTab) {
79 | this.jmsConfigTab = jmsConfigTab;
80 | UsernamePasswordListManipulator usernamePasswordListManipulatorObject = new UsernamePasswordListManipulator();
81 | TriggerAuthenticationWorker triggerAuthenticationWorkerObject = new TriggerAuthenticationWorker();
82 |
83 | JLabel blankLabel = new JLabel("\n");
84 | Insets inset = new Insets(space, space, space, space);
85 | Insets masterInset = new Insets(space * 2, space *2 , space*2, space*2);
86 | GridBagLayout masterGbl = new GridBagLayout();
87 | GridBagConstraints masterGbc = new GridBagConstraints();
88 | this.setLayout(masterGbl);
89 | this.title = "Authentication";
90 |
91 | JPanel singleUserPanel = new JPanel(new GridBagLayout());
92 | JLabel singleUserLabel = new JLabel("Username: ");
93 | singleUserLabel.setHorizontalAlignment(JLabel.RIGHT);
94 | JLabel singlePassLabel = new JLabel("Password: ");
95 | singlePassLabel.setHorizontalAlignment(JLabel.RIGHT);
96 | singlePassInput = new JTextField(20);
97 | goSingleUser = new JButton("Go");
98 | goSingleUser.addActionListener(triggerAuthenticationWorkerObject);
99 | GridBagConstraints gbc = new GridBagConstraints();
100 | Border border = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
101 | Border singleUserBorder = BorderFactory.createTitledBorder(border, "Credential Check");
102 | Border fuzzBorder = BorderFactory.createTitledBorder(border, "Credential Brute Force");
103 |
104 |
105 | gbc.insets = inset;
106 | gbc.gridx = 0;
107 | gbc.gridy = 0;
108 | singleUserPanel.add(singleUserLabel, gbc);
109 | gbc.gridx = 1;
110 | gbc.gridy = 0;
111 | gbc.gridwidth = 2;
112 | singleUserInput = new JTextField(20);
113 | //gbc.weightx = 1.0;
114 | //gbc.fill = GridBagConstraints.HORIZONTAL;
115 | singleUserPanel.add(singleUserInput, gbc);
116 | gbc.gridx = 0;
117 | gbc.gridy = 1;
118 | gbc.gridwidth = 1;
119 | gbc.weightx = 0.0;
120 | gbc.fill = GridBagConstraints.NONE;
121 | singleUserPanel.add(singlePassLabel, gbc);
122 | gbc.gridx = 1;
123 | gbc.gridy = 1;
124 | gbc.gridwidth = 2;
125 | //gbc.weightx = 1.0;
126 | //gbc.fill = GridBagConstraints.HORIZONTAL;
127 | singleUserPanel.add(singlePassInput, gbc);
128 |
129 |
130 |
131 | JPanel buttonPanel = new JPanel();
132 | buttonPanel.add(goSingleUser);
133 | gbc.gridx = 0;
134 | gbc.gridy = 2;
135 | gbc.gridwidth = 3;
136 | singleUserPanel.add(buttonPanel, gbc);
137 | singleUserPanel.setBorder(singleUserBorder);
138 |
139 | masterGbc.gridx = 0;
140 | masterGbc.gridy = 0;
141 | masterGbc.anchor = GridBagConstraints.LINE_START;
142 | this.add(singleUserPanel, masterGbc);
143 |
144 | masterGbc.gridx = 0;
145 | masterGbc.gridy = 1;
146 | this.add(blankLabel, masterGbc);
147 |
148 |
149 |
150 | /*
151 | * Panel to accomodate controls for username and password lists
152 | */
153 | JPanel loginFuzzPanel = new JPanel(new GridBagLayout());
154 | Dimension userPasswdListSize = new Dimension(275,70);
155 | gbc = new GridBagConstraints();
156 | //gbc.insets = inset;
157 |
158 | /*
159 | * Build the USERNAME, Jlist and corresponding load and clear buttons
160 | */
161 | JPanel usernamePanel = new JPanel(new GridBagLayout());
162 | JLabel userIdLabel = new JLabel("Usernames");
163 | gbc.gridx = 0;
164 | gbc.gridy = 0;
165 | usernamePanel.add(userIdLabel, gbc);
166 |
167 | usernameList = new JList();
168 | DefaultListModel usernameModel = new DefaultListModel();
169 | usernameList.setModel(usernameModel);
170 | usernameList.setBorder(border);
171 | gbc.gridx = 0;
172 | gbc.gridy = 1;
173 | JScrollPane userPane = new JScrollPane(usernameList);
174 | userPane.setPreferredSize(userPasswdListSize);
175 | usernamePanel.add(userPane, gbc);
176 |
177 | JPanel usernameLoadClearPanel = new JPanel();
178 | loadUserIdsButton = new JButton("Load");
179 | usernameLoadClearPanel.add(loadUserIdsButton);
180 | loadUserIdsButton.addActionListener(usernamePasswordListManipulatorObject);
181 | clearUserIdsButton = new JButton("Clear");
182 | usernameLoadClearPanel.add(clearUserIdsButton);
183 | clearUserIdsButton.addActionListener(usernamePasswordListManipulatorObject);
184 | gbc.gridx = 0;
185 | gbc.gridy = 2;
186 | usernamePanel.add(usernameLoadClearPanel, gbc);
187 |
188 | gbc.gridx = 0;
189 | gbc.gridy = 0;
190 | loginFuzzPanel.add(usernamePanel, gbc);
191 |
192 | /*
193 | * Build the PASSWORD, Jlist and corresponding load and clear buttons
194 | */
195 | JPanel passwordPanel = new JPanel(new GridBagLayout());
196 | JLabel passwordsLabel = new JLabel("Passwords");
197 | gbc.gridx = 0;
198 | gbc.gridy = 0;
199 | passwordPanel.add(passwordsLabel, gbc);
200 |
201 | passwordList = new JList();
202 | DefaultListModel passwordModel = new DefaultListModel();
203 | passwordList.setModel(passwordModel);
204 | //passwordList.setPreferredSize(userPasswdListSize);
205 | passwordList.setBorder(border);
206 | gbc.gridx = 0;
207 | gbc.gridy = 1;
208 | JScrollPane passPane = new JScrollPane(passwordList);
209 | passPane.setPreferredSize(userPasswdListSize);
210 | passwordPanel.add(passPane, gbc);
211 |
212 |
213 | /**
214 | * CODE BEGIN - Load and clear passwords
215 | */
216 | JPanel passwordLoadClearPanel = new JPanel();
217 | loadPasswordsButton = new JButton("Load");
218 | passwordLoadClearPanel.add(loadPasswordsButton);
219 | loadPasswordsButton.addActionListener(usernamePasswordListManipulatorObject);
220 | clearPasswordsButton = new JButton("Clear");
221 | passwordLoadClearPanel.add(clearPasswordsButton);
222 | clearPasswordsButton.addActionListener(usernamePasswordListManipulatorObject);
223 | gbc.gridx = 0;
224 | gbc.gridy = 2;
225 | passwordPanel.add(passwordLoadClearPanel, gbc);
226 |
227 | gbc.gridx = 1;
228 | gbc.gridy = 0;
229 | loginFuzzPanel.add(passwordPanel, gbc);
230 | /**
231 | * CODE ENDS - Load and clear passwords
232 | */
233 |
234 |
235 | /*
236 | * Create the go button and stick it to the end of the Fuzzing
237 | */
238 | JPanel goBruteforcePanel = new JPanel(new GridBagLayout());
239 | goBruteforceButton = new JButton("Go");
240 | goBruteforceButton.addActionListener(triggerAuthenticationWorkerObject);
241 | goBruteforcePanel.add(goBruteforceButton);
242 | gbc.gridx = 0;
243 | gbc.gridy = 0;
244 | goBruteforcePanel.add(goBruteforceButton, gbc);
245 | gbc.gridx = 0;
246 | gbc.gridy = 1;
247 | gbc.gridwidth = 2;
248 | loginFuzzPanel.add(goBruteforcePanel, gbc);
249 |
250 | masterGbc.gridx = 0;
251 | masterGbc.gridy = 2;
252 | loginFuzzPanel.setBorder(fuzzBorder);
253 | this.add(loginFuzzPanel, masterGbc);
254 |
255 |
256 | /*
257 | * Add a text box to display results and exception details
258 | */
259 | JPanel outputBoxPanel = new JPanel(new GridBagLayout());
260 | outputArea = new JTextArea(15, 50);
261 | outputArea.setEditable(false);
262 |
263 | gbc.fill = GridBagConstraints.BOTH;
264 | gbc.gridx = 0;
265 | gbc.gridy = 0;
266 | outputBoxPanel.add(new JScrollPane(outputArea), gbc);
267 | Border authBorder = BorderFactory.createTitledBorder(border, "Results");
268 | outputBoxPanel.setBorder(authBorder);
269 | masterGbc.gridx = 0;
270 | masterGbc.gridy = 3;
271 | this.add(outputBoxPanel, masterGbc);
272 |
273 |
274 | /*
275 | * Pane to display progress
276 | */
277 | JPanel progressPanel = new JPanel(new GridBagLayout());
278 | JLabel progressLabel = new JLabel("Progress > ");
279 | gbc.gridx = 0;
280 | gbc.gridy = 0;
281 | gbc.fill = GridBagConstraints.NONE;
282 | progressPanel.add(progressLabel, gbc);
283 |
284 |
285 | progressBar = new JProgressBar();
286 | gbc.fill = GridBagConstraints.HORIZONTAL;
287 | gbc.gridx = 2;
288 | gbc.gridy = 0;
289 | gbc.weightx = 1.0;
290 | progressPanel.add(progressBar, gbc);
291 |
292 | masterGbc.gridx = 0;
293 | masterGbc.gridy = 4;
294 | masterGbc.fill = GridBagConstraints.HORIZONTAL;
295 | masterGbc.insets = masterInset;
296 | this.add(progressPanel, masterGbc);
297 |
298 |
299 | }
300 |
301 | class UsernamePasswordListManipulator implements ActionListener {
302 |
303 | public void actionPerformed(ActionEvent event) {
304 | DefaultListModel usernamePasswordListModel = new DefaultListModel();
305 | if(event.getSource() == clearUserIdsButton) {
306 | usernameList.setModel(usernamePasswordListModel);
307 | return;
308 | }
309 | else {
310 | if(event.getSource() == clearPasswordsButton) {
311 | passwordList.setModel(usernamePasswordListModel);
312 | return;
313 | }
314 | }
315 |
316 |
317 | fileChooser = new JFileChooser();
318 | fileChooser.setCurrentDirectory(new File("."));
319 | Scanner fileScanner;
320 |
321 | int result = fileChooser.showOpenDialog(null);
322 | if(result == JFileChooser.APPROVE_OPTION) {
323 | File file = fileChooser.getSelectedFile();
324 | try {
325 | fileScanner = new Scanner(new FileInputStream(file));
326 | while(fileScanner.hasNextLine()) {
327 | usernamePasswordListModel.addElement(fileScanner.nextLine());
328 | }
329 | fileScanner.close();
330 | } catch (FileNotFoundException e) {
331 | LOG.info("An error has occured with the file Scanner", e);
332 | JmsGuiCommon.showErrorAndLogMessage("An error occured with the file Scanner.");
333 | }
334 | if(event.getSource() == loadUserIdsButton)
335 | usernameList.setModel(usernamePasswordListModel);
336 | else
337 | if(event.getSource() == loadPasswordsButton)
338 | passwordList.setModel(usernamePasswordListModel);
339 | }
340 | }
341 | }
342 |
343 | class TriggerAuthenticationWorker implements ActionListener {
344 |
345 | public void actionPerformed(ActionEvent event) {
346 | outputArea.setText("");
347 | progressBar.setValue(0);
348 | DefaultListModel userIdModel = (DefaultListModel)(usernameList.getModel());
349 | DefaultListModel passwordModel = (DefaultListModel)(passwordList.getModel());
350 |
351 | ArrayList usernameArrayList = new ArrayList();
352 | ArrayList passwordArrayList = new ArrayList();
353 |
354 | if(event.getSource() == goSingleUser) {
355 | usernameArrayList.add(singleUserInput.getText());
356 | passwordArrayList.add(singlePassInput.getText());
357 | } else {
358 | if(event.getSource() == goBruteforceButton) {
359 |
360 | if(passwordModel.getSize() == 0)
361 | passwordArrayList.add("");
362 | else {
363 | Enumeration e = passwordModel.elements();
364 | while(e.hasMoreElements())
365 | passwordArrayList.add(e.nextElement());
366 | }
367 |
368 | if(userIdModel.getSize() == 0)
369 | usernameArrayList.add("");
370 | else {
371 | Enumeration e = userIdModel.elements();
372 | while(e.hasMoreElements())
373 | usernameArrayList.add(e.nextElement());
374 | }
375 | }
376 | }
377 | try {
378 | authenticationWorker = new AuthenticationWorker(jmsConfigTab.getJmsConfig(), usernameArrayList, passwordArrayList);
379 | } catch (JmsDiggerException e) {
380 | LOG.info("An error has occured while creating an AuthenticationWorker", e);
381 | JmsGuiCommon.showErrorAndLogMessage("An error has occured while creating an AuthenticationWorker");
382 | }
383 | authenticationWorker.execute();
384 | disableAllButtons();
385 | }
386 |
387 | private void disableAllButtons() {
388 | goSingleUser.setEnabled(false);
389 | goBruteforceButton.setEnabled(false);
390 | loadPasswordsButton.setEnabled(false);
391 | loadUserIdsButton.setEnabled(false);
392 | clearPasswordsButton.setEnabled(false);
393 | clearUserIdsButton.setEnabled(false);
394 | }
395 | }
396 |
397 | class ProgressInfo {
398 | private String accessResult;
399 | private int percentage;
400 |
401 | public String getAccessResult() {
402 | return accessResult;
403 | }
404 |
405 | public int getPercentage() {
406 | return percentage;
407 | }
408 |
409 | public ProgressInfo(String accessResult, int percentage) {
410 | this.accessResult = accessResult;
411 | this.percentage = percentage;
412 | }
413 | }
414 |
415 | class AuthenticationWorker extends SwingWorker {
416 |
417 | private ArrayList usernameArrayList;
418 | private ArrayList passwordArrayList;
419 |
420 | private JmsConfig jmsConfig;
421 | private InitialContext initialContext;
422 | private JmsLoginInfo loginInfo;
423 | private JmsAuthentication jmsAuthn;
424 | private boolean boolResult;
425 |
426 | public AuthenticationWorker(JmsConfig jmsConfig, ArrayList usernameArrayList, ArrayList passwordArrayList) {
427 | this.jmsConfig = jmsConfig;
428 | this.usernameArrayList = usernameArrayList;
429 | this.passwordArrayList = passwordArrayList;
430 | }
431 |
432 | @Override
433 | public String doInBackground() throws JmsDiggerException {
434 | StringBuilder testResults;
435 | StringBuilder workingCreds = new StringBuilder();
436 | workingCreds.append("\n\n###########################################################\nWorking Credentials:\n");
437 | // contextFactory = new JmsInitialContextFactory(jmsConfig.getCtxFactoryClass(), jmsConfig.getProviderUrl());
438 | // contextFactory.addConnectionFactory(jmsConfig.getConnFactName());
439 | // ctx = contextFactory.getInitialContext();
440 | initialContext = jmsConfig.buildInitialContext();
441 | jmsAuthn = new JmsAuthentication(initialContext, jmsConfig.getConnFactName());
442 | int userPasswordCombinations = usernameArrayList.size() * passwordArrayList.size();
443 | int count = 0;
444 | for(String username: usernameArrayList) {
445 | for(String password: passwordArrayList) {
446 | testResults = new StringBuilder();
447 | loginInfo = new JmsLoginInfo(username, password);
448 |
449 | testResults.append("###########################################################\nTrying => "
450 | +loginInfo
451 | +"\n"
452 | +"Result: ");
453 | count++;
454 |
455 | boolResult = jmsAuthn.isLoginInfoValid(loginInfo);
456 | if(boolResult == false) {
457 | testResults.append("Failed\n");
458 | testResults.append(JmsHelper.exceptionStacktraceToString(jmsAuthn.getException()));
459 | } else {
460 | testResults.append("Success\n");
461 | workingCreds.append(loginInfo + "\n");
462 | }
463 |
464 | publish(new ProgressInfo(testResults.toString(), count*100/userPasswordCombinations));
465 | }
466 | }
467 | return workingCreds.toString();
468 | }
469 |
470 | @Override
471 | public void process(List progressInfo) {
472 | progressBar.setValue(progressInfo.get(progressInfo.size() - 1).getPercentage());
473 | for(ProgressInfo p : progressInfo) {
474 | outputArea.append("\n" + p.getAccessResult());
475 | }
476 | }
477 |
478 | @Override
479 | public void done() {
480 | //outputArea.append();
481 | try {
482 | outputArea.append(get());
483 | } catch (InterruptedException e) {
484 | LOG.info("An error has occured while appending to the outputArea", e);
485 | } catch (ExecutionException e) {
486 | LOG.info("An error has occured while appending to the outputArea", e);
487 | }
488 | enableAllButtons();
489 | }
490 |
491 | private void enableAllButtons() {
492 | //Thread.sleep(3* 1000);
493 | goSingleUser.setEnabled(true);
494 | goBruteforceButton.setEnabled(true);
495 | loadPasswordsButton.setEnabled(true);
496 | loadUserIdsButton.setEnabled(true);
497 | clearPasswordsButton.setEnabled(true);
498 | clearUserIdsButton.setEnabled(true);
499 | }
500 |
501 | }
502 |
503 | }
504 |
--------------------------------------------------------------------------------
/src/main/java/com/mcafee/gui/JmsConfig.java:
--------------------------------------------------------------------------------
1 | package com.mcafee.gui;
2 |
3 | import javax.naming.InitialContext;
4 |
5 | import com.mcafee.JmsDiggerException;
6 | import com.mcafee.JmsInitialContextFactory;
7 | import com.mcafee.JmsLoginInfo;
8 |
9 | /**
10 | *
11 | * @author Gursev Singh Kalra @ McAfee, Inc.
12 | *
13 | */
14 | public class JmsConfig {
15 | private InitialContext initialContext;
16 | private JmsInitialContextFactory contextFactory;
17 | private String ctxFactoryClass;
18 | private String connFactName;
19 | private String providerUrl;
20 | private String username;
21 | private String password;
22 | private JmsLoginInfo loginInfo;
23 | private boolean finalInitContext;
24 |
25 | public JmsConfig(String ctxFactoryClass, String connFactName, String providerUrl, String username, String password) throws JmsDiggerException {
26 | this.ctxFactoryClass = ctxFactoryClass;
27 | this.connFactName = connFactName;
28 | this.providerUrl = providerUrl;
29 | this.username = username;
30 | this.password = password;
31 | contextFactory = new JmsInitialContextFactory(this.getCtxFactoryClass(), this.getProviderUrl());
32 | contextFactory.addConnectionFactory(this.getConnFactName());
33 | loginInfo = new JmsLoginInfo(this.username, this.password);
34 | finalInitContext = false;
35 | }
36 |
37 | public InitialContext buildInitialContext() throws JmsDiggerException {
38 | //Delaying Initial Context initialization until it is retrieved.
39 | if(!finalInitContext)
40 | initialContext = contextFactory.getInitialContext();
41 | return initialContext;
42 | }
43 |
44 | public void addTopic(String topicName) {
45 | if(!finalInitContext)
46 | contextFactory.addTopic(topicName, "jms."+topicName);
47 | }
48 |
49 | public void addQueue(String queueName) {
50 | if(!finalInitContext)
51 | contextFactory.addQueue(queueName, "jms."+queueName);
52 | }
53 |
54 | public String getCtxFactoryClass() {
55 | return ctxFactoryClass;
56 | }
57 |
58 | public String getConnFactName() {
59 | return connFactName;
60 | }
61 |
62 | public String getProviderUrl() {
63 | return providerUrl;
64 | }
65 |
66 | public String getUsername() {
67 | return username;
68 | }
69 |
70 | public String getPassword() {
71 | return password;
72 | }
73 |
74 | public JmsLoginInfo getLoginInfo() {
75 | return loginInfo;
76 | }
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/src/main/java/com/mcafee/gui/JmsConfigTab.java:
--------------------------------------------------------------------------------
1 | package com.mcafee.gui;
2 |
3 | import java.awt.EventQueue;
4 | import java.awt.GridBagConstraints;
5 | import java.awt.GridBagLayout;
6 | import java.awt.Insets;
7 | import java.awt.event.ActionEvent;
8 | import java.awt.event.ActionListener;
9 |
10 | import javax.naming.InitialContext;
11 | import javax.swing.JButton;
12 | import javax.swing.JLabel;
13 | import javax.swing.JOptionPane;
14 | import javax.swing.JPanel;
15 | import javax.swing.JPasswordField;
16 | import javax.swing.JTextField;
17 |
18 | import org.slf4j.Logger;
19 | import org.slf4j.LoggerFactory;
20 |
21 | import com.mcafee.JmsAuthentication;
22 | import com.mcafee.JmsDiggerException;
23 | import com.mcafee.JmsHelper;
24 | import com.mcafee.JmsInitialContextFactory;
25 | import com.mcafee.JmsLoginInfo;
26 |
27 | /**
28 | * This panel contains all the configuration related items
29 | * @author Gursev Singh Kalra @ McAfee, Inc.
30 | *
31 | */
32 |
33 | public class JmsConfigTab extends JPanel {
34 |
35 | /**
36 | *
37 | */
38 | private static final Logger LOG = LoggerFactory.getLogger(JmsConfigTab.class);
39 | private static final long serialVersionUID = 1L;
40 | private String title;
41 | private static int space = 5;
42 |
43 | private JTextField ctxFactoryClassInput;
44 | private JTextField providerUrlInput;
45 | private JTextField usernameInput;
46 | private JPasswordField passwordInput;
47 | private JTextField connFactNameInput;
48 | private JButton testConfigButton;
49 |
50 |
51 | public String getTitle() {
52 | return title;
53 | }
54 |
55 | public JmsConfig getJmsConfig() throws JmsDiggerException {
56 | if(JmsHelper.isStringNullOrEmpty(connFactNameInput.getText())
57 | || JmsHelper.isStringNullOrEmpty(ctxFactoryClassInput.getText())
58 | || JmsHelper.isStringNullOrEmpty(providerUrlInput.getText()))
59 | {
60 | JOptionPane.showMessageDialog(null, "One of Connection Factory, Provider URL or Context Factory Name is or empty", "Error", JOptionPane.ERROR_MESSAGE);
61 | return null;
62 | }
63 | JmsConfig jmsConfig = new JmsConfig(
64 | ctxFactoryClassInput.getText(),
65 | connFactNameInput.getText(),
66 | providerUrlInput.getText(),
67 | usernameInput.getText(),
68 | new String(passwordInput.getPassword())
69 | );
70 | return jmsConfig;
71 | }
72 |
73 | public JmsConfigTab () {
74 | Insets inset = new Insets(space, space, space, space);
75 | GridBagConstraints gbc = new GridBagConstraints();
76 | gbc.insets = inset;
77 | JPanel configPanel = new JPanel(new GridBagLayout());
78 |
79 | JLabel ctxFactoryClassLabel = new JLabel("Initial Context Factory Class");
80 | ctxFactoryClassInput = new JTextField(30);
81 | ctxFactoryClassInput.setText("org.apache.activemq.jndi.ActiveMQInitialContextFactory");
82 | ctxFactoryClassInput.setEditable(false);
83 | ctxFactoryClassLabel.setHorizontalAlignment(JLabel.RIGHT);
84 |
85 | JLabel connFactNameLabel = new JLabel("Connection Factory Name");
86 | connFactNameInput = new JTextField();
87 | connFactNameInput.setEditable(false);
88 | connFactNameInput.setText("ConnectionFactory");
89 | connFactNameLabel.setHorizontalAlignment(JLabel.RIGHT);
90 |
91 | JLabel providerUrlLabel = new JLabel("Provider URL");
92 | providerUrlInput = new JTextField();
93 | providerUrlLabel.setHorizontalAlignment(JLabel.RIGHT);
94 |
95 | JLabel usernameLabel = new JLabel("Username");
96 | usernameInput = new JTextField();
97 | usernameLabel.setHorizontalAlignment(JLabel.RIGHT);
98 |
99 | JLabel passwordLabel = new JLabel("Password");
100 | passwordInput = new JPasswordField();
101 | passwordLabel.setHorizontalAlignment(JLabel.RIGHT);
102 |
103 | JPanel testConfigPanel = new JPanel();
104 | testConfigButton = new JButton("Test Configuration");
105 | testConfigButton.addActionListener(new TestJmsConfiguration());
106 | testConfigPanel.add(testConfigButton);
107 |
108 | gbc.gridx = 0;
109 | gbc.gridy = 0;
110 | gbc.weightx = 0.0;
111 | configPanel.add(ctxFactoryClassLabel, gbc);
112 | gbc.gridx = 1;
113 | gbc.gridy = 0;
114 | gbc.fill = GridBagConstraints.HORIZONTAL;
115 | gbc.weightx = 1.0;
116 | configPanel.add(ctxFactoryClassInput, gbc);
117 | gbc.gridx = 0;
118 | gbc.gridy = 1;
119 | gbc.weightx = 0.0;
120 | gbc.fill = GridBagConstraints.HORIZONTAL;
121 | configPanel.add(connFactNameLabel, gbc);
122 | gbc.gridx = 1;
123 | gbc.gridy = 1;
124 | gbc.weightx = 1.0;
125 | gbc.fill = GridBagConstraints.HORIZONTAL;
126 | configPanel.add(connFactNameInput, gbc);
127 |
128 | gbc.gridx = 0;
129 | gbc.gridy = 2;
130 | gbc.weightx = 0.0;
131 | gbc.fill = GridBagConstraints.HORIZONTAL;
132 | configPanel.add(providerUrlLabel, gbc);
133 | gbc.gridx = 1;
134 | gbc.gridy = 2;
135 | gbc.weightx = 1.0;
136 | gbc.fill = GridBagConstraints.HORIZONTAL;
137 | configPanel.add(providerUrlInput, gbc);
138 |
139 | gbc.gridx = 0;
140 | gbc.gridy = 3;
141 | gbc.weightx = 0.0;
142 | gbc.fill = GridBagConstraints.HORIZONTAL;
143 | configPanel.add(usernameLabel, gbc);
144 | gbc.gridx = 1;
145 | gbc.gridy = 3;
146 | gbc.weightx = 1.0;
147 | gbc.fill = GridBagConstraints.HORIZONTAL;
148 | configPanel.add(usernameInput, gbc);
149 | gbc.gridx = 0;
150 | gbc.gridy = 4;
151 | gbc.weightx = 0.0;
152 | gbc.fill = GridBagConstraints.HORIZONTAL;
153 | configPanel.add(passwordLabel, gbc);
154 | gbc.gridx = 1;
155 | gbc.gridy = 4;
156 | gbc.weightx = 1.0;
157 | gbc.fill = GridBagConstraints.HORIZONTAL;
158 | configPanel.add(passwordInput, gbc);
159 |
160 |
161 | gbc.gridx = 0;
162 | gbc.gridwidth = 2;
163 | gbc.gridy = 5;
164 | gbc.weightx = 1.0;
165 | gbc.fill = GridBagConstraints.HORIZONTAL;
166 | configPanel.add(testConfigPanel, gbc);
167 |
168 | GridBagConstraints masterGbc = new GridBagConstraints();
169 | masterGbc.gridx = 0;
170 | masterGbc.gridy = 0;
171 | masterGbc.anchor = GridBagConstraints.NORTHWEST;
172 |
173 | this.add(configPanel, masterGbc);
174 | this.title = "JMS Config";
175 |
176 | }
177 |
178 | class TestJmsConfiguration implements ActionListener {
179 | private String username;
180 | private String connFactName;
181 | private String ctxFactoryClass;
182 | private String providerUrl;
183 | private String password;
184 | private JmsConfigTestWorker jmsConfigTest;
185 |
186 | public TestJmsConfiguration() {
187 |
188 | }
189 |
190 | public void actionPerformed(ActionEvent e) {
191 | connFactName = connFactNameInput.getText();
192 | ctxFactoryClass = ctxFactoryClassInput.getText();
193 | providerUrl = providerUrlInput.getText();
194 | username = usernameInput.getText();
195 | username = usernameInput.getText();
196 | char[] tpassword = passwordInput.getPassword();
197 | password = new String(tpassword);
198 |
199 | if(JmsHelper.isStringNullOrEmpty(connFactName)
200 | || JmsHelper.isStringNullOrEmpty(ctxFactoryClass)
201 | || JmsHelper.isStringNullOrEmpty(providerUrl))
202 | {
203 | JOptionPane.showMessageDialog(null, "One of Connection Factory, Provider URL or Context Factory Name is or empty", "Error", JOptionPane.ERROR_MESSAGE);
204 | return;
205 | }
206 |
207 | try {
208 | jmsConfigTest = new JmsConfigTestWorker(ctxFactoryClass, connFactName, providerUrl, username, password);
209 | Thread t = new Thread(jmsConfigTest);
210 | t.start();
211 | } catch (JmsDiggerException ex) {
212 | String s = "An error has occured while creating a JmsConfigTestWorker";
213 | LOG.info(s, ex);
214 | JmsGuiCommon.showErrorAndLogMessage(s);
215 | }
216 |
217 | }
218 | }
219 |
220 |
221 | class JmsConfigTestWorker implements Runnable {
222 | private JmsInitialContextFactory contextFactory;
223 | private InitialContext ctx;
224 | private JmsLoginInfo loginInfo;
225 | private JmsAuthentication jmsAuthn;
226 | private boolean result;
227 |
228 |
229 |
230 | public JmsConfigTestWorker(String ctxFactoryClass, String connFactName, String providerUrl, String username, String password) throws JmsDiggerException {
231 | contextFactory = new JmsInitialContextFactory(ctxFactoryClass, providerUrl);
232 | contextFactory.addConnectionFactory(connFactName);
233 | ctx = contextFactory.getInitialContext();
234 | loginInfo = new JmsLoginInfo(username, password);
235 | jmsAuthn = new JmsAuthentication(ctx, connFactName);
236 | this.result = false;
237 |
238 | }
239 |
240 | public void run() {
241 | EventQueue.invokeLater(new Runnable() {
242 | public void run() {
243 | testConfigButton.setEnabled(false);
244 | }
245 | });
246 |
247 | try {
248 | result = jmsAuthn.isLoginInfoValid(loginInfo);
249 | EventQueue.invokeLater(new Runnable() {
250 | public void run() {
251 | if(result == true)
252 | JOptionPane.showMessageDialog(null, "Configuration parameters OK!", "Success", JOptionPane.INFORMATION_MESSAGE);
253 | else
254 | JOptionPane.showMessageDialog(null, "Connection failed, please check logs for more details.", "Failure", JOptionPane.ERROR_MESSAGE);
255 | }
256 | });
257 |
258 |
259 | } catch (JmsDiggerException e) {
260 | String errStr = "An error occured while checking login credentials";
261 | LOG.info(errStr, e);
262 | JmsGuiCommon.showErrorAndLogMessage(errStr);
263 | } finally {
264 | EventQueue.invokeLater(new Runnable() {
265 | public void run() {
266 | testConfigButton.setEnabled(true);
267 | }
268 | });
269 | }
270 |
271 | }
272 |
273 | }
274 |
275 | }
276 |
--------------------------------------------------------------------------------
/src/main/java/com/mcafee/gui/JmsDiggerFrame.java:
--------------------------------------------------------------------------------
1 | package com.mcafee.gui;
2 |
3 | import java.awt.BorderLayout;
4 | import java.awt.GridLayout;
5 | import java.awt.Image;
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 |
9 | import javax.imageio.ImageIO;
10 | import javax.swing.JFrame;
11 | import javax.swing.JPanel;
12 | import javax.swing.JTabbedPane;
13 | import javax.swing.SwingUtilities;
14 |
15 | import org.slf4j.Logger;
16 | import org.slf4j.LoggerFactory;
17 |
18 | import com.mcafee.JmsDiggerException;
19 |
20 | /**
21 | *
22 | * @author Gursev Singh Kalra @ McAfee, Inc.
23 | *
24 | */
25 | class JmsDiggerFrame extends JFrame {
26 |
27 | private static final long serialVersionUID = 1L;
28 | private static final int WIDTH = 700;
29 | private static final int HEIGHT = 690;
30 | private static final Logger LOG = LoggerFactory.getLogger(JmsDiggerFrame.class);
31 |
32 | public JmsDiggerFrame() {
33 |
34 | }
35 |
36 | public JmsDiggerFrame(String name) throws IOException {
37 | super(name);
38 | }
39 |
40 | public String getString() {
41 | return "string";
42 | }
43 |
44 | private static void createAndShowGUI() throws JmsDiggerException, IOException {
45 | JmsDiggerFrame jmsDiggerFrame = new JmsDiggerFrame("JMSDigger 0.1.1.0");
46 |
47 | ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
48 | InputStream inputStream = classLoader.getResourceAsStream("fs_icon_32.png");
49 | Image fsIcon = ImageIO.read(inputStream);
50 | jmsDiggerFrame.setIconImage(fsIcon);
51 |
52 | jmsDiggerFrame.setSize(WIDTH, HEIGHT);
53 | jmsDiggerFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
54 |
55 | JPanel jmsDiggerParentPanel = new JPanel(new GridLayout(1, 1));
56 | JTabbedPane tabbedPane = new JTabbedPane();
57 | tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
58 | JmsConfigTab jmsConfigTab = new JmsConfigTab();
59 | JmsAuthenticationTab authenticationTab = new JmsAuthenticationTab(jmsConfigTab);
60 | JmsDumpDestinationTab dumpTab = new JmsDumpDestinationTab(jmsConfigTab);
61 | JmsDurableSubscriberTab durableSubscriberTab = new JmsDurableSubscriberTab(jmsConfigTab);
62 | AmqOpsTab amqOpsTab = new AmqOpsTab(jmsConfigTab);
63 | JMSDiggerAboutTab aboutTab = new JMSDiggerAboutTab();
64 |
65 | // All the tabs will be added here
66 | tabbedPane.add(jmsConfigTab.getTitle(), jmsConfigTab);
67 | tabbedPane.add(authenticationTab.getTitle(), authenticationTab);
68 | tabbedPane.add(amqOpsTab.getTitle(), amqOpsTab);
69 | tabbedPane.add(dumpTab.getTitle(), dumpTab);
70 | tabbedPane.add(durableSubscriberTab.getTitle(), durableSubscriberTab);
71 | tabbedPane.add(aboutTab.getTitle(), aboutTab);
72 |
73 | jmsDiggerParentPanel.add(tabbedPane);
74 | jmsDiggerFrame.add(jmsDiggerParentPanel, BorderLayout.NORTH);
75 | jmsDiggerFrame.setVisible(true);
76 | }
77 |
78 |
79 | /**
80 | * @param args
81 | */
82 | public static void main(String[] args) {
83 | SwingUtilities.invokeLater(new Runnable() {
84 | public void run() {
85 | try {
86 | createAndShowGUI();
87 | } catch (JmsDiggerException e) {
88 | String errStr = "An error occured while creating JMSDigger GUI";
89 | LOG.info(errStr, e);
90 | JmsGuiCommon.showErrorAndLogMessage(errStr);
91 | } catch (IOException e) {
92 | String errStr = "An error occured while creating JMSDigger GUI";
93 | LOG.info(errStr, e);
94 | JmsGuiCommon.showErrorAndLogMessage(errStr);
95 | }
96 | }
97 | });
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/main/java/com/mcafee/gui/JmsDumpDestinationTab.java:
--------------------------------------------------------------------------------
1 | package com.mcafee.gui;
2 |
3 | import java.awt.FlowLayout;
4 | import java.awt.GridBagConstraints;
5 | import java.awt.GridBagLayout;
6 | import java.awt.Insets;
7 | import java.awt.event.ActionEvent;
8 | import java.awt.event.ActionListener;
9 | import java.io.File;
10 | import java.io.IOException;
11 |
12 | import javax.jms.JMSException;
13 | import javax.naming.InitialContext;
14 | import javax.naming.NamingException;
15 | import javax.swing.ButtonGroup;
16 | import javax.swing.JButton;
17 | import javax.swing.JFileChooser;
18 | import javax.swing.JLabel;
19 | import javax.swing.JOptionPane;
20 | import javax.swing.JPanel;
21 | import javax.swing.JRadioButton;
22 | import javax.swing.JSpinner;
23 | import javax.swing.JTextField;
24 | import javax.swing.SpinnerNumberModel;
25 | import javax.swing.SwingWorker;
26 |
27 | import org.slf4j.Logger;
28 | import org.slf4j.LoggerFactory;
29 |
30 | import com.mcafee.JmsDestination;
31 | import com.mcafee.JmsDiggerException;
32 | import com.mcafee.JmsDumpDestination;
33 | import com.mcafee.JmsHelper;
34 | import com.mcafee.JmsLoginInfo;
35 | import com.mcafee.MessageCountUpdater;
36 |
37 | /**
38 | *
39 | * @author Gursev Singh Kalra @ McAfee, Inc.
40 | *
41 | */
42 | public class JmsDumpDestinationTab extends JPanel {
43 |
44 |
45 | /**
46 | *
47 | */
48 | private static final Logger LOG = LoggerFactory.getLogger(JmsDumpDestinationTab.class);
49 | private static final long serialVersionUID = 1L;
50 | private String title;
51 | private JmsConfigTab jmsConfigTab;
52 | private static int space = 5;
53 | private JLabel writtenMsgCountLabel;
54 | private JTextField durableSubsNameInput;
55 | private JTextField clientIdInput;
56 | private JTextField messageSelectorInput;
57 | private JTextField destNameInput;
58 | private JButton startButton;
59 | private JButton stopButton;
60 | private SpinnerNumberModel spinnerModel;
61 | private JSpinner msgCountSpinner;
62 | private JTextField outputDirPath;
63 | private JButton outputDirSelectorButton;
64 | private JRadioButton topicRadio;
65 | private JRadioButton queueRadio;
66 | private JRadioButton durableRadio;
67 | private ButtonGroup bg;
68 | private DestinationDumpWorker destinationDumpWorker;
69 |
70 | public String getTitle() {
71 | return title;
72 | }
73 |
74 | public void enableDisableInputs(boolean status) {
75 | clientIdInput.setEditable(status);
76 | durableSubsNameInput.setEditable(status);
77 | }
78 |
79 | public void enableInputs() {
80 | enableDisableInputs(true);
81 | }
82 |
83 | public void disableInputs() {
84 | enableDisableInputs(false);
85 | clientIdInput.setText("");
86 | durableSubsNameInput.setText("");
87 | }
88 |
89 | public JmsDumpDestinationTab(JmsConfigTab jmsConfigTab) {
90 | this.jmsConfigTab = jmsConfigTab;
91 | GridBagConstraints masterGbc = new GridBagConstraints();
92 | JPanel dumpDestinationPanel = new JPanel(new GridBagLayout());
93 |
94 | Insets inset = new Insets(space, space, space, space);
95 | masterGbc.insets = inset;
96 | GridBagConstraints gbc = new GridBagConstraints();
97 |
98 | JLabel dstNameLabel = new JLabel("Destination Name");
99 | destNameInput = new JTextField();
100 | dstNameLabel.setHorizontalAlignment(JLabel.RIGHT);
101 |
102 | JLabel dstTypeLabel = new JLabel("Destination Type");
103 | dstTypeLabel.setHorizontalAlignment(JLabel.RIGHT);
104 | topicRadio = new JRadioButton("Topic");
105 | topicRadio.addActionListener(new ActionListener() {
106 | public void actionPerformed(ActionEvent e) {
107 | disableInputs();
108 | }
109 | });
110 |
111 |
112 | topicRadio.setSelected(true);
113 | queueRadio = new JRadioButton("Queue");
114 | queueRadio.addActionListener(new ActionListener() {
115 | public void actionPerformed(ActionEvent e) {
116 | disableInputs();
117 | }
118 | });
119 |
120 |
121 | durableRadio = new JRadioButton("Durable Subscriber");
122 | durableRadio.addActionListener(new ActionListener() {
123 | public void actionPerformed(ActionEvent e) {
124 | enableInputs();
125 | }
126 | });
127 |
128 | bg = new ButtonGroup();
129 | bg.add(topicRadio);
130 | bg.add(queueRadio);
131 | bg.add(durableRadio);
132 |
133 | JPanel dumpRadioPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
134 | gbc.gridx = 0;
135 | gbc.gridy = 0;
136 | dumpRadioPanel.add(topicRadio, gbc);
137 | gbc.gridx = 1;
138 | gbc.gridy = 0;
139 | dumpRadioPanel.add(queueRadio, gbc);
140 | gbc.gridx = 2;
141 | gbc.gridy = 0;
142 | dumpRadioPanel.add(durableRadio, gbc);
143 |
144 |
145 | JLabel messageSelectorLabel = new JLabel("Message Selector");
146 | messageSelectorInput = new JTextField();
147 | messageSelectorLabel.setHorizontalAlignment(JLabel.RIGHT);
148 |
149 | JLabel clientIdLabel = new JLabel("Client ID (for durable Subscribers)");
150 | clientIdInput = new JTextField();
151 | clientIdLabel.setHorizontalAlignment(JLabel.RIGHT);
152 | //JPasswordField confirmPasswordInput = new JPasswordField();
153 |
154 | JLabel durableSubsNameLabel = new JLabel("Durable Subscriber Name");
155 | durableSubsNameInput = new JTextField();
156 | durableSubsNameLabel.setHorizontalAlignment(JLabel.RIGHT);
157 |
158 | durableSubsNameLabel.setHorizontalAlignment(JLabel.RIGHT);
159 |
160 | JLabel outputDirLabel = new JLabel("Output Directory");
161 | outputDirLabel.setHorizontalAlignment(JLabel.RIGHT);
162 | outputDirSelectorButton = new JButton("Select");
163 | outputDirSelectorButton.addActionListener(new ActionListener() {
164 | public void actionPerformed(ActionEvent e) {
165 | JFileChooser fileChooser = new JFileChooser();
166 | fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
167 | fileChooser.setCurrentDirectory(new File("/"));
168 | boolean validDirectory = false;
169 | //Scanner fileScanner;
170 |
171 | while(validDirectory != true) {
172 | int result = fileChooser.showOpenDialog(null);
173 | if(result == JFileChooser.CANCEL_OPTION)
174 | return;
175 | if(result == JFileChooser.APPROVE_OPTION) {
176 | File file = fileChooser.getSelectedFile();
177 | String filePath = file.getAbsolutePath();
178 | File check = new File(filePath);
179 | if(!check.exists()) {
180 | JOptionPane.showMessageDialog(null, "Invalid directory path", "Failure", JOptionPane.ERROR_MESSAGE);
181 |
182 | } else {
183 | outputDirPath.setText(file.getAbsolutePath());
184 | validDirectory = true;
185 | }
186 | }
187 | }
188 |
189 | }
190 | });
191 |
192 | outputDirPath = new JTextField();
193 | String separator = System.getProperty("file.separator");
194 | outputDirPath.setText(System.getProperty("user.home")+separator+"jmsdigger");
195 |
196 | outputDirPath.setEditable(false);
197 | //outputDirPath.setEditable(false);
198 | JPanel outputDirSelectorPanel = new JPanel(new GridBagLayout());
199 | gbc = new GridBagConstraints();
200 | gbc.gridx = 0;
201 | gbc.gridy = 0;
202 | gbc.fill = GridBagConstraints.HORIZONTAL;
203 | gbc.weightx = 1.0;
204 |
205 | outputDirSelectorPanel.add(outputDirPath, gbc);
206 | gbc = new GridBagConstraints();
207 | gbc.gridx = 2;
208 | gbc.gridy = 0;
209 | outputDirSelectorPanel.add(outputDirSelectorButton, gbc);
210 |
211 | JLabel msgCountLabel = new JLabel("Messages to Dump (Count)");
212 | msgCountLabel.setHorizontalAlignment(JLabel.RIGHT);
213 | spinnerModel = new SpinnerNumberModel(10, 0, 9999, 1);
214 | JPanel countStartStopPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
215 | msgCountSpinner = new JSpinner(spinnerModel);
216 | startButton = new JButton("Start Dump");
217 | startButton.addActionListener(new TriggerDestinationDump());
218 | stopButton = new JButton("Stop Dump");
219 |
220 | stopButton.setEnabled(false);
221 | gbc = new GridBagConstraints();
222 | gbc.gridx = 0;
223 | gbc.gridy = 0;
224 | gbc.weightx = 0.0;
225 | gbc.fill = GridBagConstraints.NONE;
226 |
227 | countStartStopPanel.add(msgCountSpinner, gbc);
228 |
229 | gbc.weightx = 1.0;
230 | gbc.fill = GridBagConstraints.BOTH;
231 |
232 | gbc.gridx = 0;
233 | gbc.gridy = 1;
234 | countStartStopPanel.add(startButton, gbc);
235 | gbc.gridx = 0;
236 | gbc.gridy = 2;
237 | countStartStopPanel.add(stopButton, gbc);
238 | durableSubsNameLabel.setHorizontalAlignment(JLabel.RIGHT);
239 |
240 | JLabel writtenMsgLabel = new JLabel("Messages Written");
241 | writtenMsgLabel.setHorizontalAlignment(JLabel.RIGHT);
242 | writtenMsgCountLabel = new JLabel("--");
243 | writtenMsgCountLabel.setHorizontalAlignment(JLabel.LEFT);
244 |
245 |
246 | masterGbc.gridx = 0;
247 | masterGbc.gridy = 0;
248 | masterGbc.fill = GridBagConstraints.HORIZONTAL;
249 | masterGbc.weightx = 0.0;
250 | dumpDestinationPanel.add(dstNameLabel, masterGbc);
251 | masterGbc.gridx = 1;
252 | masterGbc.gridy = 0;
253 | masterGbc.fill = GridBagConstraints.HORIZONTAL;
254 | masterGbc.weightx = 1.0;
255 | dumpDestinationPanel.add(destNameInput, masterGbc);
256 |
257 | masterGbc.gridx = 0;
258 | masterGbc.gridy = 1;
259 | masterGbc.weightx = 0.0;
260 | masterGbc.fill = GridBagConstraints.HORIZONTAL;
261 | dumpDestinationPanel.add(dstTypeLabel, masterGbc);
262 | masterGbc.gridx = 1;
263 | masterGbc.gridy = 1;
264 | masterGbc.weightx = 1.0;
265 | masterGbc.fill = GridBagConstraints.HORIZONTAL;
266 | dumpDestinationPanel.add(dumpRadioPanel, masterGbc);
267 |
268 | masterGbc.gridx = 0;
269 | masterGbc.gridy = 2;
270 | masterGbc.weightx = 0.0;
271 | masterGbc.fill = GridBagConstraints.HORIZONTAL;
272 | dumpDestinationPanel.add(messageSelectorLabel, masterGbc);
273 | masterGbc.gridx = 1;
274 | masterGbc.gridy = 2;
275 | masterGbc.weightx = 1.0;
276 | masterGbc.fill = GridBagConstraints.HORIZONTAL;
277 | dumpDestinationPanel.add(messageSelectorInput, masterGbc);
278 |
279 | masterGbc.gridx = 0;
280 | masterGbc.gridy = 3;
281 | masterGbc.weightx = 0.0;
282 | masterGbc.fill = GridBagConstraints.HORIZONTAL;
283 | dumpDestinationPanel.add(clientIdLabel, masterGbc);
284 | masterGbc.gridx = 1;
285 | masterGbc.gridy = 3;
286 | masterGbc.weightx = 1.0;
287 | masterGbc.fill = GridBagConstraints.HORIZONTAL;
288 | dumpDestinationPanel.add(clientIdInput, masterGbc);
289 |
290 | masterGbc.gridx = 0;
291 | masterGbc.gridy = 4;
292 | masterGbc.weightx = 0.0;
293 | masterGbc.fill = GridBagConstraints.HORIZONTAL;
294 | dumpDestinationPanel.add(durableSubsNameLabel, masterGbc);
295 | masterGbc.gridx = 1;
296 | masterGbc.gridy = 4;
297 | masterGbc.weightx = 0.0;
298 | masterGbc.fill = GridBagConstraints.HORIZONTAL;
299 | dumpDestinationPanel.add(durableSubsNameInput, masterGbc);
300 |
301 | masterGbc.gridx = 0;
302 | masterGbc.gridy = 5;
303 | masterGbc.weightx = 0.0;
304 | masterGbc.fill = GridBagConstraints.HORIZONTAL;
305 | dumpDestinationPanel.add(outputDirLabel, masterGbc);
306 | masterGbc.gridx = 1;
307 | masterGbc.gridy = 5;
308 | masterGbc.weightx = 1.0;
309 | masterGbc.fill = GridBagConstraints.HORIZONTAL;
310 | dumpDestinationPanel.add(outputDirSelectorPanel, masterGbc);
311 |
312 | masterGbc.gridx = 0;
313 | masterGbc.gridy = 6;
314 | masterGbc.weightx = 0.0;
315 | masterGbc.fill = GridBagConstraints.HORIZONTAL;
316 | dumpDestinationPanel.add(msgCountLabel, masterGbc);
317 | masterGbc.gridx = 1;
318 | masterGbc.gridy = 6;
319 | masterGbc.weightx = 1.0;
320 | masterGbc.fill = GridBagConstraints.HORIZONTAL;
321 | dumpDestinationPanel.add(countStartStopPanel, masterGbc);
322 |
323 | masterGbc.gridx = 0;
324 | masterGbc.gridy = 7;
325 | masterGbc.weightx = 0.0;
326 | masterGbc.fill = GridBagConstraints.HORIZONTAL;
327 | dumpDestinationPanel.add(writtenMsgLabel, masterGbc);
328 | masterGbc.gridx = 1;
329 | masterGbc.gridy = 7;
330 | masterGbc.weightx = 1.0;
331 | masterGbc.fill = GridBagConstraints.HORIZONTAL;
332 | dumpDestinationPanel.add(writtenMsgCountLabel, masterGbc);
333 |
334 | masterGbc = new GridBagConstraints();
335 | masterGbc.gridx = 0;
336 | masterGbc.gridy = 0;
337 | masterGbc.anchor = GridBagConstraints.NORTHWEST;
338 | this.add(dumpDestinationPanel, masterGbc);
339 |
340 | disableInputs();
341 | this.title = "Dump Destinations";
342 |
343 | }
344 |
345 | class TriggerDestinationDump implements ActionListener {
346 |
347 | public void actionPerformed(ActionEvent arg0) {
348 | JmsDestination destinationType = JmsDestination.TOPIC;
349 | if(JmsHelper.isStringNullOrEmpty(destNameInput.getText())) {
350 | JOptionPane.showMessageDialog(null, "Destination name is empty", "Error", JOptionPane.ERROR_MESSAGE);
351 | return;
352 | }
353 |
354 | if(durableRadio.isSelected()) {
355 | if(JmsHelper.isStringNullOrEmpty(clientIdInput.getText()) || JmsHelper.isStringNullOrEmpty(durableSubsNameInput.getText())) {
356 | JOptionPane.showMessageDialog(null, "Client ID or Durable subscriber name not present", "Error", JOptionPane.ERROR_MESSAGE);
357 | return;
358 | }
359 | destinationType = JmsDestination.DURABLESUBSCRIBER;
360 | } else {
361 | if(topicRadio.isSelected()) {
362 | destinationType = JmsDestination.TOPIC;
363 | } else {
364 | destinationType = JmsDestination.QUEUE;
365 | }
366 | }
367 |
368 | try {
369 | //System.out.println("here");
370 | destinationDumpWorker = new DestinationDumpWorker(destinationType);
371 | for(ActionListener a : stopButton.getActionListeners()) {
372 | stopButton.removeActionListener(a);
373 | }
374 | stopButton.addActionListener(new ActionListener() {
375 | public void actionPerformed(ActionEvent arg0) {
376 | destinationDumpWorker.cancel(true);
377 | }
378 | });
379 | destinationDumpWorker.execute();
380 | writtenMsgCountLabel.setText("0");
381 | disableButtons();
382 | } catch (JmsDiggerException ex) {
383 | String errStr = "An execption occured while triggering destination dump";
384 | LOG.info(errStr, ex);
385 | JmsGuiCommon.showErrorAndLogMessage(ex.getMessage());
386 | } catch (NamingException ex) {
387 | String errStr = "An NamingException occured while triggering a destination dump";
388 | LOG.info(errStr, ex);
389 | JmsGuiCommon.showErrorAndLogMessage(ex.getMessage());
390 | } catch (JMSException ex) {
391 | LOG.info("", ex);
392 | JmsGuiCommon.showErrorAndLogMessage(ex.getMessage());
393 | }
394 |
395 | }
396 |
397 | private void disableButtons() {
398 | startButton.setEnabled(false);
399 | outputDirSelectorButton.setEnabled(false);
400 | stopButton.setEnabled(true);
401 | }
402 | }
403 |
404 | class DestinationDumpWorker extends SwingWorker {
405 | private String destinationName;
406 | private JmsDestination destinationType;
407 | private String msgSelector;
408 | private String clientId;
409 | private String durableSubscriberName;
410 | private String outputDirectory;
411 | private int count;
412 | private JmsDumpDestination destinationDumper;
413 | private JmsConfig jmsConfig;
414 | private InitialContext initialContext;
415 | //private Connection connection;
416 | //private ConnectionFactory connFact;
417 | private MessageCountUpdater messageCountUpdateObject;
418 | private JmsLoginInfo loginInfo;
419 |
420 |
421 | public DestinationDumpWorker(JmsDestination destinationType) throws NamingException, JMSException {
422 | jmsConfig = jmsConfigTab.getJmsConfig();
423 | String connectionFactoryName = jmsConfig.getConnFactName();
424 | this.destinationName = destNameInput.getText();
425 | this.destinationType = destinationType;
426 | this.msgSelector = messageSelectorInput.getText();
427 | this.clientId = clientIdInput.getText();
428 | this.durableSubscriberName = durableSubsNameInput.getText();
429 | this.outputDirectory = outputDirPath.getText();
430 | this.count = (Integer) msgCountSpinner.getValue();
431 |
432 | if(this.destinationType == JmsDestination.QUEUE)
433 | jmsConfig.addQueue(this.destinationName);
434 | else
435 | jmsConfig.addTopic(this.destinationName);
436 | this.initialContext = jmsConfig.buildInitialContext();
437 | this.loginInfo = jmsConfig.getLoginInfo();
438 | //this.connFact = (ConnectionFactory) initialContext.lookup(connectionFactoryName);
439 | //connection = (Connection) connFact.createConnection();
440 | messageCountUpdateObject = new MessageCountUpdater(writtenMsgCountLabel);
441 | destinationDumper = new JmsDumpDestination(this.initialContext, this.destinationName, connectionFactoryName, this.msgSelector, this.loginInfo);
442 | destinationDumper.setTargetDirectory(this.outputDirectory);
443 | destinationDumper.setClientId(this.clientId);
444 | destinationDumper.setDurableSubscriberName(this.durableSubscriberName);
445 | destinationDumper.setMsgCountToDump(count);
446 | destinationDumper.setMessageCountUpdater(messageCountUpdateObject);
447 | }
448 |
449 | private void enableButtons() {
450 | startButton.setEnabled(true);
451 | outputDirSelectorButton.setEnabled(true);
452 | stopButton.setEnabled(false);
453 | }
454 |
455 | @Override
456 | protected String doInBackground() throws Exception {
457 | // System.out.println("Doing in background");
458 | //Thread.sleep(5*1000);
459 | destinationDumper.init();
460 | destinationDumper.dump();
461 | return null;
462 | }
463 |
464 | @Override
465 | public void done() {
466 | Thread t = new Thread(
467 | new Runnable() {
468 | public void run() {
469 | while(true) {
470 | if(!isCancelled()) {
471 | if(!destinationDumper.isDumpComplete()) {
472 | try {
473 | //System.out.println(destinationDumper.isDumpComplete() + "\tSleeping now ======================\t" + isCancelled());
474 | Thread.sleep(1 * 1000);
475 | } catch (InterruptedException e) {
476 | LOG.info("The thread was interrupted", e);
477 | JmsGuiCommon.showErrorAndLogMessage(e.getMessage());
478 | }
479 | continue;
480 | }
481 | }
482 | try {
483 | enableButtons();
484 | destinationDumper.close();
485 | break;
486 | } catch (JMSException ex) {
487 | LOG.info("Destination Dumper could not be closed", ex);
488 | JmsGuiCommon.showErrorAndLogMessage(ex.getMessage());
489 | } catch (IOException ex) {
490 | LOG.info("An IOException has occured", ex);
491 | JmsGuiCommon.showErrorAndLogMessage(ex.getMessage());
492 | }
493 | }
494 | }
495 | });
496 | t.start();
497 | }
498 | }
499 | }
500 |
--------------------------------------------------------------------------------
/src/main/java/com/mcafee/gui/JmsDurableSubscriberTab.java:
--------------------------------------------------------------------------------
1 | package com.mcafee.gui;
2 |
3 | import java.awt.FlowLayout;
4 | import java.awt.GridBagConstraints;
5 | import java.awt.GridBagLayout;
6 | import java.awt.Insets;
7 | import java.awt.event.ActionEvent;
8 | import java.awt.event.ActionListener;
9 | import java.lang.reflect.Array;
10 | import java.util.ArrayList;
11 | import java.util.List;
12 | import java.util.concurrent.ExecutionException;
13 |
14 | import javax.naming.InitialContext;
15 | import javax.swing.BorderFactory;
16 | import javax.swing.JButton;
17 | import javax.swing.JLabel;
18 | import javax.swing.JOptionPane;
19 | import javax.swing.JPanel;
20 | import javax.swing.JProgressBar;
21 | import javax.swing.JScrollPane;
22 | import javax.swing.JSpinner;
23 | import javax.swing.JTextArea;
24 | import javax.swing.JTextField;
25 | import javax.swing.SpinnerNumberModel;
26 | import javax.swing.SwingWorker;
27 | import javax.swing.border.Border;
28 | import javax.swing.border.EtchedBorder;
29 |
30 | import org.slf4j.Logger;
31 | import org.slf4j.LoggerFactory;
32 |
33 | import com.mcafee.JmsDiggerException;
34 | import com.mcafee.JmsDurableSubscriberManipulator;
35 | import com.mcafee.JmsHelper;
36 |
37 | /**
38 | *
39 | * @author Gursev Singh Kalra @ McAfee, Inc.
40 | *
41 | */
42 | public class JmsDurableSubscriberTab extends JPanel {
43 |
44 | /**
45 | *
46 | */
47 | private static final long serialVersionUID = 1L;
48 | private String title;
49 | private int space = 5;
50 | private JmsConfigTab jmsConfigTab;
51 | private JTextField topicNameInput;
52 | private JTextField messageSelectorInput;
53 | private JSpinner durableSubsCountSpinner;
54 | private SpinnerNumberModel spinnerModel;
55 | private JButton createMultipleDurableSubsButton;
56 | private JProgressBar progressBar;
57 | private JTextField clientIdInput;
58 | private JTextField subsNameInput;
59 | private JButton createSingleSubsButton;
60 | private JButton eraseDurableSubsButton;
61 | private JTextArea outputArea;
62 | private JmsConfig jmsConfig;
63 | private InitialContext initialContext;
64 | private JmsDurableSubscriberManipulator manipulator ;
65 | private static final Logger LOG = LoggerFactory.getLogger(JmsDurableSubscriberTab.class);
66 |
67 |
68 | public String getTitle() {
69 | return title;
70 | }
71 |
72 | public JmsDurableSubscriberTab(JmsConfigTab jmsConfigTab) throws JmsDiggerException {
73 | this.jmsConfigTab = jmsConfigTab;
74 | //jmsConfig = this.jmsConfigTab.getJmsConfig();
75 | /**
76 | * The following line is commented out to enable late Initial Context generation.
77 | * There are additional two lines of code added see comments beginning __LAZY__ below.
78 | * This mostly appears to be a workaround, but i will have to create a more robust library.
79 | */
80 | //initialContext = jmsConfig.buildInitialContext();
81 | JPanel masterPanel = new JPanel(new GridBagLayout());
82 | title = "Durable Subscribers";
83 | TriggerDurableSubscriberCreation trigger = new TriggerDurableSubscriberCreation();
84 |
85 | JPanel nameFilterPanel = new JPanel(new GridBagLayout());
86 | GridBagConstraints masterGbc = new GridBagConstraints();
87 | GridBagConstraints gbc = new GridBagConstraints();
88 | Border border = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
89 | Insets inset = new Insets(space, space, space, space);
90 | Insets masterInset = new Insets(space * 2, space * 2, space * 2, space * 2);
91 | masterGbc.insets = masterInset;
92 |
93 | gbc.insets = inset;
94 | gbc.fill = GridBagConstraints.HORIZONTAL;
95 |
96 | JLabel topicNameLabel = new JLabel("Topic Name");
97 | gbc.gridx = 0;
98 | gbc.gridy = 0;
99 | topicNameLabel.setHorizontalAlignment(JLabel.RIGHT);
100 | nameFilterPanel.add(topicNameLabel, gbc);
101 | topicNameInput = new JTextField(30);
102 | gbc.gridx = 1;
103 | gbc.gridy = 0;
104 | nameFilterPanel.add(topicNameInput, gbc);
105 |
106 | JLabel filterLabel = new JLabel("Message Selector");
107 | gbc.gridx = 0;
108 | gbc.gridy = 1;
109 | filterLabel.setHorizontalAlignment(JLabel.RIGHT);
110 | nameFilterPanel.add(filterLabel, gbc);
111 | messageSelectorInput = new JTextField(30);
112 | gbc.gridx = 1;
113 | gbc.gridy = 1;
114 | nameFilterPanel.add(messageSelectorInput, gbc);
115 |
116 | masterGbc.gridx = 0;
117 | masterGbc.gridy = 0;
118 | masterGbc.anchor = GridBagConstraints.LINE_START;
119 | masterPanel.add(nameFilterPanel, masterGbc);
120 |
121 |
122 |
123 | JPanel randomCountPanel = new JPanel(new GridBagLayout());
124 | Border singleUserBorder = BorderFactory.createTitledBorder(border, "Create Multiple Durable Subscribers");
125 |
126 | spinnerModel = new SpinnerNumberModel(10, 1, 9999, 1);
127 | durableSubsCountSpinner = new JSpinner(spinnerModel);
128 | gbc = new GridBagConstraints();
129 | gbc.insets = inset;
130 | gbc.gridx = 0;
131 | gbc.gridy = 0;
132 | randomCountPanel.add(durableSubsCountSpinner, gbc);
133 | createMultipleDurableSubsButton = new JButton("Create");
134 | createMultipleDurableSubsButton.addActionListener(trigger);
135 | gbc.gridx = 1;
136 | gbc.gridy = 0;
137 | randomCountPanel.add(createMultipleDurableSubsButton, gbc);
138 |
139 |
140 | // JLabel progressLabel = new JLabel("Progress > ");
141 | // gbc.fill = GridBagConstraints.HORIZONTAL;
142 | // gbc.gridx = 0;
143 | // gbc.gridy = 1;
144 | // randomCountPanel.add(progressLabel, gbc);
145 |
146 | // progressBar = new JProgressBar();
147 | // progressBar.setBounds(0, 0, 30, 100);
148 | //
149 | // gbc.gridx = 1;
150 | // gbc.gridy = 1;
151 | // gbc.gridwidth = 2;
152 | // randomCountPanel.add(progressBar, gbc);
153 | randomCountPanel.setBorder(singleUserBorder);
154 |
155 | masterGbc = new GridBagConstraints();
156 | masterGbc.gridx = 0;
157 | masterGbc.gridy = 2;
158 | masterGbc.insets = inset;
159 | masterGbc.anchor = GridBagConstraints.LINE_START;
160 | masterGbc.fill = GridBagConstraints.HORIZONTAL;
161 | masterPanel.add(randomCountPanel, masterGbc);
162 |
163 |
164 |
165 |
166 |
167 | JPanel singleSubsPanel = new JPanel(new GridBagLayout());
168 | Border singleSubsBorder = BorderFactory.createTitledBorder(border, "Create/Erase A Durable Subscriber");
169 | gbc = new GridBagConstraints();
170 |
171 | JLabel clientIdLabel = new JLabel("Client ID");
172 | clientIdLabel.setHorizontalAlignment(JLabel.RIGHT);
173 | gbc.fill = GridBagConstraints.HORIZONTAL;
174 | gbc.insets = inset;
175 | gbc.gridx = 0;
176 | gbc.gridy = 0;
177 | singleSubsPanel.add(clientIdLabel, gbc);
178 |
179 | clientIdInput = new JTextField(30);
180 | gbc.gridx = 1;
181 | gbc.gridy = 0;
182 | singleSubsPanel.add(clientIdInput, gbc);
183 |
184 | JLabel subsNameLabel = new JLabel("Durable Subscriber Name");
185 | subsNameLabel.setHorizontalAlignment(JLabel.RIGHT);
186 | gbc.insets = inset;
187 | gbc.gridx = 0;
188 | gbc.gridy = 1;
189 | singleSubsPanel.add(subsNameLabel, gbc);
190 |
191 | subsNameInput = new JTextField(30);
192 | gbc.gridx = 1;
193 | gbc.gridy = 1;
194 | singleSubsPanel.add(subsNameInput, gbc);
195 |
196 | JPanel createButtonPanel = new JPanel(new GridBagLayout());
197 | createSingleSubsButton = new JButton("Create");
198 | createSingleSubsButton.addActionListener(trigger);
199 | gbc.gridx = 0;
200 | gbc.gridy = 0;
201 | createButtonPanel.add(createSingleSubsButton, gbc);
202 |
203 | eraseDurableSubsButton = new JButton("Erase");
204 | eraseDurableSubsButton.addActionListener(trigger);
205 | gbc.gridx = 1;
206 | gbc.gridy = 0;
207 | createButtonPanel.add(eraseDurableSubsButton, gbc);
208 |
209 | gbc.gridx = 0;
210 | gbc.gridy = 2;
211 | gbc.gridwidth = 2;
212 | singleSubsPanel.add(createButtonPanel, gbc);
213 | singleSubsPanel.setBorder(singleSubsBorder);
214 |
215 | JPanel outputBoxPanel = new JPanel(new GridBagLayout());
216 | outputArea = new JTextArea(15, 50);
217 | outputArea.setEditable(false);
218 |
219 | gbc.fill = GridBagConstraints.BOTH;
220 | gbc.gridx = 0;
221 | gbc.gridy = 0;
222 | outputBoxPanel.add(new JScrollPane(outputArea), gbc);
223 | Border outputBorder = BorderFactory.createTitledBorder(border, "Results");
224 | outputBoxPanel.setBorder(outputBorder);
225 | masterGbc.gridx = 0;
226 | masterGbc.gridy = 3;
227 | masterPanel.add(outputBoxPanel, masterGbc);
228 |
229 | /*
230 | * Pane to display progress
231 | */
232 | JPanel progressPanel = new JPanel(new GridBagLayout());
233 | JLabel progressLabel = new JLabel("Progress > ");
234 | gbc.gridx = 0;
235 | gbc.gridy = 0;
236 | gbc.fill = GridBagConstraints.NONE;
237 | progressPanel.add(progressLabel, gbc);
238 |
239 |
240 | progressBar = new JProgressBar();
241 | gbc.fill = GridBagConstraints.HORIZONTAL;
242 | gbc.gridx = 2;
243 | gbc.gridy = 0;
244 | gbc.weightx = 1.0;
245 | progressPanel.add(progressBar, gbc);
246 |
247 | masterGbc.gridx = 0;
248 | masterGbc.gridy = 4;
249 | masterGbc.fill = GridBagConstraints.HORIZONTAL;
250 | masterGbc.insets = inset;
251 | masterPanel.add(progressPanel, masterGbc);
252 |
253 |
254 | masterGbc.gridx = 0;
255 | masterGbc.gridy = 1;
256 | masterGbc.anchor = GridBagConstraints.LINE_START;
257 | masterGbc.insets = inset;
258 | masterPanel.add(singleSubsPanel, masterGbc);
259 |
260 | this.add(masterPanel, masterGbc);
261 |
262 | }
263 |
264 | class TriggerDurableSubscriberErase implements ActionListener {
265 |
266 | public void actionPerformed(ActionEvent arg0) {
267 | }
268 |
269 | }
270 |
271 | class TriggerDurableSubscriberCreation implements ActionListener {
272 |
273 | public void disableAllButtons() {
274 | createMultipleDurableSubsButton.setEnabled(false);
275 | createSingleSubsButton.setEnabled(false);
276 | eraseDurableSubsButton.setEnabled(false);
277 | }
278 |
279 | public void actionPerformed(ActionEvent event) {
280 | DurableSubscriberWorker durableSubscriberWorker;
281 | if(JmsHelper.isStringNullOrEmpty(topicNameInput.getText())) {
282 | JOptionPane.showMessageDialog(null, "Topic name cannot be empty or null", "Error", JOptionPane.ERROR_MESSAGE);
283 | return;
284 | }
285 |
286 | if(event.getSource() == eraseDurableSubsButton) {
287 | if(JmsHelper.isStringNullOrEmpty(subsNameInput.getText()) || JmsHelper.isStringNullOrEmpty(clientIdInput.getText())) {
288 | JOptionPane.showMessageDialog(null, "Erase function requires a Client ID and Durable Subscriber Name", "Error", JOptionPane.ERROR_MESSAGE);
289 | return;
290 | }
291 | }
292 |
293 | String topicName = topicNameInput.getText();
294 | String messageSelector = messageSelectorInput.getText();
295 | int count = 1;
296 | String clientId = clientIdInput.getText();
297 | String subsName = subsNameInput.getText();
298 |
299 | ArrayList durableSubscriberNames = new ArrayList();
300 | if(JmsHelper.isStringNullOrEmpty(clientId)) {
301 | clientId = JmsHelper.getRandomString();
302 | }
303 |
304 | if(event.getSource() == createSingleSubsButton) {
305 | if(JmsHelper.isStringNullOrEmpty(subsName)) {
306 | durableSubscriberNames.add(JmsHelper.getRandomString());
307 | }
308 | else {
309 | durableSubscriberNames.add(subsName);
310 | }
311 |
312 | } else {
313 | if(event.getSource() == createMultipleDurableSubsButton) {
314 | count = (Integer) spinnerModel.getValue();
315 | for(int i = 0; i < count; i++) {
316 | durableSubscriberNames.add(JmsHelper.getRandomString());
317 | }
318 | } else if(event.getSource() == eraseDurableSubsButton) {
319 | durableSubscriberNames.add(subsName);
320 | }
321 | }
322 |
323 | disableAllButtons();
324 | //durableSubscriberWorker = new DurableSubscriberWorker(topicName, messageSelector, clientIdList, durableSubscriberNames, (Integer) spinnerModel.getValue());
325 | try {
326 | durableSubscriberWorker = new DurableSubscriberWorker(topicName, messageSelector, clientId, durableSubscriberNames, count);
327 | if(event.getSource() == eraseDurableSubsButton) {
328 | durableSubscriberWorker.setErase(true);
329 | }
330 | durableSubscriberWorker.execute();
331 | } catch (JmsDiggerException e) {
332 | LOG.info("An error has occured while creating/executing a durableSubscriberWorker", e);
333 | JmsGuiCommon.showErrorAndLogMessage(e.getMessage());
334 | }
335 | }
336 |
337 | }
338 |
339 | class DurableSubscriberWorker extends SwingWorker {
340 |
341 | String messageSelector;
342 | String topicName;
343 | ArrayList clientIdList;
344 | ArrayList durableSubscriberNames;
345 | String clientId;
346 | int count;
347 | boolean erase;
348 |
349 | public void setErase(boolean erase) {
350 | this.erase = erase;
351 | }
352 |
353 | //public DurableSubscriberWorker(String topicName, String messageSelector, ArrayList clientIdList, ArrayList durableSubscriberNames, int count) {
354 | public DurableSubscriberWorker(String topicName, String messageSelector, String clientId, ArrayList durableSubscriberNames, int count) throws JmsDiggerException {
355 | this.topicName = topicName;
356 | this.messageSelector = messageSelector;
357 | //this.clientIdList = clientIdList;
358 | this.clientId = clientId;
359 | this.durableSubscriberNames = durableSubscriberNames;
360 | this.count = count;
361 | this.erase = false;
362 |
363 | /**
364 | * __LAZY__ the addTopic call adds the topic to the initial context's environment
365 | * variables before building the initial context. Once initial context is built, it cannot be changed.
366 | * Initializing the jmsConfig here to ensure that a new configuration is generated for each button click
367 | * to accommodate for topic changes for a single run.
368 | */
369 | jmsConfig = jmsConfigTab.getJmsConfig();
370 | jmsConfig.addTopic(topicName);
371 | initialContext = jmsConfig.buildInitialContext();
372 | }
373 |
374 | public boolean isErase() {
375 | return erase;
376 | }
377 |
378 | @Override
379 | protected ProgressInfo doInBackground() throws Exception {
380 |
381 | try {
382 | manipulator = new JmsDurableSubscriberManipulator(initialContext, topicName, jmsConfig.getConnFactName(), jmsConfig.getLoginInfo());
383 | manipulator.init(clientId);
384 | } catch (JmsDiggerException ex) {
385 | LOG.info("DurableSubscriberManipulator initialization failed", ex);
386 | ProgressInfo i = new ProgressInfo(JmsHelper.exceptionStacktraceToString(ex), false, 0);
387 | return i;
388 | }
389 |
390 | //publish(new ProgressInfo("\n==================================================\n[+] Creating durable subscribers with clientID \"" + clientId+"\"" , true, 0));
391 | try {
392 | for(int i = 0; i < durableSubscriberNames.size() ; i++) {
393 | try {
394 | if(!isErase()) {
395 | manipulator.createDurableSubscriber(durableSubscriberNames.get(i), messageSelector);
396 | publish(new ProgressInfo("\n[+] Created durable subscriber \"" + durableSubscriberNames.get(i) +"\"" ,true, i*100/count));
397 | } else {
398 | manipulator.eraseDurableSubscriber(durableSubscriberNames.get(0));
399 | publish(new ProgressInfo("\n[+] Erased durable subscriber \"" + durableSubscriberNames.get(i) +"\"" ,true, 100));
400 | }
401 | } catch(JmsDiggerException ex) {
402 | if(!isErase())
403 | publish(new ProgressInfo("\n[-] Could not create durable subscriber \"" + durableSubscriberNames.get(i) +"\"" ,true, i*100/count));
404 | else
405 | publish(new ProgressInfo("\n[-] Could not erase durable subscriber \"" + durableSubscriberNames.get(i) +"\"" ,true, 100));
406 | }
407 | }
408 | } finally {
409 | /**
410 | * Very important to close the connections as ActiveMQ allows only one active connection from one clientID.
411 | * If the connection is not closed, ActiveMQ throws an exception of the following type
412 | * Caused by: javax.jms.InvalidClientIDException: Broker: localhost - Client: already connected from tcp://ipadderss:port
413 | */
414 | manipulator.close();
415 | }
416 |
417 |
418 | return new ProgressInfo("Completed", true, 100);
419 | }
420 |
421 | @Override
422 | public void process(List progressInfo) {
423 | for(ProgressInfo pInfo : progressInfo) {
424 | outputArea.append(pInfo.getDescription());
425 | }
426 | ProgressInfo pInfo = progressInfo.get(progressInfo.size()-1);
427 | progressBar.setValue(pInfo.getPercentage());
428 | }
429 |
430 |
431 | @Override
432 | public void done() {
433 | try {
434 | ProgressInfo pInfo = get();
435 | if(pInfo.isSuccessful() == false && pInfo.getPercentage() == 0) {
436 | outputArea.setText(pInfo.getDescription());
437 | JOptionPane.showMessageDialog(null, "An error has occured while creating durable subscribers", "Error", JOptionPane.ERROR_MESSAGE);
438 | } else {
439 | progressBar.setValue(pInfo.getPercentage());
440 | }
441 | } catch (InterruptedException ex) {
442 | LOG.info("", ex);
443 | JmsGuiCommon.showErrorAndLogMessage(ex.getMessage());
444 | } catch (ExecutionException ex) {
445 | LOG.info("", ex);
446 | JmsGuiCommon.showErrorAndLogMessage(ex.getMessage());
447 | }
448 | JOptionPane.showMessageDialog(null, "Done!", "", JOptionPane.INFORMATION_MESSAGE);
449 | enableAllButtons();
450 |
451 | }
452 |
453 | public void enableAllButtons() {
454 | createMultipleDurableSubsButton.setEnabled(true);
455 | createSingleSubsButton.setEnabled(true);
456 | eraseDurableSubsButton.setEnabled(true);
457 | }
458 | }
459 | }
460 |
--------------------------------------------------------------------------------
/src/main/java/com/mcafee/gui/JmsGuiCommon.java:
--------------------------------------------------------------------------------
1 | package com.mcafee.gui;
2 |
3 | import java.awt.EventQueue;
4 | import java.awt.GridBagConstraints;
5 |
6 | import javax.swing.JOptionPane;
7 |
8 | /**
9 | *
10 | * @author Gursev Singh Kalra @ McAfee, Inc.
11 | *
12 | */
13 | public class JmsGuiCommon {
14 | public static void resetGridBagConstraints(GridBagConstraints gbc) {
15 | // Defaults from http://docs.oracle.com/javase/tutorial/uiswing/layout/gridbag.html
16 | gbc.gridx = GridBagConstraints.RELATIVE;
17 | gbc.gridy = GridBagConstraints.RELATIVE;
18 | gbc.gridwidth = 1;
19 | gbc.gridheight = 1;
20 | gbc.fill = GridBagConstraints.NONE;
21 | gbc.ipadx = 0;
22 | gbc.ipady = 0;
23 | gbc.anchor = GridBagConstraints.CENTER;
24 | gbc.weightx = 0;
25 | gbc.weighty = 0;
26 | gbc.insets.left = 0;
27 | gbc.insets.right = 0;
28 | gbc.insets.bottom = 0;
29 | gbc.insets.top = 0;
30 | }
31 |
32 | public static void showErrorAndLogMessage() {
33 | EventQueue.invokeLater(new Runnable() {
34 | public void run() {
35 | JOptionPane.showMessageDialog(null, "An error has occured, please check logs for more details.", "Error", JOptionPane.ERROR_MESSAGE);
36 | }
37 | });
38 | }
39 |
40 | public static void showErrorAndLogMessage(final String str) {
41 | EventQueue.invokeLater(new Runnable() {
42 | public void run() {
43 | JOptionPane.showMessageDialog(null, str+"\nPlease see log files for more details", "Error", JOptionPane.ERROR_MESSAGE);
44 | }
45 | });
46 | }
47 |
48 | public static void showDoneMessage() {
49 | EventQueue.invokeLater(new Runnable() {
50 | public void run() {
51 | JOptionPane.showMessageDialog(null, "Done!", "", JOptionPane.INFORMATION_MESSAGE);
52 | }
53 | });
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/com/mcafee/gui/ProgressInfo.java:
--------------------------------------------------------------------------------
1 | package com.mcafee.gui;
2 |
3 | /**
4 | *
5 | * @author Gursev Singh Kalra @ McAfee, Inc.
6 | *
7 | */
8 | public class ProgressInfo {
9 | private String description;
10 | private boolean successful;
11 | private int percentage;
12 |
13 | public ProgressInfo() {
14 |
15 | }
16 |
17 | public ProgressInfo(String description, boolean successful, int percentage) {
18 | this.description = description;
19 | this.successful = successful;
20 | this.percentage = percentage ;
21 | }
22 |
23 | public void setDescription(String description) {
24 | this.description = description;
25 | }
26 |
27 | public void setSuccessful(boolean successful) {
28 | this.successful = successful;
29 | }
30 |
31 | public void setPercentage(int percentage) {
32 | this.percentage = percentage;
33 | }
34 |
35 | public String getDescription() {
36 | if(description == null)
37 | return "";
38 | return description;
39 | }
40 |
41 | public boolean isSuccessful() {
42 | return successful;
43 | }
44 |
45 | public int getPercentage() {
46 | return percentage;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/resources/fs_icon_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenSecurityResearch/jmsdigger/5e2793c2da728b00999662ae0ce6cf562ff5b436/src/main/resources/fs_icon_32.png
--------------------------------------------------------------------------------
/src/main/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | # Root logger option
2 | log4j.rootLogger=INFO, file, stdout
3 | #log4j.rootLogger=file, stdout
4 |
5 | # Direct log messages to a log file
6 | log4j.appender.file=org.apache.log4j.RollingFileAppender
7 | log4j.appender.file.File=${user.home}/jmsdigger/jmsdigger.log
8 | log4j.appender.file.MaxFileSize=1MB
9 | log4j.appender.file.MaxBackupIndex=10
10 | log4j.appender.file.layout=org.apache.log4j.PatternLayout
11 | log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
12 |
13 | # Direct log messages to stdout
14 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender
15 | log4j.appender.stdout.Target=System.err
16 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
17 | log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
--------------------------------------------------------------------------------
/src/test/java/com/mcafee/AMQOpsTest.java:
--------------------------------------------------------------------------------
1 | package com.mcafee;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.util.ArrayList;
6 |
7 | import javax.jms.JMSException;
8 | import javax.jms.MapMessage;
9 | import javax.jms.Queue;
10 | import javax.jms.Topic;
11 |
12 | import org.junit.After;
13 | import org.junit.Before;
14 | import org.junit.Test;
15 |
16 | /**
17 | *
18 | * @author Gursev Singh Kalra @ McAfee, Inc.
19 | *
20 | */
21 | public class AMQOpsTest {
22 |
23 | private AMQOps opsTest;
24 | @Before
25 | public void setUp() throws Exception {
26 | opsTest = new AMQOps(JmsHelper.getActiveMQInitialContext(), "ConnectionFactory");
27 | opsTest.init();
28 | }
29 |
30 | @After
31 | public void tearDown() throws Exception {
32 |
33 | }
34 |
35 | @Test
36 | public void brokerStatusAndSubscriptionStatusTest() throws JmsDiggerException {
37 | ArrayList status = null;
38 | int expected = 1;
39 | status = opsTest.getBrokerStats();
40 | System.out.println(JmsHelper.mapMessageToString(status.get(0), "================"));
41 |
42 | assertNotNull(status);
43 | assertEquals(expected, status.size());
44 |
45 | status = null;
46 | status = opsTest.getSubscriptionsStats();
47 | assertNotNull(status);
48 | assertEquals(expected, status.size());
49 |
50 | }
51 |
52 | @Test
53 | public void amqstatsAndamqstatstTest() throws JmsDiggerException {
54 | String dName = null;
55 | ArrayListstatus = null;
56 | int expected = 1;
57 |
58 | dName = "jms.amqQueueStats";
59 | status = opsTest.getQueueStats(dName, true);
60 | assertNotNull(status);
61 | assertEquals(expected, status.size());
62 |
63 | status = null;
64 |
65 | dName = "jms.amqTopicStats";
66 | status = opsTest.getTopicStats(dName, true);
67 |
68 | assertNotNull(status);
69 | assertEquals(expected, status.size());
70 |
71 | status = null;
72 | expected = 0 ;
73 |
74 | dName = "aa";
75 | status = opsTest.getTopicStats(dName, true);
76 | assertNotNull(status);
77 | assertEquals(0, status.size());
78 | }
79 |
80 | @Test
81 | public void amqWildCardStatsTest() throws JmsDiggerException {
82 | String dName = null;
83 | ArrayList status = null;
84 | dName = "jms.*";
85 | status = opsTest.getQueueStats(dName, true);
86 |
87 | assertNotNull(status);
88 | assertTrue(status.size() > 1);
89 |
90 | dName = "jms.*";
91 | status = opsTest.getTopicStats(dName, true);
92 | assertNotNull(status);
93 | assertTrue(status.size() > 1);
94 | }
95 |
96 | @Test
97 | public void createQueueAndDestinationTest() throws JmsDiggerException {
98 | ArrayList aList;
99 | String dstName = "lsadf2342";
100 |
101 | Queue q = opsTest.createQueue(dstName);
102 | int expected = 1;
103 |
104 | aList = opsTest.getQueueStats(dstName, true);
105 | assertNotNull(aList);
106 | assertEquals(expected, aList.size());
107 |
108 | Topic t = opsTest.createTopic(dstName);
109 | aList = opsTest.getTopicStats(dstName, true);
110 | assertNotNull(aList);
111 | assertEquals(expected, aList.size());
112 |
113 | }
114 |
115 | }
116 |
--------------------------------------------------------------------------------
/src/test/java/com/mcafee/FuzzAMQOps.java:
--------------------------------------------------------------------------------
1 | package com.mcafee;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import static org.junit.Assert.*;
6 |
7 | import java.util.ArrayList;
8 |
9 | import javax.jms.JMSException;
10 | import javax.jms.MapMessage;
11 | import javax.jms.Queue;
12 | import javax.jms.Topic;
13 | import javax.management.MalformedObjectNameException;
14 | import javax.management.ObjectName;
15 |
16 | import org.apache.activemq.broker.BrokerService;
17 | import org.junit.After;
18 | import org.junit.AfterClass;
19 | import org.junit.Before;
20 | import org.junit.BeforeClass;
21 | import org.junit.Test;
22 |
23 | /**
24 | *
25 | * @author Gursev Singh Kalra @ McAfee, Inc.
26 | *
27 | */
28 | public class FuzzAMQOps {
29 | private static Logger LOG = LoggerFactory.getLogger(FuzzAMQOps.class);
30 |
31 | private AMQOps opsTest;
32 | private static BrokerService broker;
33 |
34 | @BeforeClass
35 | public static void setUpBeforeClass() throws Exception {
36 | broker = new BrokerService();
37 | broker.setPersistent(false);
38 | broker.start();
39 | }
40 |
41 | @AfterClass
42 | public static void tearDownAfterClass() throws Exception {
43 | broker.stop();
44 | }
45 |
46 | @Before
47 | public void setUp() throws Exception {
48 | //opsTest = new AMQOps(JmsHelper.getActiveMQInitialContextForUnitTest(), "ConnectionFactory");
49 | opsTest = new AMQOps(JmsHelper.getActiveMQInitialContext(), "ConnectionFactory");
50 | opsTest.init();
51 | }
52 |
53 | @After
54 | public void tearDown() throws Exception {
55 |
56 | }
57 |
58 | // @Test
59 | // public void brokerStatusAndSubscriptionStatusTest() throws JmsDiggerException {
60 | // ArrayList status = null;
61 | // int expected = 1;
62 | // status = opsTest.getBrokerStats();
63 | // assertNotNull(status);
64 | // assertEquals(expected, status.size());
65 | //
66 | // status = null;
67 | // status = opsTest.getSubscriptionsStats();
68 | // assertNotNull(status);
69 | // assertEquals(expected, status.size());
70 | //
71 | // }
72 | //
73 | @Test
74 | public void amqstatsAndamqstatstTest() throws JmsDiggerException {
75 |
76 | JmsMessageContentGenerator gen = new JmsMessageContentGenerator();
77 | gen.setMaxValue((int)256);
78 | String dstName = null;
79 | ArrayListstatus;
80 | Topic q;
81 | char[] c;
82 |
83 | for(int i = 1 ; i < 10; i+=1) {
84 | try {
85 | System.out.println(i);
86 | dstName = gen.getString(100);
87 | LOG.info("Destination Name => " + dstName);
88 | LOG.info(JmsHelper.stringToCharArrayString(dstName));
89 | status = opsTest.getQueueStats(dstName, false);
90 | if(status != null && status.size() > 0)
91 | for(MapMessage m: status)
92 | System.out.println(JmsHelper.mapMessageToString(m));
93 | else
94 | System.out.println("Nothing returned for " + dstName);
95 | } catch (JmsDiggerException ex) {
96 | LOG.info("Error occured at i => " + i, ex);
97 | } catch (Throwable ex) {
98 | LOG.info("This caused error => " + dstName);
99 | LOG.info("Error occured at i => " + i, ex);
100 | }
101 |
102 | }
103 |
104 |
105 | // ArrayListstatus = null;
106 | // int expected = 1;
107 | //
108 | // dstName = "jms.amqQueueStats";
109 | // status = opsTest.getQueueStats(dstName, true);
110 | // assertNotNull(status);
111 | // assertEquals(expected, status.size());
112 | //
113 | // status = null;
114 | //
115 | // dstName = "jms.amqTopicStats";
116 | // status = opsTest.getTopicStats(dstName, true);
117 | //
118 | // assertNotNull(status);
119 | // assertEquals(expected, status.size());
120 | //
121 | // status = null;
122 | // expected = 0 ;
123 | //
124 | // dstName = "aa";
125 | // status = opsTest.getTopicStats(dstName, true);
126 | // assertNotNull(status);
127 | // assertEquals(0, status.size());
128 | }
129 | //
130 | // @Test
131 | // public void amqWildCardStatsTest() throws JmsDiggerException {
132 | // String dName = null;
133 | // ArrayList status = null;
134 | // dName = "jms.*";
135 | // status = opsTest.getQueueStats(dName, true);
136 | //
137 | // assertNotNull(status);
138 | // assertTrue(status.size() > 1);
139 | //
140 | // dName = "jms.*";
141 | // status = opsTest.getTopicStats(dName, true);
142 | // assertNotNull(status);
143 | // assertTrue(status.size() > 1);
144 | // }
145 |
146 | //@Test
147 | public void createLongQueueNames() throws JmsDiggerException, Exception {
148 |
149 | //tried all 65536 characters. None returned error
150 | JmsMessageContentGenerator gen = new JmsMessageContentGenerator();
151 | gen.setMaxValue((int)256);
152 | String dstName = "";
153 | Topic q;
154 | char[] c;
155 |
156 | for(int i = 1 ; i < 5000; i+=1) {
157 | try {
158 | System.out.println(i);
159 | dstName = gen.getString(5);
160 | dstName = "//*/" + dstName;
161 | LOG.info("Destination Name => " + dstName);
162 | LOG.info(JmsHelper.stringToCharArrayString(dstName));
163 | q = opsTest.createTopic(dstName);
164 | } catch (JmsDiggerException ex) {
165 | LOG.info("Error occured at i => " + i, ex);
166 | } catch (Throwable ex) {
167 | LOG.info("This caused error => " + dstName);
168 | LOG.info("Error occured at i => " + i, ex);
169 | }
170 |
171 | }
172 | }
173 |
174 | //@Test
175 | public void testObjectName() throws MalformedObjectNameException, NullPointerException {
176 | ObjectName onm = new ObjectName("aaaaaaaaaaaaa.ddddd");
177 | System.out.println(onm.toString());
178 | }
179 |
180 | //@Test
181 | public void createQueueAndDestinationTest() throws JmsDiggerException {
182 | //tried all 65536 characters. None returned error
183 | ArrayList aList;
184 | String dstName;
185 | Queue q;
186 |
187 | for(int i = 55000 ; i < 65536; i ++) {
188 | try {
189 | System.out.println(i);
190 | dstName = "" + (char)i;
191 | q = opsTest.createQueue(dstName);
192 | } catch (JmsDiggerException ex) {
193 | LOG.info("Error occured at i => " + i, ex);
194 | }
195 |
196 | }
197 | //
198 | // aList = opsTest.getQueueStats(dstName, true);
199 | // assertNotNull(aList);
200 | // assertEquals(expected, aList.size());
201 | //
202 | // Topic t = opsTest.createTopic(dstName);
203 | // aList = opsTest.getTopicStats(dstName, true);
204 | // assertNotNull(aList);
205 | // assertEquals(expected, aList.size());
206 |
207 | }
208 |
209 | }
210 |
--------------------------------------------------------------------------------
/src/test/java/com/mcafee/IdGeneratorTest.java:
--------------------------------------------------------------------------------
1 | package com.mcafee;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import org.apache.activemq.util.IdGenerator;
6 | import org.junit.After;
7 | import org.junit.Before;
8 | import org.junit.Test;
9 |
10 | /**
11 | *
12 | * @author Gursev Singh Kalra @ McAfee, Inc.
13 | *
14 | */
15 | public class IdGeneratorTest {
16 |
17 | @Before
18 | public void setUp() throws Exception {
19 | }
20 |
21 | @After
22 | public void tearDown() throws Exception {
23 | for(int i = 0; i < 100; i++)
24 | System.out.println(new IdGenerator().generateId());
25 | }
26 |
27 | @Test
28 | public void test() {
29 |
30 | fail("Not yet implemented");
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/test/java/com/mcafee/JmsAuthenticationTest.java:
--------------------------------------------------------------------------------
1 | package com.mcafee;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import javax.naming.InitialContext;
6 |
7 | import org.junit.After;
8 | import org.junit.Before;
9 | import org.junit.Test;
10 |
11 | /**
12 | *
13 | * @author Gursev Singh Kalra @ McAfee, Inc.
14 | *
15 | */
16 | public class JmsAuthenticationTest {
17 | private JmsAuthentication jmsAuthn;
18 | private JmsInitialContextFactory contextFactory;
19 | private InitialContext ctx;
20 | private String connFact = "ConnectionFactory";
21 | private JmsLoginInfo loginInfo;
22 | private boolean state;
23 | private boolean testingAnonymous;
24 |
25 |
26 | @Before
27 | public void setUp() throws JmsDiggerException {
28 | contextFactory = new JmsInitialContextFactory("org.apache.activemq.jndi.ActiveMQInitialContextFactory", "tcp://192.168.10.101:61626");
29 | contextFactory.addConnectionFactory(connFact);
30 | ctx = contextFactory.getInitialContext();
31 | jmsAuthn = new JmsAuthentication(ctx, connFact);
32 | // Make sure to change Messaging broker running configuration before changing this variable.
33 | testingAnonymous = true;
34 | }
35 |
36 | @After
37 | public void tearDown() throws Exception {
38 |
39 | }
40 |
41 | /**
42 | * only one of testIsLoginInfoValid
43 | * @throws JmsDiggerException
44 | */
45 | @Test
46 | public void testValidUsernameInvalidPassword() throws JmsDiggerException {
47 | loginInfo = new JmsLoginInfo("system", "iNvAlIdPassword!");
48 | state = jmsAuthn.isLoginInfoValid(loginInfo);
49 | if(testingAnonymous)
50 | assertEquals(true, state);
51 | else
52 | assertEquals(false, state);
53 | }
54 |
55 | /**
56 | * only one of testIsLoginInfoValid
57 | * @throws JmsDiggerException
58 | */
59 | @Test
60 | public void testInvalidUsernameValidPassword() throws JmsDiggerException {
61 | loginInfo = new JmsLoginInfo("iNvAlId", "manager");
62 | state = jmsAuthn.isLoginInfoValid(loginInfo);
63 | if(testingAnonymous)
64 | assertEquals(true, state);
65 | else
66 | assertEquals(false, state);
67 | }
68 |
69 | /**
70 | * only one of testIsLoginInfoValid
71 | * @throws JmsDiggerException
72 | */
73 | @Test
74 | public void testSystemUsernameManagerPassword() throws JmsDiggerException {
75 | loginInfo = new JmsLoginInfo("\"", "pas");
76 | state = jmsAuthn.isLoginInfoValid(loginInfo);
77 | if(!testingAnonymous)
78 | assertTrue(state);
79 | }
80 |
81 | @Test
82 | public void testIsAnonymousAuthAlowed() throws JmsDiggerException {
83 | state = jmsAuthn.isAnonymousAuthAlowed();
84 | if(testingAnonymous)
85 | assertEquals(true, state);
86 | else
87 | assertEquals(false, state);
88 | }
89 |
90 | @Test
91 | public void testNullUsernameTest() throws JmsDiggerException {
92 | loginInfo = new JmsLoginInfo(null, "manager");
93 | state = jmsAuthn.isLoginInfoValid(loginInfo);
94 | if(testingAnonymous)
95 | assertTrue(state);
96 | else
97 | assertFalse(state);
98 | }
99 |
100 | @Test
101 | public void testNullPasswordTest() throws JmsDiggerException {
102 | loginInfo = new JmsLoginInfo("system", null);
103 | state = jmsAuthn.isLoginInfoValid(loginInfo);
104 | if(testingAnonymous)
105 | assertTrue(state);
106 | else
107 | assertFalse(state);
108 |
109 | }
110 |
111 | @Test
112 | public void testNullUsernameAndNullPasswordTest() throws JmsDiggerException {
113 | loginInfo = new JmsLoginInfo(null, null);
114 | state = jmsAuthn.isLoginInfoValid(loginInfo);
115 | if(testingAnonymous)
116 | assertTrue(state);
117 | else
118 | assertFalse(state);
119 | }
120 |
121 | }
122 |
--------------------------------------------------------------------------------
/src/test/java/com/mcafee/JmsDumpDestinationTest.java:
--------------------------------------------------------------------------------
1 | package com.mcafee;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.io.IOException;
6 | import java.io.Serializable;
7 | import java.util.Random;
8 |
9 | import javax.jms.BytesMessage;
10 | import javax.jms.ConnectionFactory;
11 | import javax.jms.JMSException;
12 | import javax.jms.MapMessage;
13 | import javax.jms.Message;
14 | import javax.jms.Connection;
15 | import javax.jms.MessageProducer;
16 | import javax.jms.ObjectMessage;
17 | import javax.jms.Queue;
18 | import javax.jms.QueueConnection;
19 | import javax.jms.QueueConnectionFactory;
20 | import javax.jms.QueueSession;
21 | import javax.jms.Session;
22 | import javax.jms.StreamMessage;
23 | import javax.jms.TextMessage;
24 | import javax.jms.Topic;
25 | import javax.naming.InitialContext;
26 | import javax.naming.NamingException;
27 |
28 | import org.apache.activemq.ScheduledMessage;
29 | import org.apache.activemq.util.IdGenerator;
30 | import org.junit.After;
31 | import org.junit.Before;
32 | import org.junit.Test;
33 | import org.apache.commons.lang.RandomStringUtils;
34 |
35 | class RandomPerson implements Serializable {
36 | private static Random random = new Random();
37 | private String name;
38 | private int age;
39 | public RandomPerson() {
40 | name = RandomStringUtils.random(random.nextInt(15));
41 | age = random.nextInt(20);
42 | }
43 | }
44 |
45 | /**
46 | *
47 | * @author Gursev Singh Kalra @ McAfee, Inc.
48 | *
49 | */
50 | public class JmsDumpDestinationTest {
51 | private InitialContext ctx;
52 |
53 | private String dumpQueue11Msgs = "dumpQueue11Msgs";
54 | private String dumpQueue00Msgs = "dumpQueue00Msgs";
55 | private String dumpTopic00Msgs = "dumpTopic00Msgs";
56 | private String dumpTopic11Msgs = "dumpTopic11Msgs";
57 | private String topic4DurableSubscriber = "topic4DurableSubscriber";
58 | private String durableSubscriberName = "durableSubscriberName";
59 | private String connFactName = "ConnectionFactory";
60 |
61 | private ConnectionFactory connFact;
62 | private JmsDumpDestination destDumper;
63 | private JmsDurableSubscriberManipulator durableSubsManipulator;
64 | private String clientId = "gursev";
65 |
66 | //The "session" and "connection" are used to send messages to the test queues and topics.
67 | // They are never passed on to the JmsDumpDestination object
68 | private Session session;
69 | private Connection connection;
70 |
71 |
72 | private InitialContext getInitialContext() throws JmsDiggerException
73 | {
74 | JmsInitialContextFactory contextFactory = new JmsInitialContextFactory("org.apache.activemq.jndi.ActiveMQInitialContextFactory", "tcp://127.0.0.1:61616");
75 | contextFactory.addConnectionFactory(connFactName);
76 | contextFactory.addQueue(dumpQueue11Msgs, "jms."+dumpQueue11Msgs);
77 | contextFactory.addQueue(dumpQueue00Msgs, "jms."+dumpQueue00Msgs);
78 | contextFactory.addTopic(dumpTopic00Msgs, "jms."+dumpTopic00Msgs);
79 | contextFactory.addTopic(dumpTopic11Msgs, "jms."+dumpTopic11Msgs);
80 | contextFactory.addTopic(topic4DurableSubscriber, "jms."+topic4DurableSubscriber);
81 | InitialContext ctxx = contextFactory.getInitialContext();
82 | return ctxx;
83 | }
84 |
85 |
86 | @Before
87 | public void setUp() throws Exception {
88 | ctx = getInitialContext();
89 | connFact = (ConnectionFactory) ctx.lookup(connFactName);
90 | connection = (Connection) connFact.createConnection();
91 | }
92 |
93 | @After
94 | public void tearDown() throws Exception {
95 | if(destDumper != null)
96 | destDumper.close();
97 | }
98 |
99 | // @Test
100 | // public void testDumpQueue00MsgsForNoMessage() throws JMSException, IOException, Exception {
101 | // String qName = dumpQueue00Msgs;
102 | // destDumper = new JmsDumpDestination(ctx, qName, connFactName);
103 | // destDumper.setMsgCountToDump(0);
104 | // destDumper.init();
105 | // try {
106 | // destDumper.dump();
107 | // } catch(Exception ex) {
108 | // //gobble it up
109 | // }
110 | // destDumper.close();
111 | // assertEquals(0, destDumper.getMsgsWritten());
112 | // }
113 |
114 |
115 | private void sendMessages(Session session, MessageProducer mp) throws NamingException, JMSException {
116 | byte[] b = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47};
117 | Message msg = session.createMessage();
118 | mp.send(msg);
119 | msg = session.createMessage();
120 | mp.send(msg);
121 |
122 | TextMessage tmsg = (TextMessage) session.createTextMessage();
123 | tmsg.setText("text message by gursev");
124 | tmsg.setStringProperty(ScheduledMessage.AMQ_SCHEDULED_CRON, "* * * * *");
125 | String s = new IdGenerator().generateId();
126 | tmsg.setStringProperty(ScheduledMessage.AMQ_SCHEDULED_ID, s);
127 | System.out.println(s);
128 | mp.send(tmsg);
129 | tmsg = (TextMessage) session.createTextMessage();
130 | tmsg.setText("text message by gursev");
131 | mp.send(tmsg);
132 |
133 | ObjectMessage omsg = (ObjectMessage) session.createObjectMessage(true);
134 | omsg.setObject(new RandomPerson());
135 | mp.send(omsg);
136 |
137 |
138 | MapMessage mmsg = (MapMessage) session.createMapMessage();
139 | mmsg.setBoolean("boolean", false);
140 |
141 |
142 | mmsg.setByte("byte", (byte) 0x44);
143 | mmsg.setChar("char", 'c');
144 | mmsg.setFloat("float", (float) 4.444);
145 | mmsg.setInt("int", 33);
146 | mmsg.setBytes("bytes[]", b);
147 | mp.send(mmsg);
148 | mmsg = (MapMessage) session.createMapMessage();
149 | mmsg.setBoolean("boolean", false);
150 | mmsg.setByte("byte", (byte) 0x44);
151 | mmsg.setChar("char", 'c');
152 | mmsg.setFloat("float", (float) 4.444);
153 | mmsg.setInt("int", 33);
154 | mmsg.setBytes("bytes[]", b);
155 | mp.send(mmsg);
156 |
157 |
158 | BytesMessage bmsg = (BytesMessage) session.createBytesMessage();
159 | bmsg.writeBytes(b);
160 | mp.send(bmsg);
161 |
162 | bmsg = (BytesMessage) session.createBytesMessage();
163 | bmsg.writeBytes(b);
164 | mp.send(bmsg);
165 |
166 | StreamMessage smsg = (StreamMessage) session.createStreamMessage();
167 | smsg.writeBoolean(true);
168 | smsg.writeByte((byte) 0x44);
169 | smsg.writeChar('c');
170 | smsg.writeFloat((float) 4.444);
171 | smsg.writeInt(3333);
172 | smsg.writeBytes(b);
173 | mp.send(smsg);
174 |
175 | smsg = (StreamMessage) session.createStreamMessage();
176 | smsg.writeBoolean(true);
177 | smsg.writeByte((byte) 0x44);
178 | smsg.writeChar('c');
179 | smsg.writeFloat((float) 4.444);
180 | smsg.writeInt(3333);
181 | smsg.writeBytes(b);
182 | mp.send(smsg);
183 | }
184 |
185 |
186 | @Test
187 | public void testDumpTopic00MsgsForNoMessage() throws JMSException, IOException, Exception {
188 | String tName = dumpTopic00Msgs;
189 | destDumper = new JmsDumpDestination(ctx, tName, connFactName);
190 | destDumper.setTargetDirectory("/Users/Consultant/jmsdigger");
191 | destDumper.init();
192 |
193 | destDumper.dump();
194 |
195 | //Sleep to ensure that every message is read
196 | Thread.sleep(5000);
197 | destDumper.close();
198 | assertEquals(0, destDumper.getMsgsWritten());
199 | }
200 |
201 |
202 | @Test
203 | public void testDumpTopic11MsgsFor11Messages() throws JMSException, IOException, Exception {
204 | Topic topic = (Topic) ctx.lookup(dumpTopic11Msgs);
205 | session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
206 | MessageProducer mp = session.createProducer(topic);
207 |
208 | destDumper = new JmsDumpDestination(ctx, dumpTopic11Msgs, connFactName);
209 | destDumper.setTargetDirectory("/Users/Consultant/jmsdigger");
210 |
211 | destDumper.init();
212 |
213 | //Initiating dump before sending messages. This ensures that onMessage has started listening before messages are sent
214 | destDumper.dump();
215 |
216 | //Sending messages after initiating the dump process so messages are read
217 | sendMessages(session, mp);
218 |
219 | //Sleep to ensure that every message is read
220 | Thread.sleep(10000);
221 | destDumper.close();
222 | assertEquals(11, destDumper.getMsgsWritten());
223 | }
224 |
225 |
226 | @Test
227 | public void testDumpQueue11MsgsFor11Messages() throws JMSException, IOException, Exception {
228 | Queue queue = (Queue) ctx.lookup(dumpQueue11Msgs);
229 | session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
230 | MessageProducer mp = session.createProducer(queue);
231 | sendMessages(session, mp);
232 |
233 | destDumper = new JmsDumpDestination(ctx, dumpQueue11Msgs, connFactName);
234 | destDumper.setTargetDirectory("/Users/Consultant/jmsdigger");
235 | destDumper.setMsgCountToDump(11);
236 |
237 | destDumper.init();
238 | destDumper.dump();
239 | destDumper.close();
240 | assertEquals(11, destDumper.getMsgsWritten());
241 | }
242 |
243 | /**
244 | * This test works with two classes
245 | * 1. Durable subscriber manipulation class
246 | * 2. Dump destination.
247 | * @throws NamingException
248 | * @throws JMSException
249 | * @throws InterruptedException
250 | * @throws IOException
251 | * @throws IllegalAccessException
252 | */
253 | @Test
254 | public void testDurableSubscriberDump() throws NamingException, JMSException, InterruptedException, IOException, IllegalAccessException {
255 | Topic topic = (Topic) ctx.lookup(topic4DurableSubscriber);
256 |
257 | durableSubsManipulator = new JmsDurableSubscriberManipulator(ctx, topic4DurableSubscriber, connFactName);
258 | durableSubsManipulator.init(clientId);
259 | durableSubsManipulator.createDurableSubscriber(durableSubscriberName);
260 | durableSubsManipulator.close(); // Important to close as a only one connection can use a single client ID.
261 |
262 | session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
263 | MessageProducer mp = session.createProducer(topic);
264 | mp.setTimeToLive(0);
265 | sendMessages(session, mp);
266 |
267 | //Closing to ensure that dump method connectivity with same ID does not error out.
268 | session.close();
269 | connection.close();
270 |
271 | destDumper = new JmsDumpDestination(ctx, topic4DurableSubscriber, connFactName);
272 | destDumper.setTargetDirectory("/Users/Consultant/jmsdigger");
273 | destDumper.setClientId(clientId);
274 | destDumper.setDurableSubscriberName(durableSubscriberName);
275 | destDumper.init();
276 | destDumper.dump();
277 |
278 | Thread.sleep(10000);
279 | destDumper.close();
280 | assertEquals(11, destDumper.getMsgsWritten());
281 |
282 | }
283 |
284 | @Test
285 | public void zSendMessagesToDurableSubscriber() throws NamingException, JMSException {
286 | Topic topic = (Topic) ctx.lookup(topic4DurableSubscriber);
287 | session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
288 | MessageProducer mp = session.createProducer(topic);
289 | for(int i = 0; i < 10; i ++) {
290 | //mp.setTimeToLive(0);
291 | sendMessages(session, mp);
292 | }
293 | session.close();
294 | connection.close();
295 | destDumper = null;
296 | }
297 |
298 | @Test
299 | public void zSendMessagesToTopic11Msgs() throws NamingException, JMSException {
300 | Topic topic = (Topic) ctx.lookup(dumpTopic11Msgs);
301 | session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
302 | MessageProducer mp = session.createProducer(topic);
303 | sendMessages(session, mp);
304 | destDumper = null;
305 | }
306 |
307 | @Test
308 | public void zSendMessagesToQueue() throws NamingException, JMSException {
309 | Queue queue = (Queue) ctx.lookup(dumpQueue11Msgs);
310 | session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
311 | MessageProducer mp = session.createProducer(queue);
312 | sendMessages(session, mp);
313 | destDumper = null;
314 | }
315 |
316 |
317 | }
318 |
--------------------------------------------------------------------------------
/src/test/java/com/mcafee/JmsDurableSubscriberManipulatorTest.java:
--------------------------------------------------------------------------------
1 | package com.mcafee;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.util.ArrayList;
6 |
7 | import javax.jms.JMSException;
8 | import javax.jms.TopicSubscriber;
9 | import javax.naming.InitialContext;
10 |
11 | import org.junit.After;
12 | import org.junit.Before;
13 | import org.junit.Test;
14 |
15 | /**
16 | *
17 | * @author Gursev Singh Kalra @ McAfee, Inc.
18 | *
19 | */
20 | public class JmsDurableSubscriberManipulatorTest {
21 | private InitialContext ctx;
22 | private String durableSubscriberTopic = "durableSubscriberTopic";
23 | private JmsDurableSubscriberManipulator manipulator = null;
24 | private String connFactName = "ConnectionFactory";
25 | TopicSubscriber tsub;
26 | private String durableSubscriberName = "durableSubscriberName";
27 | private String clientId = "gursev";
28 | ArrayList tsAlist;
29 |
30 |
31 | @Before
32 | public void setUp() throws Exception {
33 | JmsInitialContextFactory contextFactory = new JmsInitialContextFactory("org.apache.activemq.jndi.ActiveMQInitialContextFactory", "tcp://localhost:61616");
34 | contextFactory.addConnectionFactory(connFactName);
35 | contextFactory.addTopic(durableSubscriberTopic, "jms." + durableSubscriberTopic);
36 | ctx = contextFactory.getInitialContext();
37 | manipulator = new JmsDurableSubscriberManipulator(ctx, durableSubscriberTopic, connFactName);
38 | manipulator.init(clientId);
39 | }
40 |
41 | @After
42 | public void tearDown() throws Exception {
43 | manipulator.close();
44 | }
45 |
46 | @Test
47 | public void testCreateDurableSubscribers() throws JmsDiggerException {
48 | int count = 1;
49 | tsAlist = new ArrayList();
50 | tsAlist = manipulator.createDurableSubscribers(count);
51 | assertEquals(count, tsAlist.size());
52 | }
53 |
54 | @Test
55 | public void testCreateRandDurableSubscriber() throws JmsDiggerException, JMSException {
56 | tsub = null;
57 | tsub = manipulator.createRandDurableSubscriber();
58 | assertNotNull(tsub);
59 | }
60 |
61 | @Test
62 | public void testCreateDurableSubscriberWithName() throws JmsDiggerException {
63 | tsub = null;
64 | tsub = manipulator.createDurableSubscriber(durableSubscriberName);
65 | assertNotNull(tsub);
66 | }
67 |
68 | @Test
69 | public void testCreateDurableSubscriberWithNameMessageSelectorAndNoLocal() throws JmsDiggerException {
70 | tsub = null;
71 | tsub = manipulator.createDurableSubscriber(durableSubscriberName, "test", true);
72 | assertNotNull(tsub);
73 | }
74 |
75 | @Test
76 | public void testEraseDurableSubscriber() throws JmsDiggerException {
77 | manipulator.createDurableSubscriber(durableSubscriberName+"Eraseme", "test", true);
78 | manipulator.close();
79 | manipulator.init(clientId);
80 | manipulator.eraseDurableSubscriber(durableSubscriberName+"Eraseme");
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/src/test/java/com/mcafee/JmsHelperTest.java:
--------------------------------------------------------------------------------
1 | package com.mcafee;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import javax.jms.ConnectionFactory;
6 | import javax.jms.Destination;
7 | import javax.jms.JMSException;
8 | import javax.jms.Message;
9 | import javax.jms.Queue;
10 | import javax.jms.QueueConnectionFactory;
11 | import javax.jms.TextMessage;
12 | import javax.jms.Topic;
13 | import javax.naming.InitialContext;
14 | import javax.naming.NamingException;
15 |
16 | import org.junit.After;
17 | import org.junit.Before;
18 | import org.junit.Test;
19 |
20 | /**
21 | *
22 | * @author Gursev Singh Kalra @ McAfee, Inc.
23 | *
24 | */
25 | public class JmsHelperTest {
26 |
27 | private JmsInitialContextFactory contextFactory;
28 | private InitialContext ctx;
29 |
30 | @Before
31 | public void setUp() throws Exception {
32 | contextFactory = new JmsInitialContextFactory("org.apache.activemq.jndi.ActiveMQInitialContextFactory", "tcp://localhost:61616");
33 | contextFactory.addTopic("exploits", "jms.exploits");
34 | contextFactory.addQueue("notInJndi", "jms.notInJndi");
35 | ctx = contextFactory.getInitialContext();
36 | }
37 |
38 | @After
39 | public void tearDown() throws Exception {
40 | }
41 |
42 | @Test
43 | public void testGetDestinationTrueInitCtxAndTrueJNDI() throws JmsDiggerException {
44 | Destination dest = JmsHelper.getDestination(ctx, "exploits");
45 | assertNotNull(dest);
46 | }
47 |
48 | // @Test
49 | // public void randomTest() throws NamingException
50 | // {
51 | // InitialContext ctx = new InitialContext();
52 | // //QueueConnectionFactory queueConnectionFactory = (QueueConnectionFactory)ctx.lookup("ConnectionFactory");
53 | // Queue queue = (Queue)ctx.lookup("submissions");
54 | // assertNull(queue);
55 | //
56 | // }
57 |
58 |
59 | /**
60 | * ActiveMQ auto creates new destinations during context looks up for a destination that is not present on the Broker
61 | */
62 | @Test
63 | public void testGetDestinationTrueInitCtxAndFalseJNDI() throws JMSException{
64 | Destination dest = JmsHelper.getDestination(ctx, "notInJndi");
65 | if(dest instanceof Queue)
66 | {
67 | System.out.println(((Queue) dest).getQueueName());
68 | }
69 | if(dest instanceof Topic)
70 | {
71 | System.out.println(((Topic) dest).getTopicName());
72 | }
73 |
74 | assertNotNull(dest);
75 | }
76 |
77 |
78 | @Test (expected=JmsDiggerException.class)
79 | public void testGetDestinationFalseInitCtxAndTrueJNDI() throws JmsDiggerException {
80 | JmsHelper.getDestination(ctx, "results");
81 | }
82 |
83 |
84 | @Test (expected=JmsDiggerException.class)
85 | public void testGetDestinationFalseInitCtxAndFalseJNDI() throws JmsDiggerException {
86 | JmsHelper.getDestination(ctx, "nowhere");
87 | }
88 |
89 |
90 | @Test
91 | public void testGetConnectionFactory() {
92 |
93 | }
94 |
95 | @Test
96 | public void testGetDestinationIntrusive()
97 | {
98 | String cfName = "ConnectionFactory";
99 | String destName = "exploits";
100 | //Destination dest = JmsHelper.getDestinationIntrusiveConsumer(ctx, cfName, null, destName, result);//(ctx, cfName, destName, result);
101 | //Destination dest = JmsHelper.getDestinationIntrusiveCreateDestination(ctx, cfName, null, destName, result);//(ctx, cfName, destName, result);
102 | //assertNotNull(dest);
103 | //loginInfo = new JmsLoginInfo("gursev", "kalra");
104 | }
105 |
106 | }
107 |
--------------------------------------------------------------------------------
/src/test/java/com/mcafee/JmsInitialContextFactoryTest.java:
--------------------------------------------------------------------------------
1 | package com.mcafee;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import javax.naming.InitialContext;
6 | import javax.naming.NamingException;
7 |
8 | import org.junit.After;
9 | import org.junit.Before;
10 | import org.junit.Test;
11 |
12 | /**
13 | *
14 | * @author Gursev Singh Kalra @ McAfee, Inc.
15 | *
16 | */
17 | public class JmsInitialContextFactoryTest {
18 | private JmsInitialContextFactory contextFactory;
19 |
20 | @Before
21 | public void setUp() throws Exception {
22 | //TODO: right now this is hard tied to ActiveMQ. But will be modified to
23 | //run generic tests when the tool adds support for multiple providers
24 | contextFactory = new JmsInitialContextFactory("org.apache.activemq.jndi.ActiveMQInitialContextFactory", "tcp://localhost:61616");
25 | }
26 |
27 | @After
28 | public void tearDown() throws Exception {
29 | }
30 |
31 | @Test
32 | public void testJmsInitialContextFactoryExists() throws JmsDiggerException {
33 | // make sure that ActiveMQ instance is running
34 | InitialContext ctx = contextFactory.getInitialContext();
35 | assertNotNull(ctx);
36 | }
37 |
38 | @Test (expected=JmsDiggerException.class)
39 | public void testJmsInitialContextFactoryDoesNotExist() throws JmsDiggerException {
40 | contextFactory = new JmsInitialContextFactory("org.apache.activemq.jndi.ActiveMQInitialContextFactoryyyyy", "tcp://localhost:61616");
41 | contextFactory.getInitialContext();
42 | }
43 |
44 | @Test
45 | public void testAddQueueWhenEditableIsFalse() throws JmsDiggerException {
46 | InitialContext ctx = contextFactory.getInitialContext();
47 | contextFactory.addQueue("bangbang", "bang");
48 | try {
49 | assertFalse(ctx.getEnvironment().containsKey("bangbang"));
50 | } catch (NamingException e) {
51 | e.printStackTrace();
52 | }
53 | }
54 |
55 | @Test
56 | public void testAddRawPropertyToEnv() throws JmsDiggerException {
57 | contextFactory.addRawPropertyToEnv("bangbang", "bang");
58 | InitialContext ctx = contextFactory.getInitialContext();
59 | try {
60 | assertNotNull(ctx.getEnvironment().containsKey("bangbang"));
61 | } catch (NamingException e) {
62 | e.printStackTrace();
63 | }
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/src/test/java/com/mcafee/JmsLoginInfoTest.java:
--------------------------------------------------------------------------------
1 | package com.mcafee;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import org.junit.After;
6 | import org.junit.Before;
7 | import org.junit.Test;
8 |
9 |
10 | /**
11 | *
12 | * @author Gursev Singh Kalra @ McAfee, Inc.
13 | *
14 | */
15 | public class JmsLoginInfoTest {
16 |
17 | private JmsLoginInfo loginInfo = null;
18 | @Before
19 | public void setUp() throws Exception {
20 | loginInfo = new JmsLoginInfo("gursev", "kalra");
21 | }
22 |
23 | @After
24 | public void tearDown() throws Exception {
25 | }
26 |
27 | @Test
28 | public void testGetUsername() {
29 | assertEquals("gursev", loginInfo.getUsername());
30 | }
31 |
32 | @Test
33 | public void testGetUsernameWrong() {
34 | assertNotEquals("_gursev", loginInfo.getUsername());
35 | }
36 |
37 | @Test
38 | public void testGetPassword() {
39 | assertEquals("kalra", loginInfo.getPassword());
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/test/java/com/mcafee/JmsPasswordOpsTest.java:
--------------------------------------------------------------------------------
1 | package com.mcafee;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import org.junit.After;
6 | import org.junit.Before;
7 | import org.junit.Test;
8 |
9 | /**
10 | *
11 | * @author Gursev Singh Kalra @ McAfee, Inc.
12 | *
13 | */
14 | public class JmsPasswordOpsTest {
15 | private JmsPasswordOps passwdOps = new JmsPasswordOps();
16 |
17 | @Before
18 | public void setUp() throws Exception {
19 |
20 |
21 | passwdOps.addPassword("new");
22 | passwdOps.addPassword("new1");
23 | passwdOps.addPassword("new2");
24 | passwdOps.addPassword("new3");
25 | passwdOps.addPassword("new4");
26 | passwdOps.addPassword("new5");
27 | passwdOps.addPassword("new6");
28 | passwdOps.addPassword("new7");
29 | passwdOps.addPassword("activemq");
30 | passwdOps.addPassword("new8");
31 | passwdOps.addPassword("new9");
32 | passwdOps.addPassword(" ");
33 | }
34 |
35 | @After
36 | public void tearDown() throws Exception {
37 |
38 | }
39 |
40 | @Test
41 | public void testDecrypt() {
42 | String pass;
43 | pass = passwdOps.decrypt("Cf3Jf3tM+UrSOoaKU50od5CuBa8rxjoL");
44 | assertEquals("password", pass);
45 | pass = passwdOps.decrypt("mYRkg+4Q4hua1kvpCCI2hg==");
46 | assertEquals("manager", pass);
47 |
48 | }
49 |
50 | @Test
51 | public void testDecryptInvalidInput() {
52 | assertNull(passwdOps.decrypt("mYRkg+4Q4hua1kvpCCI2hg="));
53 |
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------