/*
* SyncResource.java
*
* Created on April 12, 2007, 1:39 PM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package org.atomojo.app.admin;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.atomojo.app.App;
import org.atomojo.app.Storage;
import org.atomojo.app.WebComponent;
import org.atomojo.app.client.XMLRepresentationParser;
import org.atomojo.app.db.DB;
import org.infoset.xml.Document;
import org.infoset.xml.Element;
import org.infoset.xml.XMLException;
import org.infoset.xml.util.DocumentDestination;
import org.restlet.data.Disposition;
import org.restlet.data.MediaType;
import org.restlet.data.Reference;
import org.restlet.data.Status;
import org.restlet.representation.FileRepresentation;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.ServerResource;
/**
*
* @author alex
*/
public class BackupResource extends ServerResource implements AdminXML
{
/** Creates a new instance of SyncResource */
public BackupResource() {
setNegotiated(false);
}
public Representation get()
{
final DB db = (DB)getRequest().getAttributes().get(App.DB_ATTR);
final Storage storage = (Storage)getRequest().getAttributes().get(App.STORAGE_ATTR);
final Reference resourceBase = (Reference)getRequest().getAttributes().get(App.RESOURCE_BASE_ATTR);
File tmpDir = (File)getContext().getAttributes().get(WebComponent.ATOMOJO_TMP_DIR);
long tstamp = System.currentTimeMillis();
String baseName = db.getName()+".backup."+tstamp;
/*
File dir = new File(tmpDir,baseName);
if (!dir.mkdirs()) {
getResponse().setStatus(Status.SERVER_ERROR_INTERNAL,"Cannot create output directory.");
return;
}*/
try {
Backup backup = new Backup(db,storage,resourceBase);
final File zipFile = new File(tmpDir,baseName+".zip");
backup.toZip(baseName, zipFile);
/*
backup.toDirectory(dir);
zipDir(dir,zipFile);
deleteDir(dir);
*/
getResponse().setStatus(Status.SUCCESS_OK);
Representation rep = new FileRepresentation(zipFile,MediaType.APPLICATION_ZIP) {
public void release() {
zipFile.delete();
}
};
Disposition disposition = new Disposition();
disposition.setFilename("backup.zip");
rep.setDisposition(disposition);
return rep;
} catch (Exception ex) {
getContext().getLogger().log(Level.SEVERE,"Cannot perform backup to due to exception: "+ex.getMessage(),ex);
getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
return new StringRepresentation("Cannot perform backup to due to exception.");
//deleteDir(dir);
}
}
public void zipDir(File dir,File zipFile)
throws java.io.IOException
{
Logger log = getLogger();
ZipOutputStream zipStream = new ZipOutputStream(new FileOutputStream(zipFile));
zipStream.setMethod(ZipOutputStream.DEFLATED);
int baseLength = dir.getParentFile().getAbsolutePath().length();
final List<File> queue = new ArrayList<File>();
queue.add(dir);
byte [] buffer = new byte[32768];
while (queue.size()>0) {
File target = queue.remove(queue.size()-1);
if (target.isDirectory()) {
target.listFiles(new FileFilter() {
public boolean accept(File f)
{
queue.add(f);
return false;
}
});
} else {
FileInputStream is = new FileInputStream(target);
BufferedInputStream source = new BufferedInputStream(is);
ZipEntry theEntry = new ZipEntry(target.getAbsolutePath().substring(baseLength+1));
log.info("\tAdding: " + theEntry.getName());
zipStream.putNextEntry(theEntry);
int len;
while ((len=source.read(buffer))>=0) {
zipStream.write(buffer, 0, len);
}
zipStream.flush();
zipStream.closeEntry();
source.close();
}
}
zipStream.close();
}
public void deleteDir(File dir)
{
final List<File> queue = new ArrayList<File>();
queue.add(dir);
boolean ok = true;
int mark = -1;
while (ok && queue.size()>0) {
File target = queue.remove(queue.size()-1);
if (target.isDirectory()) {
if (mark==queue.size()) {
ok = target.delete();
mark = -1;
} else {
mark = queue.size();
queue.add(target);
target.listFiles(new FileFilter() {
public boolean accept(File f)
{
queue.add(f);
return false;
}
});
}
} else {
ok = target.delete();
}
}
}
public Representation post(Representation entity)
{
final DB db = (DB)getRequest().getAttributes().get(App.DB_ATTR);
final Storage storage = (Storage)getRequest().getAttributes().get(App.STORAGE_ATTR);
final Reference resourceBase = (Reference)getRequest().getAttributes().get(App.RESOURCE_BASE_ATTR);
if (getRequest().getResourceRef().getRemainingPart().endsWith(".zip")) {
getResponse().setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED);
return null;
}
if (!XMLRepresentationParser.isXML(entity.getMediaType())) {
getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
return new StringRepresentation("Non-XML media type for entity body: "+entity.getMediaType().getName());
}
XMLRepresentationParser parser = new XMLRepresentationParser();
try {
DocumentDestination dest = new DocumentDestination();
parser.parse(entity,AdminApplication.createAdminDocumentDestination(dest,AdminXML.NM_BACKUP));
Document doc = dest.getDocument();
Element top = doc.getDocumentElement();
String location = top.getAttributeValue("location");
if (location==null) {
getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
return new StringRepresentation("The 'location' attribute is missing.");
}
location = location.trim();
if (location.length()==0) {
getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
return new StringRepresentation("The 'location' attribute is empty.");
}
File dir = new File(location);
if (!dir.exists()) {
if (!dir.mkdirs()) {
getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
return new StringRepresentation("The "+dir.getAbsolutePath()+" doesn't exist and can't be created.");
}
}
if (!dir.canWrite()) {
getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
return new StringRepresentation("Cannot write to "+dir.getAbsolutePath());
}
try {
Backup backup = new Backup(db,storage,resourceBase);
backup.toDirectory(dir);
getResponse().setStatus(Status.SUCCESS_CREATED);
return null;
} catch (Exception ex) {
getContext().getLogger().log(Level.SEVERE,"Cannot perform backup to due to exception: "+ex.getMessage(),ex);
getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
return new StringRepresentation("Cannot perform backup to due to exception: "+ex.getMessage());
}
} catch (IOException ex) {
getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
return new StringRepresentation("I/O exception: "+ex.getMessage());
} catch (XMLException ex) {
getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
return new StringRepresentation("XML exception: "+ex.getMessage());
}
}
}