KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > cjdbc > controller > backup > OctopusBackuper


1 /**
2  * C-JDBC: Clustered JDBC.
3  * Copyright (C) 2002-2005 French National Institute For Research In Computer
4  * Science And Control (INRIA).
5  * Contact: c-jdbc@objectweb.org
6  *
7  * This library is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as published by the
9  * Free Software Foundation; either version 2.1 of the License, or any later
10  * version.
11  *
12  * This library is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15  * for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this library; if not, write to the Free Software Foundation,
19  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20  *
21  * Initial developer(s): Emmanuel Cecchet.
22  * Contributor(s): Nicolas Modrzyk.
23  */

24
25 package org.objectweb.cjdbc.controller.backup;
26
27 import java.io.BufferedInputStream JavaDoc;
28 import java.io.BufferedOutputStream JavaDoc;
29 import java.io.BufferedReader JavaDoc;
30 import java.io.BufferedWriter JavaDoc;
31 import java.io.File JavaDoc;
32 import java.io.FileInputStream JavaDoc;
33 import java.io.FileNotFoundException JavaDoc;
34 import java.io.FileOutputStream JavaDoc;
35 import java.io.FileReader JavaDoc;
36 import java.io.FileWriter JavaDoc;
37 import java.io.IOException JavaDoc;
38 import java.io.InputStream JavaDoc;
39 import java.io.ObjectInputStream JavaDoc;
40 import java.io.ObjectOutputStream JavaDoc;
41 import java.io.OutputStream JavaDoc;
42 import java.io.PrintStream JavaDoc;
43 import java.net.ServerSocket JavaDoc;
44 import java.net.Socket JavaDoc;
45 import java.util.ArrayList JavaDoc;
46 import java.util.Date JavaDoc;
47 import java.util.Hashtable JavaDoc;
48
49 import org.apache.log4j.Category;
50 import org.apache.log4j.Priority;
51 import org.objectweb.cjdbc.common.exceptions.BackupException;
52 import org.objectweb.cjdbc.common.exceptions.OctopusException;
53 import org.objectweb.cjdbc.common.i18n.Translate;
54 import org.objectweb.cjdbc.common.log.Trace;
55 import org.objectweb.cjdbc.common.sql.schema.DatabaseTable;
56 import org.objectweb.cjdbc.common.util.FileManagement;
57 import org.objectweb.cjdbc.common.util.LoggingOutputStream;
58 import org.objectweb.cjdbc.common.util.Zipper;
59 import org.objectweb.cjdbc.controller.backend.DatabaseBackend;
60 import org.webdocwf.util.loader.Loader;
61 import org.webdocwf.util.loader.generator.LoaderGenerator;
62
63 /**
64  * This class defines a Backuper based on Octopus v2.8.
65  * <p>
66  * The only option supported by this Backuper is 'zip=[true,false]' which
67  * defines if the dump directory must be compressed in a zip file.
68  *
69  * @author <a HREF="mailto:emmanuel.cecchet@emicnetworks.com">Emmanuel Cecchet
70  * </a>
71  * @author <a HREF="mailto:Nicolas.Modrzyk@inrialpes.fr">Nicolas Modrzyk </a>
72  * @version 1.0
73  */

