View Javadoc

1   /* $Id: BinaryFileManager.java,v 1.9 2006/01/12 15:13:08 psionides Exp $ */
2   package net.sourceforge.jdbdump.dump;
3   
4   import java.io.File;
5   import java.io.FileInputStream;
6   import java.io.FileOutputStream;
7   import java.io.IOException;
8   import java.io.InputStream;
9   import java.io.ObjectInputStream;
10  import java.io.ObjectOutputStream;
11  import java.util.zip.GZIPInputStream;
12  import java.util.zip.GZIPOutputStream;
13  import java.util.zip.ZipEntry;
14  import java.util.zip.ZipFile;
15  import java.util.zip.ZipOutputStream;
16  
17  import org.apache.log4j.Logger;
18  
19  /***
20   * An implementation of DumpFileManager which saves dump objects in binary (serialized) form.
21   * 
22   * @see DumpFileManager
23   * @author jsuder
24   */
25  
26  public class BinaryFileManager implements DumpFileManager {
27  
28  	/*** A log4j logger for this class. */
29  	private static Logger logger = Logger.getLogger(BinaryFileManager.class);
30  
31  	/***
32  	 * Saves a backup of the database represented in the dump object into the specified file.
33  	 * First it saves the database structure which is already contained in the Dump, then
34  	 * uses the Dump to download all the data, table by table, record by record, and saves it
35  	 * into the file as soon as it's downloaded.
36  	 * 
37  	 * @param dump a database dump created using DatabaseConnector.dump() method
38  	 * @param file a file in which the backup will be stored
39  	 * @param compress compression method used to compress the file (zip, gzip or none)
40  	 */
41  
42  	public void exportDump(Dump dump, File file, CompressionMethod compress) {
43  		ObjectOutputStream output;
44  
45  		try {
46  			if (compress == CompressionMethod.ZIP) {
47  				// create a zip file with one *.bin file inside
48  				ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(file));
49  				String zippedName = file.getName().substring(0, file.getName().lastIndexOf('.')) + ".bin";
50  				zip.putNextEntry(new ZipEntry(zippedName));
51  				output = new ObjectOutputStream(zip);
52  			} else if (compress == CompressionMethod.GZIP) {
53  				// create a gzip file
54  				GZIPOutputStream gzip = new GZIPOutputStream(new FileOutputStream(file));
55  				output = new ObjectOutputStream(gzip);
56  			} else {
57  				// use no compression, just save the file as it is
58  				output = new ObjectOutputStream(new FileOutputStream(file));
59  			}
60  		} catch (Exception e) {
61  			logger.error("Error while creating an ouput stream to the backup file: " + e);
62  			e.printStackTrace();
63  			return;
64  		}
65  
66  		try {
67  			// save the table structure into the file
68  			output.writeObject(dump);
69  		} catch (IOException e) {
70  			logger.error("Error while saving the dump structure into the backup file: " + e);
71  			e.printStackTrace();
72  			return;
73  		}
74  		
75  		// then save data for all the tables
76  		for (Table table : dump.getTables()) {
77  			logger.info("Downloading data from table " + table.getName());
78  			try {
79  				table.initializeData();
80  				int count = 0;
81  				while (true) {
82  					String[] line = table.getDataLine();
83  					output.writeObject(line);
84  					if (count == 100) {
85  						// reset the stream from time to time
86  						// that releases the previously written lines from memory
87  						output.reset();
88  						count = 0;
89  					}
90  					count++;
91  					if (line == null) {
92  						// null line marks the end of that table's data
93  						break;
94  					}
95  				}
96  			} catch (Exception e) {
97  				logger.error("Error while saving data from table " + table.getName() + ": " + e);
98  				e.printStackTrace();
99  				return;
100 			}
101 		}
102 		
103 		try {
104 			output.close();
105 		} catch (IOException e) {
106 			logger.warn("Couldn't close output file.");
107 		}
108 	}
109 
110 	/***
111 	 * Loads the database structure as a Dump object from the specified file.
112 	 * <br />
113 	 * This method doesn't load any data (i.e. table records) from the file yet. Data should be
114 	 * loaded by DatabaseConnector.restore() when the dump returned by this function is passed to
115 	 * it. The dump stores a reference to the input stream from this file to be able to read the data
116 	 * later; when it is no longer needed, it should be closed by calling closeFileReader() on the
117 	 * Dump (but that shouldn't be called until all data is read in DatabaseConnector.restore()).
118 	 * 
119 	 * @param file a file from which the backup should be read
120 	 * @param compress compression method used to decompress the file (zip, gzip or none)
121 	 * @return a database dump that can be uploaded using DatabaseConnector.restore() method
122 	 */
123 
124 	public Dump importDump(File file, CompressionMethod compress) { 
125 		ObjectInputStream input;
126 		
127 		try {
128 			if (compress == CompressionMethod.ZIP) {
129 				ZipFile zipFile = new ZipFile(file);
130 				ZipEntry entry = zipFile.entries().nextElement();
131 				InputStream compressedFile = zipFile.getInputStream(entry);
132 				input = new ObjectInputStream(compressedFile);
133 			} else if (compress == CompressionMethod.GZIP) {
134 				GZIPInputStream gzip = new GZIPInputStream(new FileInputStream(file));
135 				input = new ObjectInputStream(gzip);
136 			} else { // no compression
137 				input = new ObjectInputStream(new FileInputStream(file));
138 			}
139 
140 			// read the serialized Dump
141 			Dump dump = (Dump) input.readObject();
142 			
143 			// set the reference used later to download data
144 			dump.setFileReader(input);
145 
146 			return dump;
147 		} catch (Exception e) {
148 			logger.error("An exception occured during import - dump file couldn't be read: " + e);
149 			e.printStackTrace();
150 			return null;
151 		}
152 	}
153 }