KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > continuent > sequoia > controller > backup > backupers > PostgreSQLPlainTextBackuper


1 /**
2  * Sequoia: Database clustering technology.
3  * Copyright (C) 2005 Emic Networks
4  * Contact: sequoia@continuent.org
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * Initial developer(s): Emmanuel Cecchet.
19  * Contributor(s): Dylan Hansen, Mathieu Peltier, Olivier Fambon.
20  */

21
22 package org.continuent.sequoia.controller.backup.backupers;
23
24 import java.io.File JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.Date JavaDoc;
28
29 import org.continuent.sequoia.common.exceptions.BackupException;
30 import org.continuent.sequoia.common.log.Trace;
31 import org.continuent.sequoia.controller.backend.DatabaseBackend;
32 import org.continuent.sequoia.controller.backup.BackupManager;
33 import org.continuent.sequoia.controller.backup.DumpTransferInfo;
34
35 /**
36  * This class defines a Backuper for PostgreSQL databases. This backuper makes
37  * dumps in a plain-text format with a .sql extension.
38  * <p>
39  * Supported URLs are:
40  * <ul>
41  * <li>jdbc:postgresql://host:port/dbname?param1=foo,param2=bar</li>
42  * <li>jdbc:postgresql://host/dbname?param1=foo,param2=bar</li>
43  * <li>jdbc:postgresql:dbname?param1=foo,param2=bar</li>
44  * </ul>
45  *
46  * @author <a HREF="mailto:emmanuel.cecchet@emicnetworks.com">Emmanuel Cecchet</a>
47  * @author <a HREF="mailto:dhansen@h2st.com">Dylan Hansen</a>
48  * @author <a HREF="mailto:mathieu.peltier@emicnetworks.com">Mathieu Peltier</a>
49  * @author <a HREF="mailto:olivier.fambon@emicnetworks.com">Olivier Fambon</a>
50  * @version 1.0
51  */

