throws DirectoryException
{
// Get the properties to use for the backup. We don't care whether or not
// it's incremental, so there's no need to get that.
String backupID = backupConfig.getBackupID();
BackupDirectory backupDirectory = backupConfig.getBackupDirectory();
boolean compress = backupConfig.compressData();
boolean encrypt = backupConfig.encryptData();
boolean hash = backupConfig.hashData();
boolean signHash = backupConfig.signHash();
// Create a hash map that will hold the extra backup property information
// for this backup.
HashMap<String,String> backupProperties = new HashMap<String,String>();
// Get the crypto manager and use it to obtain references to the message
// digest and/or MAC to use for hashing and/or signing.
CryptoManager cryptoManager = DirectoryServer.getCryptoManager();
Mac mac = null;
MessageDigest digest = null;
String digestAlgorithm = null;
String macKeyID = null;
if (hash)
{
if (signHash)
{
try
{
macKeyID = cryptoManager.getMacEngineKeyEntryID();
backupProperties.put(BACKUP_PROPERTY_MAC_KEY_ID, macKeyID);
mac = cryptoManager.getMacEngine(macKeyID);
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
Message message = ERR_TASKS_BACKUP_CANNOT_GET_MAC.get(
macKeyID, stackTraceToSingleLineString(e));
throw new DirectoryException(
DirectoryServer.getServerErrorResultCode(), message,
e);
}
}
else
{
digestAlgorithm = cryptoManager.getPreferredMessageDigestAlgorithm();
backupProperties.put(BACKUP_PROPERTY_DIGEST_ALGORITHM, digestAlgorithm);
try
{
digest = cryptoManager.getPreferredMessageDigest();
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
Message message = ERR_TASKS_BACKUP_CANNOT_GET_DIGEST.get(
digestAlgorithm, stackTraceToSingleLineString(e));
throw new DirectoryException(
DirectoryServer.getServerErrorResultCode(), message,
e);
}
}
}
// Create an output stream that will be used to write the archive file. At
// its core, it will be a file output stream to put a file on the disk. If
// we are to encrypt the data, then that file output stream will be wrapped
// in a cipher output stream. The resulting output stream will then be
// wrapped by a zip output stream (which may or may not actually use
// compression).
String filename = null;
OutputStream outputStream;
try
{
filename = TASKS_BACKUP_BASE_FILENAME + backupID;
File archiveFile = new File(backupDirectory.getPath() + File.separator +
filename);
if (archiveFile.exists())
{
int i=1;
while (true)
{
archiveFile = new File(backupDirectory.getPath() + File.separator +
filename + "." + i);
if (archiveFile.exists())
{
i++;
}
else
{
filename = filename + "." + i;
break;
}
}
}
outputStream = new FileOutputStream(archiveFile, false);
backupProperties.put(BACKUP_PROPERTY_ARCHIVE_FILENAME, filename);
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
Message message = ERR_TASKS_BACKUP_CANNOT_CREATE_ARCHIVE_FILE.
get(String.valueOf(filename), backupDirectory.getPath(),
getExceptionMessage(e));
throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
message, e);
}
// If we should encrypt the data, then wrap the output stream in a cipher
// output stream.
if (encrypt)
{
try
{
outputStream
= cryptoManager.getCipherOutputStream(outputStream);
}
catch (CryptoManagerException e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
Message message = ERR_TASKS_BACKUP_CANNOT_GET_CIPHER.get(
stackTraceToSingleLineString(e));
throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
message, e);
}
}
// Wrap the file output stream in a zip output stream.
ZipOutputStream zipStream = new ZipOutputStream(outputStream);
Message message = ERR_TASKS_BACKUP_ZIP_COMMENT.get(
DynamicConstants.PRODUCT_NAME,
backupID);
zipStream.setComment(String.valueOf(message));
if (compress)
{
zipStream.setLevel(Deflater.DEFAULT_COMPRESSION);
}
else
{
zipStream.setLevel(Deflater.NO_COMPRESSION);
}
// Take tasks file and write it to the zip stream. If we
// are using a hash or MAC, then calculate that as well.
byte[] buffer = new byte[8192];
File tasksFile = getFileForPath(taskBackingFile);
String baseName = tasksFile.getName();
// We'll put the name in the hash, too.
if (hash) {
if (signHash) {
mac.update(getBytes(baseName));
} else {
digest.update(getBytes(baseName));
}
}
InputStream inputStream = null;
try {
ZipEntry zipEntry = new ZipEntry(baseName);
zipStream.putNextEntry(zipEntry);
inputStream = new FileInputStream(tasksFile);
while (true) {
int bytesRead = inputStream.read(buffer);
if (bytesRead < 0 || backupConfig.isCancelled()) {
break;
}
if (hash) {
if (signHash) {
mac.update(buffer, 0, bytesRead);
} else {
digest.update(buffer, 0, bytesRead);
}
}
zipStream.write(buffer, 0, bytesRead);
}
zipStream.closeEntry();
inputStream.close();
} catch (Exception e) {
if (debugEnabled()) {
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
try {
inputStream.close();
} catch (Exception e2) {
}
try {
zipStream.close();
} catch (Exception e2) {
}
message = ERR_TASKS_BACKUP_CANNOT_BACKUP_TASKS_FILE.get(baseName,
stackTraceToSingleLineString(e));
throw new DirectoryException(
DirectoryServer.getServerErrorResultCode(),
message, e);
}
// We're done writing the file, so close the zip stream (which should also
// close the underlying stream).
try
{
zipStream.close();
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
message = ERR_TASKS_BACKUP_CANNOT_CLOSE_ZIP_STREAM.get(
filename, backupDirectory.getPath(), stackTraceToSingleLineString(e));
throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
message, e);
}
// Get the digest or MAC bytes if appropriate.
byte[] digestBytes = null;
byte[] macBytes = null;
if (hash)
{
if (signHash)
{
macBytes = mac.doFinal();
}
else
{
digestBytes = digest.digest();
}
}
// Create the backup info structure for this backup and add it to the backup
// directory.
// FIXME -- Should I use the date from when I started or finished?
BackupInfo backupInfo = new BackupInfo(backupDirectory, backupID,
new Date(), false, compress,
encrypt, digestBytes, macBytes,
null, backupProperties);
try
{
backupDirectory.addBackup(backupInfo);
backupDirectory.writeBackupDirectoryDescriptor();
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
message = ERR_TASKS_BACKUP_CANNOT_UPDATE_BACKUP_DESCRIPTOR.get(
backupDirectory.getDescriptorPath(), stackTraceToSingleLineString(e));
throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
message, e);
}
}