package org.springframework.roo.addon.backup;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.Validate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.springframework.roo.process.manager.FileManager;
import org.springframework.roo.process.manager.MutableFile;
import org.springframework.roo.project.Path;
import org.springframework.roo.project.ProjectOperations;
import org.springframework.roo.support.logging.HandlerUtils;
import org.springframework.roo.support.util.FileUtils;
import org.osgi.service.component.ComponentContext;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
/**
* Operations for the 'backup' add-on.
*
* @author Stefan Schmidt
* @author Ben Alex
* @author Alan Stewart
* @since 1.0
*/
@Component
@Service
public class BackupOperationsImpl implements BackupOperations {
// ------------ OSGi component attributes ----------------
private BundleContext context;
protected void activate(final ComponentContext cContext) {
this.context = cContext.getBundleContext();
}
private static final Logger LOGGER = HandlerUtils.getLogger(BackupOperationsImpl.class);
private FileManager fileManager;
private ProjectOperations projectOperations;
public String backup() {
Validate.isTrue(isBackupPossible(), "Project metadata unavailable");
// For Windows, make a date format that can legally form part of a
// filename (ROO-277)
final String pattern =
File.separatorChar == '\\' ? "yyyy-MM-dd_HH.mm.ss" : "yyyy-MM-dd_HH:mm:ss";
final DateFormat df = new SimpleDateFormat(pattern);
final long start = System.nanoTime();
ZipOutputStream zos = null;
try {
final File projectDirectory =
new File(getProjectOperations().getPathResolver().getFocusedIdentifier(Path.ROOT, "."));
final MutableFile file =
getFileManager().createFile(
FileUtils.getCanonicalPath(new File(projectDirectory, getProjectOperations()
.getFocusedProjectName() + "_" + df.format(new Date()) + ".zip")));
zos = new ZipOutputStream(file.getOutputStream());
zip(projectDirectory, projectDirectory, zos);
} catch (final FileNotFoundException e) {
LOGGER.fine("Could not determine project directory");
} catch (final IOException e) {
LOGGER.fine("Could not create backup archive");
} finally {
IOUtils.closeQuietly(zos);
}
final long milliseconds = (System.nanoTime() - start) / 1000000;
return "Backup completed in " + milliseconds + " ms";
}
public boolean isBackupPossible() {
return getProjectOperations().isFocusedProjectAvailable();
}
private void zip(final File directory, final File base, final ZipOutputStream zos)
throws IOException {
final File[] files = directory.listFiles(new FilenameFilter() {
public boolean accept(final File dir, final String name) {
// Don't use this directory if it's "target" under base
if (dir.equals(base) && name.equals("target")) {
return false;
}
// Skip existing backup files
if (dir.equals(base) && name.endsWith(".zip")) {
return false;
}
// Skip files that start with "."
return !name.startsWith(".");
}
});
for (final File file : files) {
if (file.isDirectory()) {
if (file.listFiles().length == 0) {
final ZipEntry dirEntry =
new ZipEntry(file.getPath().substring(base.getPath().length() + 1)
+ File.separatorChar);
zos.putNextEntry(dirEntry);
}
zip(file, base, zos);
} else {
InputStream inputStream = null;
try {
final ZipEntry entry =
new ZipEntry(file.getPath().substring(base.getPath().length() + 1));
zos.putNextEntry(entry);
inputStream = new FileInputStream(file);
IOUtils.write(IOUtils.toByteArray(inputStream), zos);
} finally {
IOUtils.closeQuietly(inputStream);
}
}
}
}
public FileManager getFileManager() {
if (fileManager == null) {
// Get all Services implement FileManager interface
try {
ServiceReference<?>[] references =
context.getAllServiceReferences(FileManager.class.getName(), null);
for (ServiceReference<?> ref : references) {
fileManager = (FileManager) context.getService(ref);
return fileManager;
}
return null;
} catch (InvalidSyntaxException e) {
LOGGER.warning("Cannot load FileManager on BackupOperationsImpl.");
return null;
}
} else {
return fileManager;
}
}
public ProjectOperations getProjectOperations() {
if (projectOperations == null) {
// Get all Services implement ProjectOperations interface
try {
ServiceReference<?>[] references =
context.getAllServiceReferences(ProjectOperations.class.getName(), null);
for (ServiceReference<?> ref : references) {
projectOperations = (ProjectOperations) context.getService(ref);
return projectOperations;
}
return null;
} catch (InvalidSyntaxException e) {
LOGGER.warning("Cannot load ProjectOperations on BackupOperationsImpl.");
return null;
}
} else {
return projectOperations;
}
}
}