52 public class PostgreSQLPlainTextBackuper extends AbstractPostgreSQLBackuper
53 {
54   // Logger
55
static Trace logger = Trace
56                                              .getLogger(PostgreSQLPlainTextBackuper.class
57                                                  .getName());
58
59   /**
60    * The dump format for this (family of) backuper.
61    */

62   public static final String JavaDoc DUMP_FORMAT = "PostgreSQL Plain Text Dump";
63
64   /**
65    * @see org.continuent.sequoia.controller.backup.Backuper#getDumpFormat()
66    */

67   public String JavaDoc getDumpFormat()
68   {
69     return DUMP_FORMAT;
70   }
71
72   /**
73    * @see org.continuent.sequoia.controller.backup.Backuper#backup(DatabaseBackend,
74    * String, String, String, String, ArrayList)
75    */

76   public Date JavaDoc backup(DatabaseBackend backend, String JavaDoc login, String JavaDoc password,
77       String JavaDoc dumpName, String JavaDoc path, ArrayList JavaDoc tables) throws BackupException
78   {
79     // Parse the URL for the connection information
80
String JavaDoc url = backend.getURL();
81     PostgreSQLUrlInfo info = new AbstractPostgreSQLBackuper.PostgreSQLUrlInfo(
82         url);
83
84     if (logger.isDebugEnabled())
85       logger.debug("Backing up database '" + info.getDbName() + "' on host '"
86           + info.getHost() + ":" + info.getPort() + "'");
87
88     try
89     {
90       // Create the path, if it does not already exist
91
File JavaDoc pathDir = new File JavaDoc(path);
92       if (!pathDir.exists())
93       {
94         pathDir.mkdirs();
95         pathDir.mkdir();
96       }
97       String JavaDoc fullPath = getDumpPhysicalPath(path, dumpName) + ".sql";
98
99       int exitValue = -1;
100       String JavaDoc dumpOptions = "";
101       if (pgDumpFlags != null)
102       {
103         if (pgDumpFlags.indexOf("-F") >= 0
104             || pgDumpFlags.indexOf("--format=") >= 0)
105         {
106           logger.error("Invalid option in pgDumpFlags \"" + pgDumpFlags
107               + "\". You are not allowed to set the format of the dump!");
108         }
109         else
110         {
111           dumpOptions = " " + pgDumpFlags + " ";
112         }
113       }
114       if (useAuthentication)
115       {
116         if (logger.isDebugEnabled())
117           logger.debug("Performing backup using authentication");
118         int timeout = -1;
119         if (dumpTimeout != null)
120         {
121           try
122           {
123             timeout = Integer.parseInt(dumpTimeout);
124           }
125           catch (NumberFormatException JavaDoc e)
126           {
127             logger.error("\"" + dumpTimeout
128                 + "\" is not a valid dump-timeout value!");
129             timeout = -1;
130           }
131         }
132         String JavaDoc[] expectFeed = makeExpectDialogueWithAuthentication("pg_dump",
133             info, " -f " + fullPath + dumpOptions, login, password, timeout);
134
135         String JavaDoc[] cmd = makeExpectCommandReadingStdin();
136
137         exitValue = executeNativeCommand(expectFeed, cmd);
138       }
139       else
140       {
141         if (pgDumpFlags != null)
142         {
143           if (pgDumpFlags.indexOf("-U") >= 0 || pgDumpFlags.indexOf("-W") >= 0)
144           {
145             logger
146                 .error("Invalid option in pgDumpFlags \""
147                     + pgDumpFlags
148                     + "\". Set \"authentication=true\" if you want to use authentication!");
149           }
150           else
151           {
152             dumpOptions = " " + pgDumpFlags + " ";
153           }
154         }
155
156         String JavaDoc cmd = makeCommand("pg_dump", info, "-f " + fullPath
157             + dumpOptions, login);
158         exitValue = executeNativeCommand(cmd);
159       }
160
161       if (exitValue != 0)
162       {
163         printErrors();
164         throw new BackupException(
165             "pg_dump execution did not complete successfully!");
166       }
167
168     }
169     catch (Exception JavaDoc e)
170     {
171       String JavaDoc msg = "Error while performing backup";
172       logger.error(msg, e);
173       throw new BackupException(msg, e);
174     }
175
176     return new Date JavaDoc(System.currentTimeMillis());
177   }
178
179   /**
180    * @see org.continuent.sequoia.controller.backup.Backuper#restore(DatabaseBackend,
181    * String, String, String, String, ArrayList)
182    */

183   public void restore(DatabaseBackend backend, String JavaDoc login, String JavaDoc password,
184       String JavaDoc dumpName, String JavaDoc path, ArrayList JavaDoc tables) throws BackupException
185   {
186     // Parse the URL for the connection information
187
String JavaDoc url = backend.getURL();
188     PostgreSQLUrlInfo info = new AbstractPostgreSQLBackuper.PostgreSQLUrlInfo(
189         url);
190
191     if (logger.isDebugEnabled())
192       logger.debug("Restoring database '" + info.getDbName() + "' on host '"
193           + info.getHost() + ":" + info.getPort() + "'");
194
195     // Check to see if the given path + dumpName exists
196
String JavaDoc fullPath = getDumpPhysicalPath(path, dumpName) + ".sql";
197     File JavaDoc dump = new File JavaDoc(fullPath);
198     if (!dump.exists())
199       throw new BackupException("Backup '" + fullPath + "' does not exist!");
200
201     try
202     {
203       if (useAuthentication)
204       {
205         if (logger.isInfoEnabled())
206           logger.info("Performing database operations using authentication");
207
208         // Drop the database if it already exists
209
if (logger.isDebugEnabled())
210           logger.debug("Dropping database '" + info.getDbName() + "'");
211
212         String JavaDoc[] expectFeed = makeExpectDialogueWithAuthentication("dropdb",
213             info, "", login, password, 60); // 1 minute timeout
214

215         String JavaDoc[] cmd = makeExpectCommandReadingStdin();
216
217         if (executeNativeCommand(expectFeed, cmd) != 0)
218         {
219           printErrors();
220           throw new BackupException(
221               "dropdb execution did not complete successfully!");
222         }
223
224         // Re-create the database, use the specified encoding if provided
225
if (logger.isDebugEnabled())
226           logger.debug("Re-creating '" + info.getDbName() + "'");
227
228         expectFeed = makeExpectDialogueWithAuthentication("createdb", info,
229             encoding != null ? "--encoding=" + encoding + " " : "", login,
230             password, 60); // 1 minute timeout
231

232         cmd = makeExpectCommandReadingStdin();
233
234         if (executeNativeCommand(expectFeed, cmd) != 0)
235         {
236           printErrors();
237           throw new BackupException(
238               "createdb execution did not complete successfully!");
239         }
240
241         // Run a pre-restore script, if specified
242
if (preRestoreScript != null)
243         {
244           if (logger.isDebugEnabled())
245             logger.debug("Running pre-restore script '" + preRestoreScript
246                 + "' on '" + info.getDbName() + "'");
247
248           expectFeed = makeExpectDialogueWithAuthentication("psql", info,
249               "--pset pager -f " + preRestoreScript, login, password, 300); // 5
250
// minutes
251
// timeout
252

253           cmd = makeExpectCommandReadingStdin();
254
255           if (executeNativeCommand(expectFeed, cmd) != 0)
256           {
257             printErrors();
258             throw new BackupException(
259                 "psql execution did not complete successfully!");
260           }
261         }
262
263         // Use the psql command to rebuild the database
264
if (logger.isDebugEnabled())
265           logger.debug("Rebuilding '" + info.getDbName() + "' from dump '"
266               + dumpName + "'");
267
268         int timeout = -1;
269         if (restoreTimeout != null)
270         {
271           try
272           {
273             timeout = Integer.parseInt(restoreTimeout);
274           }
275           catch (NumberFormatException JavaDoc e)
276           {
277             logger.error("\"" + restoreTimeout
278                 + "\" is not a valid restore-timeout value!");
279             timeout = -1;
280           }
281         }
282
283         expectFeed = makeExpectDialogueWithAuthentication("psql", info,
284             "--pset pager -f " + fullPath, login, password, timeout); // 30
285
// minutes
286
// timeout
287

288         cmd = makeExpectCommandReadingStdin();
289
290         if (executeNativeCommand(expectFeed, cmd) != 0)
291         {
292           printErrors();
293           throw new BackupException(
294               "psql execution did not complete successfully!");
295         }
296         
297         // Run a post-restore script, if specified
298
if (postRestoreScript != null)
299         {
300           if (logger.isDebugEnabled())
301             logger.debug("Running post-restore script '" + postRestoreScript
302                 + "' on '" + info.getDbName() + "'");
303
304           expectFeed = makeExpectDialogueWithAuthentication("psql", info,
305               "--pset pager -f " + postRestoreScript, login, password, 300); // 5
306
// minutes
307
// timeout
308

309           cmd = makeExpectCommandReadingStdin();
310
311           if (executeNativeCommand(expectFeed, cmd) != 0)
312           {
313             printErrors();
314             throw new BackupException(
315                 "psql execution did not complete successfully!");
316           }
317         }
318       }
319       else
320       // No authentication
321
{
322         // Drop the database if it already exists
323
if (logger.isDebugEnabled())
324           logger.debug("Dropping database '" + info.getDbName() + "'");
325
326         String JavaDoc dropCmd = makeCommand("dropdb", info, "", login);
327         if (executeNativeCommand(dropCmd) != 0)
328         {
329           printErrors();
330           throw new BackupException(
331               "dropdb execution did not complete successfully!");
332         }
333
334         // Re-create the database, use the specified encoding if provided
335
if (logger.isDebugEnabled())
336           logger.debug("Re-creating '" + info.getDbName() + "'");
337
338         String JavaDoc createCmd = makeCommand("createdb", info, encoding != null
339             ? "--encoding=" + encoding + " "
340             : "", login);
341         if (executeNativeCommand(createCmd) != 0)
342         {
343           printErrors();
344           throw new BackupException(
345               "createdb execution did not complete successfully!");
346         }
347
348         // Run a pre-restore script, if specified
349
if (preRestoreScript != null)
350         {
351           if (logger.isDebugEnabled())
352             logger.debug("Running pre-restore script '" + preRestoreScript
353                 + "' on '" + info.getDbName() + "'");
354
355           String JavaDoc preRestoreCmd = makeCommand("psql", info, "--pset pager -f "
356               + preRestoreScript, login);
357           if (executeNativeCommand(preRestoreCmd) != 0)
358           {
359             printErrors();
360             throw new BackupException(
361                 "psql execution did not complete successfully!");
362           }
363         }
364
365         // Use the psql command to rebuild the database
366
if (logger.isDebugEnabled())
367           logger.debug("Rebuilding '" + info.getDbName() + "' from dump '"
368               + dumpName + "'");
369
370         String JavaDoc replayCmd = makeCommand("psql", info, "--pset pager -f "
371             + fullPath, login);
372         if (executeNativeCommand(replayCmd) != 0)
373         {
374           printErrors();
375           throw new BackupException(
376               "psql execution did not complete successfully!");
377         }
378         
379         // Run a post-restore script, if specified
380
if (postRestoreScript != null)
381         {
382           if (logger.isDebugEnabled())
383             logger.debug("Running post-restore script '" + postRestoreScript
384                 + "' on '" + info.getDbName() + "'");
385
386           String JavaDoc postRestoreCmd = makeCommand("psql", info, "--pset pager -f "
387               + postRestoreScript, login);
388           if (executeNativeCommand(postRestoreCmd) != 0)
389           {
390             printErrors();
391             throw new BackupException(
392                 "psql execution did not complete successfully!");
393           }
394         }
395       }
396     }
397     catch (Exception JavaDoc e)
398     {
399       String JavaDoc msg = "Error while performing backup";
400       logger.error(msg, e);
401       throw new BackupException(msg, e);
402     }
403   }
404
405   /**
406    * @see org.continuent.sequoia.controller.backup.Backuper#fetchDump(org.continuent.sequoia.controller.backup.DumpTransferInfo,
407    * java.lang.String, java.lang.String)
408    */

409   public void fetchDump(DumpTransferInfo dumpTransferInfo, String JavaDoc path,
410       String JavaDoc dumpName) throws BackupException, IOException JavaDoc
411   {
412     BackupManager.fetchDumpFile(dumpTransferInfo, path, dumpName + ".sql");
413   }
414
415   /**
416    * @see org.continuent.sequoia.controller.backup.Backuper#deleteDump(java.lang.String,
417    * java.lang.String)
418    */

419   public void deleteDump(String JavaDoc path, String JavaDoc dumpName) throws BackupException
420   {
421     super.deleteDump(path, dumpName + ".sql");
422   }
423 }
424
Popular Tags