001/* 002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * bstefanescu 011 * 012 * $Id: NuxeoArchiveWriter.java 29029 2008-01-14 18:38:14Z ldoguin $ 013 */ 014 015package org.nuxeo.ecm.core.io.impl.plugins; 016 017import java.io.BufferedOutputStream; 018import java.io.File; 019import java.io.FileOutputStream; 020import java.io.IOException; 021import java.io.InputStream; 022import java.io.OutputStream; 023import java.util.Map; 024import java.util.zip.Deflater; 025import java.util.zip.ZipEntry; 026import java.util.zip.ZipOutputStream; 027 028import org.apache.commons.io.IOUtils; 029import org.dom4j.Document; 030import org.dom4j.io.OutputFormat; 031import org.dom4j.io.XMLWriter; 032import org.nuxeo.ecm.core.api.Blob; 033import org.nuxeo.ecm.core.api.DocumentLocation; 034import org.nuxeo.ecm.core.api.DocumentRef; 035import org.nuxeo.ecm.core.io.DocumentTranslationMap; 036import org.nuxeo.ecm.core.io.ExportConstants; 037import org.nuxeo.ecm.core.io.ExportedDocument; 038import org.nuxeo.ecm.core.io.impl.AbstractDocumentWriter; 039import org.nuxeo.ecm.core.io.impl.DWord; 040import org.nuxeo.ecm.core.io.impl.DocumentTranslationMapImpl; 041 042/** 043 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 044 */ 045public class NuxeoArchiveWriter extends AbstractDocumentWriter { 046 047 protected ZipOutputStream out; 048 049 public NuxeoArchiveWriter(File destination) throws IOException { 050 this(new BufferedOutputStream(new FileOutputStream(destination)), Deflater.DEFAULT_COMPRESSION); 051 } 052 053 public NuxeoArchiveWriter(File destination, int compressionLevel) throws IOException { 054 this(new BufferedOutputStream(new FileOutputStream(destination)), compressionLevel); 055 } 056 057 public NuxeoArchiveWriter(OutputStream out) throws IOException { 058 this(new ZipOutputStream(out), Deflater.DEFAULT_COMPRESSION); 059 } 060 061 public NuxeoArchiveWriter(OutputStream out, int compressionLevel) throws IOException { 062 this(new ZipOutputStream(out), compressionLevel); 063 } 064 065 public NuxeoArchiveWriter(ZipOutputStream out) throws IOException { 066 this(out, Deflater.DEFAULT_COMPRESSION); 067 } 068 069 public NuxeoArchiveWriter(ZipOutputStream out, int compressionLevel) throws IOException { 070 this.out = out; 071 this.out.setLevel(compressionLevel); 072 setComment(""); 073 // write the marker entry 074 writeMarker(); 075 } 076 077 public void setComment(String comment) { 078 if (out != null) { 079 out.setComment(ExportConstants.ZIP_HEADER + "\r\n" + comment); 080 } 081 } 082 083 @Override 084 public DocumentTranslationMap write(ExportedDocument doc) throws IOException { 085 String path = doc.getPath().toString(); 086 writeDocument(path, doc); 087 // keep location unchanged 088 DocumentLocation oldLoc = doc.getSourceLocation(); 089 String oldServerName = oldLoc.getServerName(); 090 DocumentRef oldDocRef = oldLoc.getDocRef(); 091 DocumentTranslationMap map = new DocumentTranslationMapImpl(oldServerName, oldServerName); 092 map.put(oldDocRef, oldDocRef); 093 return map; 094 } 095 096 @Override 097 public void close() { 098 if (out != null) { 099 try { 100 out.close(); 101 } catch (IOException e) { 102 // do nothing 103 } finally { 104 out = null; 105 } 106 } 107 } 108 109 protected void writeDocument(String path, ExportedDocument doc) throws IOException { 110 111 if (path.equals("/") || path.length() == 0) { 112 path = ""; 113 } else { // avoid adding a root entry 114 path += '/'; 115 ZipEntry entry = new ZipEntry(path); 116 // store the number of child as an extra info on the entry 117 entry.setExtra(new DWord(doc.getFilesCount()).getBytes()); 118 out.putNextEntry(entry); 119 out.closeEntry(); 120 // System.out.println(">> add entry: "+entry.getName()); 121 } 122 123 // write metadata 124 ZipEntry entry = new ZipEntry(path + ExportConstants.DOCUMENT_FILE); 125 out.putNextEntry(entry); 126 try { 127 writeXML(doc.getDocument(), out); 128 } finally { 129 out.closeEntry(); 130 // System.out.println(">> add entry: "+entry.getName()); 131 } 132 133 // write external documents 134 for (Map.Entry<String, Document> ext : doc.getDocuments().entrySet()) { 135 String fileName = ext.getKey() + ".xml"; 136 entry = new ZipEntry(path + fileName); 137 out.putNextEntry(entry); 138 try { 139 writeXML(ext.getValue(), out); 140 } finally { 141 out.closeEntry(); 142 } 143 } 144 145 // write blobs 146 Map<String, Blob> blobs = doc.getBlobs(); 147 for (Map.Entry<String, Blob> blobEntry : blobs.entrySet()) { 148 String fileName = blobEntry.getKey(); 149 entry = new ZipEntry(path + fileName); 150 out.putNextEntry(entry); 151 try (InputStream in = blobEntry.getValue().getStream()) { 152 IOUtils.copy(in, out); 153 } 154 // DO NOT CALL out.close(), we want to keep writing to it 155 out.closeEntry(); 156 } 157 } 158 159 protected static void writeXML(Document doc, OutputStream out) throws IOException { 160 OutputFormat format = AbstractDocumentWriter.createPrettyPrint(); 161 XMLWriter writer = new XMLWriter(out, format); 162 writer.write(doc); 163 } 164 165 protected void writeMarker() throws IOException { 166 ZipEntry entry = new ZipEntry(ExportConstants.MARKER_FILE); 167 out.putNextEntry(entry); 168 out.closeEntry(); 169 } 170}