001: /**
002: * Sequoia: Database clustering technology.
003: * Copyright (C) 2005 Emic Networks
004: * Contact: sequoia@continuent.org
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: *
018: * Initial developer(s): Emmanuel Cecchet.
019: * Contributor(s): ______________________.
020: */package org.continuent.sequoia.controller.backup.backupers;
021:
022: import java.io.File;
023: import java.io.IOException;
024: import java.util.ArrayList;
025: import java.util.Date;
026:
027: import org.continuent.sequoia.common.exceptions.BackupException;
028: import org.continuent.sequoia.common.log.Trace;
029: import org.continuent.sequoia.common.util.FileManagement;
030: import org.continuent.sequoia.controller.backend.DatabaseBackend;
031: import org.continuent.sequoia.controller.backup.BackupManager;
032: import org.continuent.sequoia.controller.backup.Backuper;
033: import org.continuent.sequoia.controller.backup.DumpTransferInfo;
034:
035: /**
036: * This class defines a Backuper for Apache Derby databases.
037: * <p>
038: * Supported URLs are jdbc:derby:PathToDerbyDatabase[;options]
039: * <p>
040: * The Backuper itself does not take any option. It simply dumps the Derby
041: * directory into a zip file.
042: *
043: * @author <a href="mailto:emmanuel.cecchet@emicnetworks.com">Emmanuel Cecchet</a>
044: * @version 1.0
045: */
046: public class DerbyEmbeddedBackuper implements Backuper {
047: static Trace logger = Trace.getLogger(DerbyEmbeddedBackuper.class
048: .getName());
049:
050: /**
051: * Creates a new <code>DerbyEmbeddedBackuper</code> object
052: */
053: public DerbyEmbeddedBackuper() {
054: }
055:
056: /**
057: * @see org.continuent.sequoia.controller.backup.Backuper#getDumpFormat()
058: */
059: public String getDumpFormat() {
060: return "Derby embedded compressed dump";
061: }
062:
063: /**
064: * @see org.continuent.sequoia.controller.backup.Backuper#getOptions()
065: */
066: public String getOptions() {
067: return null;
068: }
069:
070: /**
071: * @see org.continuent.sequoia.controller.backup.Backuper#setOptions(java.lang.String)
072: */
073: public void setOptions(String options) {
074: // Ignored, no options
075: }
076:
077: /**
078: * @see org.continuent.sequoia.controller.backup.Backuper#backup(org.continuent.sequoia.controller.backend.DatabaseBackend,
079: * java.lang.String, java.lang.String, java.lang.String,
080: * java.lang.String, java.util.ArrayList)
081: */
082: public Date backup(DatabaseBackend backend, String login,
083: String password, String dumpName, String path,
084: ArrayList tables) throws BackupException {
085: String derbyPath = getDerbyPath(backend, true);
086:
087: try {
088: File pathDir = new File(path);
089: if (!pathDir.exists()) {
090: pathDir.mkdirs();
091: pathDir.mkdir();
092: }
093:
094: if (logger.isDebugEnabled())
095: logger.debug("Archiving " + derbyPath + " in " + path
096: + File.separator + dumpName + Zipper.ZIP_EXT);
097:
098: Zipper.zip(getDumpPhysicalPath(path, dumpName), derbyPath,
099: Zipper.STORE_PATH_FROM_ZIP_ROOT);
100: } catch (Exception e) {
101: String msg = "Error while performing backup";
102: logger.error(msg, e);
103: throw new BackupException(msg, e);
104: }
105:
106: return new Date(System.currentTimeMillis());
107: }
108:
109: /**
110: * @see org.continuent.sequoia.controller.backup.Backuper#restore(org.continuent.sequoia.controller.backend.DatabaseBackend,
111: * java.lang.String, java.lang.String, java.lang.String,
112: * java.lang.String, java.util.ArrayList)
113: */
114: public void restore(DatabaseBackend backend, String login,
115: String password, String dumpName, String path,
116: ArrayList tables) throws BackupException {
117: String derbyPath = getDerbyPath(backend, false);
118:
119: File derbyDir = new File(derbyPath);
120:
121: // First delete any existing directory
122: if (FileManagement.deleteDir(derbyDir))
123: logger.info("Existing Derby directory " + derbyPath
124: + " has been deleted.");
125:
126: // Now create the dir
127: derbyDir.mkdirs();
128: derbyDir.mkdir();
129:
130: // Unzip the dump
131: try {
132: if (logger.isDebugEnabled())
133: logger.debug("Uncompressing dump");
134: Zipper
135: .unzip(getDumpPhysicalPath(path, dumpName),
136: derbyPath);
137: } catch (Exception e) {
138: String msg = "Error while uncompressing dump";
139: logger.error(msg, e);
140: throw new BackupException(msg, e);
141: }
142: }
143:
144: /**
145: * @see org.continuent.sequoia.controller.backup.Backuper#deleteDump(java.lang.String,
146: * java.lang.String)
147: */
148: public void deleteDump(String path, String dumpName)
149: throws BackupException {
150: File toRemove = new File(getDumpPhysicalPath(path, dumpName));
151: if (logger.isDebugEnabled())
152: logger.debug("Deleting compressed dump " + toRemove);
153: toRemove.delete();
154: }
155:
156: /**
157: * Get the dump physical path from its logical name
158: *
159: * @param path the path where the dump is stored
160: * @param dumpName dump logical name
161: * @return path to zip file
162: */
163: private String getDumpPhysicalPath(String path, String dumpName) {
164: return path + File.separator + dumpName + Zipper.ZIP_EXT;
165: }
166:
167: /**
168: * Extract the path where the Derby database is stored by parsing the backend
169: * JDBC URL.
170: *
171: * @param backend the Derby backend
172: * @param checkPath if true we check if the path is a valid directory
173: * @return path to the Derby database
174: * @throws BackupException if the URL is not valid or the path not valid
175: */
176: private String getDerbyPath(DatabaseBackend backend,
177: boolean checkPath) throws BackupException {
178: String url = backend.getURL();
179: if (!url.startsWith("jdbc:derby:"))
180: throw new BackupException("Unsupported url " + url
181: + " expecting jdbc:derby:pathToDb");
182:
183: // Strip 'jdbc:derby:'
184: // 11 = "jdbc:derby:".length()
185: String derbyPath = url.substring(11);
186: // Remove all options that are after the first semicolon
187: int semicolon = derbyPath.indexOf(';');
188: if (semicolon > -1)
189: derbyPath = derbyPath.substring(0, semicolon);
190:
191: if (checkPath) {
192: File checkDerbyPath = new File(derbyPath);
193: if (!checkDerbyPath.isDirectory())
194: throw new BackupException(
195: "Directory "
196: + derbyPath
197: + " does not exist. This might be due to an unsupported URL format (expectin jdbc:derby:pathToDb)");
198: }
199:
200: return derbyPath;
201: }
202:
203: /**
204: * @see org.continuent.sequoia.controller.backup.Backuper#fetchDump(org.continuent.sequoia.controller.backup.DumpTransferInfo,
205: * java.lang.String, java.lang.String)
206: */
207: public void fetchDump(DumpTransferInfo dumpTransferInfo,
208: String path, String dumpName) throws BackupException,
209: IOException {
210: BackupManager.fetchDumpFile(dumpTransferInfo, path, dumpName
211: + Zipper.ZIP_EXT);
212: }
213:
214: /**
215: * @see org.continuent.sequoia.controller.backup.Backuper#setupDumpServer()
216: */
217: public DumpTransferInfo setupDumpServer() throws IOException {
218: return BackupManager.setupDumpFileServer();
219: }
220:
221: }
|