1
2 package net.sourceforge.jdbdump.dump;
3
4 import java.io.IOException;
5 import java.io.ObjectInputStream;
6 import java.io.Serializable;
7 import java.util.Vector;
8
9 import net.sourceforge.jdbdump.connect.DatabaseConnector;
10
11 import org.apache.log4j.Logger;
12
13 /***
14 * Represents the entire database structure downloaded into memory.
15 * <br /><br />
16 * A typical process of dumping a database looks like the following:
17 * <ol>
18 * <li>gui class creates a DatabaseConnector and connects it using connect()</li>
19 * <li>gui calls DatabaseConnector.dump(), which creates a Dump</li>
20 * <li>then it calls DumpFileManager.exportDump(dump), which saves it and its data to a file</li>
21 * <li>finally, it disconnects DatabaseConnector using disconnect()</li>
22 * </ol>
23 * And a process of restoring a database looks like the following:
24 * <ol>
25 * <li>gui class creates a DatabaseConnector and connects it using connect()</li>
26 * <li>then it calls DumpFileManager.importDump() which reads the dump back from a file</li>
27 * <li>then it calls DatabaseConnector.restore(dump), which uploads the dump and its data
28 * into a database</li>
29 * <li>finally, it disconnects DatabaseConnector using disconnect(), and closes the input
30 * file using Dump.closeFileReader()</li>
31 * </ol>
32 * <br />
33 * It is important to know that when the dump object is constructed, either by dump() or importDump(),
34 * it doesn't mean that it already contains all the data it needs. To minimize memory usage, Dump
35 * stores only database structure, but not its data. The data is read from a file or database later,
36 * in exportDump() or restore(), and copied on the fly to the destination place. So, when a Dump is
37 * created by dump(), the Connection object which was used to create is must be available until all
38 * the data is downloaded in exportDump(); and when a Dump is created by importDump(), the
39 * file input stream used to load it must not be closed until the data is downloaded in
40 * restore().
41 * <br /><br />
42 * In both cases, the data is read by the same methods initializeData() and getDataLine() (see Table
43 * class). A Table knows where to get the data from by checking the "mode" in which its parent Dump
44 * is, which can be either "database read mode" or "file read mode". It can be set by calling
45 * setDatabaseReader(Connection c) or setFileReader(ObjectInputStream s) respectively, and can be checked
46 * by isReadingFromDatabase() method.
47 *
48 * @see Table
49 * @see DatabaseConnector
50 * @see DumpFileManager
51 * @author jsuder
52 */
53
54 public class Dump implements Serializable {
55
56 /*** ID used in serialization process. */
57 private static final long serialVersionUID = 8861226762920104092L;
58
59 /*** A list of all tables in the database. */
60 private Vector<Table> tables;
61
62 /*** A reference to a DatabaseConnector which created this dump, needed to download data later. */
63 private transient DatabaseConnector databaseReader;
64
65 /*** A reference to an open file input stream, from which the data will be read later. */
66 private transient ObjectInputStream fileReader;
67
68 /*** True if data should be read from the database and written into a file, false if it's
69 * the opposite. */
70 private transient boolean readFromDatabase = false;
71
72 /*** A log4j logger for this class. */
73 private static Logger logger = Logger.getLogger(Dump.class);
74
75 /***
76 * Creates a new empty dump, which will be later filled with tables, views and other stuff...
77 */
78
79 public Dump() {
80 tables = new Vector<Table>();
81 this.databaseReader = null;
82 this.fileReader = null;
83 }
84
85 /***
86 * Returns a list of all tables stored in the dump object.
87 * @return a list of tables
88 */
89
90 public Vector<Table> getTables() {
91 return tables;
92 }
93
94 /***
95 * Returns a DatabaseConnector used to download table data after the dump is
96 * created, if the dump is set in "read from database" mode (by calling
97 * setDatabaseReader()). Otherwise, returns null.
98 * @return a DatabaseConnector which created this dump
99 */
100
101 public DatabaseConnector getDatabaseReader() {
102 if (!readFromDatabase) {
103 databaseReader = null;
104 }
105 return databaseReader;
106 }
107
108 /***
109 * Returns a stream which can be used to read records of table data from a backup
110 * file, if the dump is set in "read from file" mode (by calling setFileReader()).
111 * Otherwise, returns null.
112 * @return an input stream reading records from a backup file
113 */
114
115 public ObjectInputStream getFileReader() {
116 if (readFromDatabase) {
117 fileReader = null;
118 }
119 return fileReader;
120 }
121
122 /***
123 * Sets the dump in "database read mode", and sets the used DatabaseConnector to
124 * the one given in argument.
125 * @param connection a DatabaseConnector which should be used to read data later
126 */
127
128 public void setDatabaseReader(DatabaseConnector connection) {
129 this.databaseReader = connection;
130 readFromDatabase = true;
131 }
132
133 /***
134 * Sets the dump in "file read mode", and sets the used file input stream
135 * the one given in argument.
136 * @param stream an open file input stream which should be used to read data later
137 */
138
139 public void setFileReader(ObjectInputStream stream) {
140 this.fileReader = stream;
141 readFromDatabase = false;
142 }
143
144 /***
145 * Closes the file from which dump data has been read. Should be done after all the
146 * data is read in DatabaseConnector.restore(), but not earlier.
147 */
148
149 public void closeFileReader() {
150 try {
151 fileReader.close();
152 } catch (IOException e) {
153 logger.warn("Couldn't close fileReader: " + e);
154 }
155 fileReader = null;
156 }
157
158 /***
159 * Tells if the dump is currently in "database read mode" or "file read mode".
160 * @return true if it is in "database read mode"
161 */
162
163 public boolean isReadingFromDatabase() {
164 return readFromDatabase;
165 }
166
167 /***
168 * Reads a dump from a file using serialization and initializes it and its tables.
169 * @param in an input stream from which the dump will be read
170 * @throws IOException if the object can't be read from the file
171 * @throws ClassNotFoundException if the saved object format doesn't match this class
172 */
173
174 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
175 in.defaultReadObject();
176 this.databaseReader = null;
177 this.fileReader = null;
178 this.readFromDatabase = false;
179 for (Table t : tables) {
180 t.setDump(this);
181 }
182 }
183 }