1 /***
2 * Redistribution and use of this software and associated documentation
3 * ("Software"), with or without modification, are permitted provided
4 * that the following conditions are met:
5 *
6 * 1. Redistributions of source code must retain copyright
7 * statements and notices. Redistributions must also contain a
8 * copy of this document.
9 *
10 * 2. Redistributions in binary form must reproduce the
11 * above copyright notice, this list of conditions and the
12 * following disclaimer in the documentation and/or other
13 * materials provided with the distribution.
14 *
15 * 3. The name "Exolab" must not be used to endorse or promote
16 * products derived from this Software without prior written
17 * permission of Exoffice Technologies. For written permission,
18 * please contact info@exolab.org.
19 *
20 * 4. Products derived from this Software may not be called "Exolab"
21 * nor may "Exolab" appear in their names without prior written
22 * permission of Exoffice Technologies. Exolab is a registered
23 * trademark of Exoffice Technologies.
24 *
25 * 5. Due credit should be given to the Exolab Project
26 * (http://www.exolab.org/).
27 *
28 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32 * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 * OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Copyright 2005 (C) Exoffice Technologies Inc. All Rights Reserved.
42 *
43 * $Id: Exporter.java,v 1.3 2005/11/12 12:47:37 tanderson Exp $
44 */
45 package org.exolab.jms.tools.migration;
46
47 import java.sql.Connection;
48 import java.sql.SQLException;
49 import javax.jms.JMSException;
50
51 import org.apache.commons.logging.Log;
52 import org.apache.commons.logging.LogFactory;
53 import org.apache.derby.jdbc.EmbeddedDataSource;
54
55 import org.exolab.jms.config.Configuration;
56 import org.exolab.jms.config.ConfigurationReader;
57 import org.exolab.jms.persistence.DatabaseService;
58 import org.exolab.jms.persistence.PersistenceException;
59 import org.exolab.jms.service.ServiceException;
60 import org.exolab.jms.tools.db.Database;
61 import org.exolab.jms.tools.db.RDBMSTool;
62 import org.exolab.jms.tools.migration.master.MasterConsumerStore;
63 import org.exolab.jms.tools.migration.master.MasterDestinationStore;
64 import org.exolab.jms.tools.migration.master.MasterMessageStore;
65 import org.exolab.jms.tools.migration.master.MasterUserStore;
66 import org.exolab.jms.tools.migration.proxy.ConsumerStore;
67 import org.exolab.jms.tools.migration.proxy.DestinationStore;
68 import org.exolab.jms.tools.migration.proxy.MessageStore;
69 import org.exolab.jms.tools.migration.proxy.PropertyStore;
70 import org.exolab.jms.tools.migration.proxy.UserStore;
71 import org.exolab.jms.tools.migration.proxy.VersionInfo;
72 import org.exolab.jms.util.CommandLine;
73 import org.exolab.jms.util.Version;
74
75
76 /***
77 * Exports data from a master database into a proxy.
78 *
79 * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a>
80 * @version $Revision: 1.3 $ $Date: 2005/11/12 12:47:37 $
81 * @see Importer
82 */
83 public class Exporter {
84
85 /***
86 * The database service.
87 */
88 private final DatabaseService _database;
89
90 /***
91 * The connection factory for the target database.
92 */
93 private final EmbeddedDataSource _dataSource;
94
95 /***
96 * The logger.
97 */
98 private final Log _log = LogFactory.getLog(Exporter.class);
99
100
101 /***
102 * Construct a new <code>Exporter</code>.
103 *
104 * @param config the configuration to use
105 * @param database the database name
106 * @param delete if <code>true</code>, indicates to delete data in the
107 * migration database, if it exists
108 */
109 public Exporter(Configuration config, String database, boolean delete)
110 throws PersistenceException {
111 if (config == null) {
112 throw new IllegalArgumentException("Argument 'config' is null");
113 }
114 if (database == null) {
115 throw new IllegalArgumentException("Argument 'database' is null");
116 }
117 _database = new DatabaseService(config);
118 _dataSource = MigrationHelper.getDataSource(database);
119
120 init(delete);
121 }
122
123 /***
124 * Export the data from the master database to the migration database.
125 *
126 * @throws JMSException
127 * @throws PersistenceException for any persistence error
128 * @throws ServiceException for any service error
129 */
130 public void apply() throws JMSException, PersistenceException,
131 ServiceException {
132
133 Connection connection;
134 try {
135 connection = _dataSource.getConnection();
136 } catch (SQLException exception) {
137 throw new PersistenceException(
138 "Failed to get connection to target database",
139 exception);
140 }
141
142 PropertyStore properties = new PropertyStore(connection);
143 VersionInfo info = new VersionInfo(properties);
144 info.setProxySchemaVersion("1.0");
145 info.setOpenJMSVersion(Version.VERSION);
146 info.setCreationTimestamp(System.currentTimeMillis());
147
148 DestinationStore destinations = new DestinationStore(connection);
149 ConsumerStore consumers = new ConsumerStore(destinations, connection);
150 MessageStore messages = new MessageStore(destinations, connection);
151 UserStore users = new UserStore(connection);
152
153
154 _database.start();
155
156 _log.info("Exporting destinations...");
157 apply(new MasterDestinationStore(_database), destinations);
158 _log.info("Exported " + destinations.size() + " destinations");
159
160 _log.info("Exporting messages...");
161 apply(new MasterMessageStore(_database), messages);
162 _log.info("Exported " + messages.size() + " messages");
163
164 _log.info("Exporting consumers...");
165 apply(new MasterConsumerStore(_database), consumers);
166 _log.info("Exported " + consumers.size() + " consumers");
167
168 _log.info("Exporting users...");
169 apply(new MasterUserStore(_database), users);
170 _log.info("Exported " + users.size() + " users");
171
172 try {
173 connection.close();
174 } catch (SQLException exception) {
175 throw new PersistenceException("Failed to close target",
176 exception);
177 }
178
179 _database.stop();
180 _dataSource.setShutdownDatabase("shutdown");
181
182 _log.info("Export complete");
183 }
184
185 /***
186 * Main line.
187 *
188 * @param args command line arguments
189 */
190 public static void main(String[] args) {
191 CommandLine commands = new CommandLine(args);
192
193 String path = commands.value("config");
194 if (path == null) {
195 usage();
196 System.exit(1);
197 } else {
198 try {
199 Configuration config = ConfigurationReader.read(path);
200
201 String database = commands.value("db");
202 if (database == null) {
203 database = "openjms_migdb";
204 }
205 boolean delete = commands.exists("delete");
206
207 Exporter exporter = new Exporter(config, database, delete);
208 exporter.apply();
209
210 System.exit(0);
211 } catch (Exception exception) {
212 exception.printStackTrace();
213 System.exit(1);
214 }
215 }
216 }
217
218 /***
219 * Initialise the target database.
220 *
221 * @param delete if <code>true</code>, indicates to delete data in the
222 * proxy database, if it exists
223 * @throws PersistenceException for any persistence error
224 */
225 private void init(boolean delete) throws PersistenceException {
226 RDBMSTool tool;
227 try {
228 tool = new RDBMSTool(_dataSource.getConnection());
229 } catch (SQLException exception) {
230 throw new PersistenceException(exception);
231 }
232
233 try {
234 Database schema = MigrationHelper.getSchema();
235 if (tool.hasTables(schema.getTable())) {
236 if (delete) {
237 tool.delete(schema);
238 } else {
239 throw new PersistenceException(
240 "Cannot export data: migration database already "
241 + "exists but delete not specified");
242 }
243 } else {
244 tool.create(schema);
245 }
246 } finally {
247 tool.close();
248 }
249 }
250
251 /***
252 * Export data from a source store, and import it to a target store.
253 *
254 * @param source the source store
255 * @param target the target store
256 * @throws JMSException for any JMS error
257 * @throws PersistenceException for any persistence error
258 */
259 private void apply(Store source, Store target)
260 throws JMSException, PersistenceException {
261
262 StoreIterator iterator = source.exportCollection();
263 target.importCollection(iterator);
264 }
265
266 /***
267 * Displays usage information for this tool when invoked from the command
268 * line
269 */
270 private static void usage() {
271 System.err.println(
272 "usage: " + Exporter.class.getName()
273 + " <arguments> [options]\n"
274 + "arguments:\n"
275 + " -config <path> specifies the path to an OpenJMS "
276 + "configuration file\n"
277 + " -db <name> specifies the path to export data to\n");
278 }
279
280 }