74 public class OctopusBackuper implements Backuper
75 {
76   static Trace logger = Trace
77                                                    .getLogger(OctopusBackuper.class
78                                                        .getName());
79   private boolean zipBackupFiles = true;
80
81   static
82   {
83     String JavaDoc cjdbcHome = System.getProperty("cjdbc.home");
84     if (cjdbcHome != null)
85       System.setProperty("OCTOPUS_HOME", cjdbcHome + File.separator + "lib"
86           + File.separator + "octopus" + File.separator + "xml");
87   }
88
89   //
90
// Octopus constants
91
//
92

93   private static final int DB_NAME = 0;
94   private static final int DRIVER = 1;
95   private static final int FULL_NAME = 2;
96   private static final int PREFIX_URL = 3;
97
98   // four values ... this is REALLY dirty but I see no other way to deal with
99
// octopus constants ...
100
// 1. If we parse the url, what can describe the db we're dealing with
101
// 2. In octopus specific conf file, <Driver name="hsql">
102
// 3. In octopus general vendors file, what driver are we using ...
103
// 4. the part of the url, octopus adds up automatically, from conf file
104

105   private static final String JavaDoc[] HSQL = {"hsqldb", "hsql",
106       "HypersonicSQL", "jdbc:hsqldb:" };
107   private static final String JavaDoc[] CSV = {"csv", "csv", "Csv",
108       "jdbc:relique:csv:" };
109   private static final String JavaDoc[] MYSQL = {"mysql", "mm", "MySQL",
110       "jdbc:mysql://" };
111   private static final String JavaDoc[] POSTGRESQL = {"postgresql", "postgresql",
112       "PostgreSQL", "jdbc:postgresql://" };
113   private static final String JavaDoc[] ORACLE = {"oracle", "oracle", "Oracle",
114       "jdbc:oracle:thin:" };
115   private static final String JavaDoc[] JTURBO = {"jTurbo", "jTurbo", "MSQL",
116       "jdbc:JTurbo://" };
117   private static final String JavaDoc[] MSSQL = {"microsoft", "microsoft",
118       "MSQL", "jdbc:microsoft:sqlserver://" };
119
120   static final Hashtable JavaDoc TYPES;
121   static
122   {
123     TYPES = new Hashtable JavaDoc();
124     TYPES.put(HSQL[DB_NAME], HSQL);
125     TYPES.put(CSV[DB_NAME], CSV);
126     TYPES.put(MYSQL[DB_NAME], MYSQL);
127     TYPES.put(ORACLE[DB_NAME], ORACLE);
128     TYPES.put(POSTGRESQL[DB_NAME], POSTGRESQL);
129     TYPES.put(JTURBO[DB_NAME], JTURBO);
130     TYPES.put(MSSQL[DB_NAME], MSSQL);
131   }
132
133   //
134
// OctopusBackuper interface implementation
135
//
136

137   /**
138    * Creates a new <code>OctopusBackuper</code> object
139    */

140   public OctopusBackuper()
141   {
142   }
143
144   /**
145    * @see org.objectweb.cjdbc.controller.backup.Backuper#getDumpFormat()
146    */

147   public String JavaDoc getDumpFormat()
148   {
149     if (zipBackupFiles)
150       return "Octopus v2.8 database neutral dump compressed";
151     else
152       return "Octopus v2.8 database neutral dump";
153   }
154
155   /**
156    * @see org.objectweb.cjdbc.controller.backup.Backuper#backup(org.objectweb.cjdbc.controller.backend.DatabaseBackend,
157    * java.lang.String, java.lang.String, java.lang.String,
158    * java.lang.String, java.util.ArrayList)
159    */

160   public Date JavaDoc backup(DatabaseBackend backend, String JavaDoc login, String JavaDoc password,
161       String JavaDoc dumpName, String JavaDoc path, ArrayList JavaDoc tables) throws BackupException
162   {
163     logger.info(Translate.get("backup.manager.backuping.backend", new String JavaDoc[]{
164         backend.getName(), dumpName}));
165
166     // The dump will be located in a sub-directory with the same name
167
String JavaDoc octopusDir = createOctopusDir(path, dumpName);
168
169     String JavaDoc type = getDatabaseType(backend.getURL());
170     String JavaDoc sourceType = getOctopusType(type);
171     String JavaDoc sourceUrl = backend.getURL().substring(getUrlPrefix(type).length());
172     String JavaDoc sourceDriver = getOctopusDriver(type);
173     String JavaDoc targetType = getOctopusType(TYPE_CSV);
174     String JavaDoc targetDriver = getOctopusDriver(TYPE_CSV);
175     String JavaDoc targetUrl = createCsvDir(octopusDir);
176     String JavaDoc targetUser = "";
177     String JavaDoc targetPassword = "";
178
179     try
180     {
181       // Prevent Octopus from dumping everything on the standard output
182
redirectOutputStream();
183
184       // Generate metadata
185
if (logger.isDebugEnabled())
186         logger.debug("### Generating Octopus metadata ###");
187       callOctopusLoader(sourceType, sourceUrl, sourceDriver, login, password,
188           targetType, targetDriver, targetUrl, targetUser, targetPassword,
189           true, true, octopusDir);
190
191       // Generate loader job
192
if (logger.isDebugEnabled())
193         logger.debug("### Generating loader job ###");
194       callOctopusLoader(sourceType, sourceUrl, sourceDriver, login, password,
195           targetType, targetDriver, targetUrl, targetUser, targetPassword,
196           true, false, octopusDir);
197
198       if (logger.isDebugEnabled())
199       {
200         logger.debug("=======================================");
201         logger.debug("Using the following Octopus settings:");
202         logger.debug("Octopus dump directory=" + octopusDir);
203         logger.debug("Target URL=" + targetUrl);
204         logger.debug("Loader job file=" + getLoaderJobFile(octopusDir));
205         logger.debug("Compress backup=" + zipBackupFiles);
206         logger.debug("OCTOPUS HOME:" + System.getProperty("OCTOPUS_HOME"));
207         logger.debug("=======================================");
208       }
209
210       // Perform the backup
211
launchOctopus(octopusDir, dumpName, tables);
212     }
213     catch (Exception JavaDoc e)
214     {
215       String JavaDoc msg = "Error while performing backup for backend "
216           + backend.getName();
217       logger.error(msg, e);
218       throw new BackupException(msg, e);
219     }
220
221     // Check if we need to compress the backup
222
if (zipBackupFiles)
223     {
224       try
225       {
226         if (logger.isDebugEnabled())
227           logger.debug("Compressing dump");
228         Zipper.zip(path + File.separator + dumpName + Zipper.ZIP_EXT,
229             octopusDir, Zipper.STORE_PATH_FROM_ZIP_ROOT);
230         if (logger.isDebugEnabled())
231           logger.debug("Cleaning uncompressed dump files");
232         cleanUp(octopusDir);
233       }
234       catch (Exception JavaDoc e)
235       {
236         String JavaDoc msg = "Error while compressing dump";
237         logger.error(msg, e);
238         throw new BackupException(msg, e);
239       }
240     }
241
242     return new Date JavaDoc(System.currentTimeMillis());
243   }
244
245   /**
246    * @see org.objectweb.cjdbc.controller.backup.Backuper#restore(org.objectweb.cjdbc.controller.backend.DatabaseBackend,
247    * java.lang.String, java.lang.String, java.lang.String,
248    * java.lang.String, java.util.ArrayList)
249    */

250   public void restore(DatabaseBackend backend, String JavaDoc login, String JavaDoc password,
251       String JavaDoc dumpName, String JavaDoc path, ArrayList JavaDoc tables) throws BackupException
252   {
253     logger.info(Translate.get("backup.manager.restoring.backend", new String JavaDoc[]{
254         backend.getName(), dumpName}));
255
256     // The dump will be located in a sub-directory with the same name
257
String JavaDoc octopusDir = createOctopusDir(path, dumpName);
258
259     if (zipBackupFiles)
260     {
261       try
262       {
263         if (logger.isDebugEnabled())
264           logger.debug("Uncompressing dump");
265         Zipper.unzip(path + File.separator + dumpName + Zipper.ZIP_EXT,
266             octopusDir);
267       }
268       catch (Exception JavaDoc e)
269       {
270         String JavaDoc msg = "Error while uncompressing dump";
271         logger.error(msg, e);
272         throw new BackupException(msg, e);
273       }
274     }
275
276     String JavaDoc type = getDatabaseType(backend.getURL());
277     String JavaDoc targetType = getOctopusType(type);
278     String JavaDoc targetUrl = backend.getURL().substring(getUrlPrefix(type).length());
279     String JavaDoc targetDriver = getOctopusDriver(type);
280     String JavaDoc sourceType = getOctopusType(TYPE_CSV);
281     String JavaDoc sourceDriver = getOctopusDriver(TYPE_CSV);
282     String JavaDoc sourceUrl = createCsvDir(octopusDir);
283     String JavaDoc sourceUser = "";
284     String JavaDoc sourcePassword = "";
285
286     try
287     {
288       // Prevent Octopus from dumping everything on the standard output
289
redirectOutputStream();
290
291       // Generate loader job
292
if (logger.isDebugEnabled())
293         logger.debug("### Generating loader job ###");
294       callOctopusLoader(sourceType, sourceUrl, sourceDriver, sourceUser,
295           sourcePassword, targetType, targetDriver, targetUrl, login, password,
296           false, false, octopusDir);
297
298       setOctopusLoaderJob(octopusDir, sourceType);
299
300       if (logger.isDebugEnabled())
301       {
302         logger.debug("=======================================");
303         logger.debug("Using the following Octopus settings:");
304         logger.debug("Octopus dump directory=" + octopusDir);
305         logger.debug("Source URL=" + sourceUrl);
306         logger.debug("Target URL=" + targetUrl);
307         logger.debug("Loader job file=" + getLoaderJobFile(octopusDir));
308         logger.debug("Compress backup=" + zipBackupFiles);
309         logger.debug("OCTOPUS HOME:" + System.getProperty("OCTOPUS_HOME"));
310         logger.debug("=======================================");
311       }
312
313       // Perform the backup
314
launchOctopus(octopusDir, dumpName, tables);
315
316       if (zipBackupFiles)
317       {
318         if (logger.isDebugEnabled())
319           logger.debug("Cleaning backup files");
320         cleanUp(octopusDir);
321       }
322     }
323     catch (Exception JavaDoc e)
324     {
325       String JavaDoc msg = "Error while performing restore operation on backend "
326           + backend.getName();
327       logger.error(msg, e);
328       throw new BackupException(msg, e);
329     }
330
331   }
332
333   /**
334    * @see org.objectweb.cjdbc.controller.backup.Backuper#deleteDump(java.lang.String,
335    * java.lang.String)
336    */

337   public void deleteDump(String JavaDoc path, String JavaDoc dumpName) throws BackupException
338   {
339     if (zipBackupFiles)
340     {
341       File JavaDoc toRemove = new File JavaDoc(path + File.separator + dumpName
342           + Zipper.ZIP_EXT);
343       if (logger.isDebugEnabled())
344         logger.debug("Deleting compressed dump " + toRemove);
345       toRemove.delete();
346     }
347     else
348     {
349       if (logger.isDebugEnabled())
350         logger.debug("Deleting dump directory " + path + File.separator
351             + dumpName);
352       cleanUp(path + File.separator + dumpName);
353     }
354   }
355
356   //
357
// Octopus wrappers
358
//
359

360   private static final String JavaDoc TYPE_CSV = "csv";
361   private static final String JavaDoc COPY_MODE = "copy";
362   private static final String JavaDoc OCTOPUS_INCLUDE_HREF = "<include HREF=\"sql/";
363
364   private void callOctopusLoader(String JavaDoc sourceType, String JavaDoc sourceUrl,
365       String JavaDoc sourceDriver, String JavaDoc sourceUser, String JavaDoc sourcePassword,
366       String JavaDoc targetType, String JavaDoc targetDriver, String JavaDoc targetUrl,
367       String JavaDoc targetUser, String JavaDoc targetPassword, boolean backup,
368       boolean generateAllVendors, String JavaDoc octopusDir) throws OctopusException
369   {
370     try
371     {
372       if (logger.isDebugEnabled())
373       {
374         logger.debug("Source Type:" + sourceType);
375         logger.debug("Source Driver:" + sourceDriver);
376         logger.debug("Source URL :" + sourceUrl);
377         logger.debug("Source User :" + sourceUser);
378         logger.debug("Target Type:" + targetType);
379         logger.debug("Target Driver:" + targetDriver);
380         logger.debug("Target URL:" + targetUrl);
381         logger.debug("Target User :" + targetUser);
382         logger.debug("Generate SQL for all vendors :" + generateAllVendors);
383       }
384       LoaderGenerator loader = new LoaderGenerator(sourceType, // sourceType
385
sourceUrl, // sourceDatabase Url?
386
COPY_MODE, // valueMode
387
octopusDir, // generatorOutput
388
sourceDriver, // sourceDriverName
389
targetDriver, // TargetDriverName
390
targetUrl, // targetDataBase
391
targetType, // TargetType
392
sourceUser, // sourceUser
393
sourcePassword, // sourcePassword
394
targetUser, // targetUser
395
targetPassword, // targetPassword
396
"", // domlPath
397
"org.webdoc.util.loader", // package name
398
"true", // generate drop table stmt
399
"true", // generate drop integrity statement
400
"true", // generate create table stmt
401
"true", // generate create pk statement
402
"true", // generate create fk statement
403
"true", // generate create index stmt
404
String.valueOf(generateAllVendors), // generate sql for all vendors
405
String.valueOf(!generateAllVendors), // generate xml
406
"false", // generate doml
407
String.valueOf(!generateAllVendors), // full mode ??
408
String.valueOf(!backup), // restore mode
409
null, // convertTablesToSemicolonSeparatedList(database.getTables()),
410
// tables list
411
null // Jar file structure
412
);
413       loader.generate();
414     }
415     catch (Exception JavaDoc e)
416     {
417       throw new OctopusException(e);
418     }
419   }
420
421   /**
422    * This start octopus with previously generated LoaderJob file
423    *
424    * @param octopusDir the working directory
425    * @param tables the list of tables to backup, null means all tables
426    * @throws OctopusException if octopus fails
427    */

428   private void launchOctopus(String JavaDoc octopusDir, String JavaDoc dumpName,
429       ArrayList JavaDoc tables) throws OctopusException
430   {
431     try
432     {
433       Loader myOctopus;
434       String JavaDoc loaderLogging;
435       if (logger.isDebugEnabled())
436         loaderLogging = Loader.LOGMODE_FULL;
437       else if (!logger.isFatalEnabled()) // Logger is OFF
438
loaderLogging = Loader.LOGMODE_NONE;
439       else
440         loaderLogging = Loader.LOGMODE_NORMAL;
441
442       if (tables == null)
443       {
444         // Copy everything
445
myOctopus = new Loader(getLoaderJobFile(octopusDir), loaderLogging,
446             "cjdbc", octopusDir, "Octopus" + dumpName + ".log", true, null,
447             null, true, null, 0, 100);
448       }
449       else
450       {
451         // Copy only the tables we want
452
myOctopus = new Loader(getLoaderJobFile(octopusDir), loaderLogging,
453             "cjdbc", octopusDir, "Octopus" + dumpName + ".log", true, null,
454             null, true, null, 0, 100, convertTablesToArray(tables));
455       }
456       try
457       {
458         myOctopus.load();
459       }
460       catch (Exception JavaDoc e)
461       {
462         logger.error("Failed to load octopus", e);
463         throw new OctopusException(Translate.get(
464             "controller.octopus.load.failed", e));
465       }
466     }
467     // I am doing this because Octopus throws NullPointerException
468
// all the time so it is impossible to know which failed
469
catch (OctopusException oe)
470     {
471       // This is thrown only by the above.
472
throw oe;
473     }
474     catch (Exception JavaDoc e)
475     {
476       throw new OctopusException(Translate
477           .get("controller.octopus.instance.failed"));
478     }
479   }
480
481   private void cleanUp(String JavaDoc octopusDir)
482   {
483     if (logger.isDebugEnabled())
484       logger.debug("Cleaning up temporary backup files...");
485     File JavaDoc toRemove = new File JavaDoc(octopusDir);
486     FileManagement.deleteDir(toRemove);
487   }
488
489   private String JavaDoc[] convertTablesToArray(ArrayList JavaDoc tablesList)
490   {
491     int length = tablesList.size();
492     String JavaDoc[] result = new String JavaDoc[length];
493     for (int i = 0; i < length; i++)
494       result[i] = ((DatabaseTable) tablesList.get(i)).getName();
495     return result;
496   }
497
498   private String JavaDoc createOctopusDir(String JavaDoc path, String JavaDoc dumpName)
499       throws BackupException
500   {
501     // Create main octopus directory
502
String JavaDoc octopusDir = path + File.separator + dumpName;
503
504     File JavaDoc octopusd = new File JavaDoc(octopusDir);
505     octopusd.mkdirs();
506     octopusd.mkdir();
507
508     if (!octopusd.exists())
509       throw new BackupException("backup.directory.cannot.be.created");
510
511     return octopusDir;
512   }
513
514   private String JavaDoc createCsvDir(String JavaDoc octopusDir) throws BackupException
515   {
516     // Create Csv directory
517
String JavaDoc csvDir = TYPE_CSV;
518     File JavaDoc csvd = new File JavaDoc(octopusDir + File.separator + csvDir);
519     csvDir = csvd.getAbsolutePath();
520     csvd.mkdirs();
521     csvd.mkdir();
522
523     if (!csvd.exists())
524       throw new BackupException("backup.directory.cannot.be.created");
525
526     return csvDir;
527   }
528
529   private String JavaDoc getDatabaseType(String JavaDoc url) throws BackupException
530   {
531     if (url == null)
532       throw new BackupException("Invalid null source url");
533     int index = url.indexOf(':');
534     int index2 = url.indexOf(':', index + 1);
535     if (index == -1 || index2 == -1 || index > index2)
536       throw new BackupException("Invalid source url format");
537     String JavaDoc type = url.substring(index + 1, index2);
538     return type;
539   }
540
541   private String JavaDoc getLoaderJobFile(String JavaDoc octopusDir)
542   {
543     return octopusDir + File.separator + "LoaderJob.olj";
544   }
545
546   private void redirectOutputStream()
547   {
548     System.setOut(new PrintStream JavaDoc(new LoggingOutputStream(Category
549         .getInstance(this.getClass().getName()), Priority.DEBUG), true));
550   }
551
552   private void setOctopusLoaderJob(String JavaDoc octopusDir, String JavaDoc sourceType)
553       throws OctopusException
554   {
555     String JavaDoc onErrorContinueEqualFalse = "onErrorContinue=\"false\"";
556     String JavaDoc onErrorContinueEqualTrue = "onErrorContinue=\"true\"";
557     BufferedReader JavaDoc br = null;
558     BufferedWriter JavaDoc bw = null;
559
560     try
561     {
562       br = new BufferedReader JavaDoc(new FileReader JavaDoc(getLoaderJobFile(octopusDir)));
563       String JavaDoc line = "";
564       StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
565
566       while ((line = br.readLine()) != null)
567       {
568         /* Give the metadata location */
569         int idx = line.indexOf(OCTOPUS_INCLUDE_HREF);
570         if (idx != -1)
571         {
572           idx += OCTOPUS_INCLUDE_HREF.length();
573           // -4 = Skip "sql/"
574
line = line.substring(0, idx - 4) + ".." + File.separator
575               + octopusDir + File.separator + "SQLForAllVendors"
576               + File.separator + sourceType + File.separator + "sql"
577               + File.separator + line.substring(idx);
578         }
579
580         /* Force on error continue */
581         int index7 = line.indexOf(onErrorContinueEqualFalse);
582         if (index7 != -1)
583         {
584           line = line.substring(0, index7) + onErrorContinueEqualTrue
585               + line.substring(index7 + onErrorContinueEqualFalse.length());
586         }
587         buffer.append(line + System.getProperty("line.separator"));
588       }
589       br.close();
590       if (logger.isDebugEnabled())
591       {
592         logger.debug("Octopus file updated with success");
593       }
594
595       bw = new BufferedWriter JavaDoc(new FileWriter JavaDoc(getLoaderJobFile(octopusDir)));
596       bw.write(buffer.toString());
597       bw.close();
598     }
599     catch (FileNotFoundException JavaDoc fie)
600     {
601       // loader job was not generated properly
602
logger.warn(Translate.get("controller.octopus.loader.job.not.found"));
603       throw new OctopusException(fie.getMessage());
604     }
605     catch (IOException JavaDoc e)
606     {
607       // Error while reading file
608
logger.warn(Translate.get("controller.octopus.loader.io.problem"));
609     }
610     finally
611     {
612       // close the open streams
613
if (bw != null)
614         try
615         {
616           bw.close();
617         }
618         catch (IOException JavaDoc e1)
619         {
620
621         }
622       if (br != null)
623         try
624         {
625           br.close();
626         }
627         catch (IOException JavaDoc e2)
628         {
629         }
630     }
631   }
632
633   /**
634    * Get octopus type.
635    *
636    * @param type from url
637    * @return value from hashtable or null
638    */

639   private String JavaDoc getOctopusType(String JavaDoc type)
640   {
641     if (type == null)
642       return null;
643     return ((String JavaDoc[]) TYPES.get(type))[OctopusBackuper.FULL_NAME];
644   }
645
646   /**
647    * Get octopus driver.
648    *
649    * @param type from url
650    * @return value from hashtable or null
651    */

652   private String JavaDoc getOctopusDriver(String JavaDoc type)
653   {
654     if (type == null)
655       return null;
656     return ((String JavaDoc[]) TYPES.get(type))[OctopusBackuper.DRIVER];
657   }
658
659   /**
660    * Get Octopus url prefix
661    *
662    * @param type from url
663    * @return value from hashtable or null
664    */

665   private String JavaDoc getUrlPrefix(String JavaDoc type)
666   {
667     if (type == null)
668       return null;
669     return ((String JavaDoc[]) TYPES.get(type))[OctopusBackuper.PREFIX_URL];
670   }
671
672   //
673
// Octopus Backuper options
674
//
675

676   /**
677    * @see org.objectweb.cjdbc.controller.backup.Backuper#getOptions()
678    */

679   public String JavaDoc getOptions()
680   {
681     return "zip=" + String.valueOf(zipBackupFiles);
682   }
683
684   /**
685    * @see org.objectweb.cjdbc.controller.backup.Backuper#setOptions(java.lang.String)
686    */

687   public void setOptions(String JavaDoc options)
688   {
689     if (options != null)
690     {
691       int idx = options.indexOf("zip=");
692       if (idx > -1)
693       {
694         try
695         {
696           zipBackupFiles = !"false".equals(options.substring(idx + 1).trim());
697         }
698         catch (RuntimeException JavaDoc e)
699         {
700           zipBackupFiles = true;
701           logger
702               .warn("Invalid option for OctopusBackuper, available option is 'zip=[true,false]' ("
703                   + options + ")");
704         }
705       }
706     }
707     logger.info("OctopusBackuper backup compression is set to "
708         + zipBackupFiles);
709   }
710
711   /**
712    * @see org.objectweb.cjdbc.controller.backup.Backuper#getBackupManager()
713    */

714   public BackupManager getBackupManager()
715   {
716     // TODO: Auto-generated method stub
717
return null;
718   }
719
720   /**
721    * @see org.objectweb.cjdbc.controller.backup.Backuper#fetchDump(org.objectweb.cjdbc.controller.backup.DumpTransferInfo,
722    * java.lang.String, java.lang.String)
723    */

724   public void fetchDump(DumpTransferInfo dumpTransferInfo, String JavaDoc path,
725       String JavaDoc dumpName) throws BackupException, IOException JavaDoc
726   {
727
728     //
729
// Phase 1: talk to dump server using it's very smart protocol
730
//
731

732     Socket JavaDoc soc = new Socket JavaDoc();
733
734     soc.connect(dumpTransferInfo.getBackuperServerAddress());
735
736     ObjectOutputStream JavaDoc oos = new ObjectOutputStream JavaDoc(soc.getOutputStream());
737
738     oos.writeLong(dumpTransferInfo.getSessionKey());
739     oos.writeObject(path);
740     oos.writeObject(dumpName);
741
742     // end of very smart protocol: read server response.
743
InputStream JavaDoc is = new BufferedInputStream JavaDoc(soc.getInputStream());
744     int response = is.read();
745     if (response != 0xEC) // server replies "EC" to say it's happy to carry on.
746
throw new BackupException("bad response from dump server");
747
748     //
749
// Phase 2: protocolar ablutions ok, go copy the stream into a local file
750
//
751

752     File JavaDoc thePath = new File JavaDoc(path);
753     if (!thePath.exists())
754       thePath.mkdirs();
755
756     File JavaDoc theFile = new File JavaDoc(path + File.separator + dumpName + Zipper.ZIP_EXT);
757     theFile.createNewFile();
758
759     OutputStream JavaDoc os = new BufferedOutputStream JavaDoc(new FileOutputStream JavaDoc(theFile));
760     int c = is.read();
761     while (c != -1)
762     {
763       os.write(c);
764       c = is.read();
765     }
766     os.flush();
767     os.close();
768   }
769
770   class DumpTransferServerThread extends Thread JavaDoc
771   {
772     private ServerSocket JavaDoc serverSocket;
773     private long sessionKey;
774
775     public void run()
776     {
777       try
778       {
779         //
780
// Wait for client to connect
781
//
782
Socket JavaDoc soc = serverSocket.accept();
783         ObjectInputStream JavaDoc ois = new ObjectInputStream JavaDoc(soc.getInputStream());
784
785         //
786
// Phase 1: server side very smart protocol to authenticate client
787
//
788
long key = ois.readLong();
789
790         if (key != this.sessionKey)
791         {
792           soc.close();
793           return; // read will fail on client side
794
}
795
796         String JavaDoc path = (String JavaDoc) ois.readObject();
797         String JavaDoc dumpName = (String JavaDoc) ois.readObject();
798
799         if (!zipBackupFiles)
800         {
801           logger.error("non-zipped backup server not supported");
802           soc.close();
803           return;
804         }
805
806         File JavaDoc theFile = new File JavaDoc(path + File.separator + dumpName
807             + Zipper.ZIP_EXT);
808
809         if (!theFile.exists())
810         {
811           logger.error("requested dump does not exist: " + theFile.getPath());
812           soc.close();
813           return;
814         }
815
816         InputStream JavaDoc is = new BufferedInputStream JavaDoc(new FileInputStream JavaDoc(theFile));
817         OutputStream JavaDoc os = new BufferedOutputStream JavaDoc(soc.getOutputStream());
818
819         // end of very smart protocol: return "EC" to client to say it's ok to
820
// fetch the dump
821
os.write(0xEC);
822
823         //
824
// Phase 2: burst the dump file over the wire.
825
//
826
int c = is.read();
827         while (c != -1)
828         {
829           os.write(c);
830           c = is.read();
831         }
832         os.flush();
833         os.close();
834       }
835       catch (IOException JavaDoc e)
836       {
837         e.printStackTrace();
838       }
839       catch (ClassNotFoundException JavaDoc e)
840       {
841         e.printStackTrace();
842       }
843     }
844
845     DumpTransferServerThread(ServerSocket JavaDoc serverSocket, long sessionKey)
846     {
847       setName("DumpTransfer server thread");
848       this.serverSocket = serverSocket;
849       this.sessionKey = sessionKey;
850     }
851   }
852
853   /**
854    * @see org.objectweb.cjdbc.controller.backup.Backuper#setupServer()
855    */

856   public DumpTransferInfo setupServer() throws IOException JavaDoc
857   {
858     ServerSocket JavaDoc soc = new ServerSocket JavaDoc();
859     soc.bind(null);
860     long sessionKey = soc.hashCode();
861
862     new DumpTransferServerThread(soc, sessionKey).start();
863
864     return new DumpTransferInfo(soc.getLocalSocketAddress(), sessionKey);
865   }
866 }
867
Popular Tags