package com.idega.builder.io;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import com.idega.builder.data.IBExportImportData;
import com.idega.core.builder.data.ICPage;
import com.idega.core.file.data.ICFile;
import com.idega.io.ZipOutputStreamIgnoreClose;
import com.idega.io.serialization.FileObjectWriter;
import com.idega.io.serialization.ICFileWriter;
import com.idega.io.serialization.ICPageWriter;
import com.idega.io.serialization.ObjectWriter;
import com.idega.io.serialization.Storable;
import com.idega.io.serialization.WriterToFile;
import com.idega.io.serialization.XMLDataWriter;
import com.idega.presentation.IWContext;
import com.idega.util.StringHandler;
import com.idega.util.xml.XMLData;
import com.idega.xml.XMLElement;
/**
* <p>Title: idegaWeb</p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2003</p>
* <p>Company: idega Software</p>
* @author <a href="thomas@idega.is">Thomas Hilbig</a>
* @version 1.0
* Created on Mar 18, 2004
*/
public class IBExportImportDataWriter extends WriterToFile implements ObjectWriter {
private static final String ZIP_EXTENSION = "zip";
private static final String ZIP_ELEMENT_DELIMITER = "_";
public IBExportImportDataWriter(IWContext iwc) {
super(iwc);
}
public IBExportImportDataWriter(Storable storable, IWContext iwc) {
super(storable,iwc);
}
public String createContainer() throws IOException {
String name = ((IBExportImportData) this.storable).getName();
long folderIdentifier = System.currentTimeMillis();
String path = getRealPathToFile(name, ZIP_EXTENSION, folderIdentifier);
File auxiliaryFile = null;
OutputStream destination = null;
OutputStream outputStreamWrapper = null;
try {
auxiliaryFile = new File(path);
destination = new BufferedOutputStream((new FileOutputStream(auxiliaryFile)));
}
catch (FileNotFoundException ex) {
// logError("[XMLData] problem creating file.");
// log(ex);
throw new IOException("xml file could not be stored");
}
try {
outputStreamWrapper = writeData(destination);
}
finally {
close(outputStreamWrapper);
}
return getURLToFile(name, ZIP_EXTENSION, folderIdentifier);
}
public OutputStream writeData(OutputStream destination) throws IOException {
// use this stream because some writers call close and we don't want to close the zip output stream
ZipOutputStreamIgnoreClose zipOutputStream = new ZipOutputStreamIgnoreClose(destination);
IBExportImportData metadata = (IBExportImportData) this.storable;
List data = metadata.getData();
Map alreadyStoredElements = new HashMap(data.size());
// counter for the entries in metadata
int entryNumber = 0;
// counter for the prefix of the stored files
int identifierNumber = 0;
Iterator iterator = data.iterator();
while (iterator.hasNext()) {
Storable element = (Storable) iterator.next();
// do not store the same elements twice into the zip file
if (alreadyStoredElements.containsKey(element)) {
XMLElement fileElement = (XMLElement) alreadyStoredElements.get(element);
metadata.modifyElementSetNameSetOriginalNameLikeElementAt(entryNumber++, fileElement);
}
else {
WriterToFile currentWriter = (WriterToFile) element.write(this, this.iwc);
String originalName = currentWriter.getName();
String mimeType = currentWriter.getMimeType();
boolean markedAsDeleted = currentWriter.isMarkedAsDeleted();
String zipElementName = createZipElementName(originalName, identifierNumber++);
XMLElement fileElement = metadata.modifyElementSetNameSetOriginalName(entryNumber++, zipElementName, originalName, mimeType, markedAsDeleted);
if (! markedAsDeleted) {
ZipEntry zipEntry = new ZipEntry(zipElementName);
alreadyStoredElements.put(element, fileElement);
zipOutputStream.putNextEntry(zipEntry);
try {
currentWriter.writeData(zipOutputStream);
}
finally {
closeEntry(zipOutputStream);
}
}
}
}
// add metadata itself to the zip file
XMLData metadataSummary = metadata.createMetadataSummary();
WriterToFile currentWriter = (WriterToFile) metadataSummary.write(this, this.iwc);
String originalName = currentWriter.getName();
ZipEntry zipEntry = new ZipEntry(originalName);
zipOutputStream.putNextEntry(zipEntry);
try {
currentWriter.writeData(zipOutputStream);
}
finally {
closeEntry(zipOutputStream);
closeStream(zipOutputStream);
}
return destination;
}
public String getName() {
return ((IBExportImportData) this.storable).getName();
}
public String getMimeType() {
return "application/zip";
}
public Object write(File file, IWContext context) {
return new FileObjectWriter(file, context);
}
public Object write(ICFile file, IWContext context) {
return new ICFileWriter(file, context);
}
public Object write(XMLData xmlData, IWContext context) {
return new XMLDataWriter(xmlData, context);
}
public Object write(IBExportImportData metadata, IWContext context) {
return new IBExportImportDataWriter(metadata, context);
}
public Object write(ICPage page, IWContext context) {
return new ICPageWriter(page, context);
}
private String createZipElementName(String originalName, int entryNumber) {
String originalNameWithoutExtension = StringHandler.cutExtension(originalName);
String modifiedName = StringHandler.stripNonRomanCharacters(originalNameWithoutExtension);
modifiedName = StringHandler.replaceNameKeepExtension(originalName, modifiedName);
StringBuffer buffer = new StringBuffer();
buffer.append(entryNumber).append(ZIP_ELEMENT_DELIMITER).append(modifiedName);
return buffer.toString();
}
protected void closeEntry(ZipOutputStream output) {
try {
if (output != null) {
output.closeEntry();
}
}
catch (IOException io) {
// do not hide an existing exception
}
}
protected void closeStream(ZipOutputStreamIgnoreClose output) {
try {
if (output != null) {
output.closeStream();
}
}
catch (IOException io) {
// do not hide an existing exception
}
}
}