001/* 002 * Copyright (c) 2006-2014 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 */ 013 014package org.nuxeo.ecm.core.io.impl.plugins; 015 016import java.io.File; 017import java.io.FileInputStream; 018import java.io.FileOutputStream; 019import java.io.IOException; 020import java.io.InputStream; 021import java.util.zip.ZipEntry; 022import java.util.zip.ZipInputStream; 023 024import org.nuxeo.common.utils.FileUtils; 025import org.nuxeo.ecm.core.io.DocumentReader; 026import org.nuxeo.ecm.core.io.ExportedDocument; 027import org.nuxeo.ecm.core.io.impl.AbstractDocumentReader; 028import org.nuxeo.runtime.api.Framework; 029 030/** 031 * A reader to read zip files. If the zip file is recognized as a nuxeo archive then the {@link NuxeoArchiveReader} will 032 * be used to read the zip otherwise the zip will be deflated to a temporary directory and then 033 * {@link XMLDirectoryReader} will be used to read the zip. 034 * 035 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 036 */ 037public class ZipReader extends AbstractDocumentReader { 038 039 private final ZipInputStream in; 040 041 private DocumentReader delegate; 042 043 public ZipReader(File file) throws IOException { 044 this(new FileInputStream(file)); 045 } 046 047 public ZipReader(InputStream in) throws IOException { 048 this.in = new ZipInputStream(in); 049 initialize(); 050 } 051 052 private void initialize() throws IOException { 053 ZipEntry entry = in.getNextEntry(); 054 if (NuxeoArchiveReader.isMarkerEntry(entry)) { 055 delegate = new NuxeoArchiveReader(in, false); 056 } else { // not a nuxeo archive file 057 File root = null; 058 try { 059 root = File.createTempFile("nuxeo-import-", ".unzip"); 060 Framework.trackFile(root, root); 061 root.delete(); 062 root.mkdirs(); 063 extract(in, entry, root); 064 while ((entry = in.getNextEntry()) != null) { 065 extract(in, entry, root); 066 } 067 } finally { 068 in.close(); 069 } 070 delegate = new XMLDirectoryReader(root); 071 } 072 } 073 074 @Override 075 public ExportedDocument read() throws IOException { 076 return delegate.read(); 077 } 078 079 @Override 080 public void close() { 081 delegate.close(); 082 } 083 084 private static void extract(ZipInputStream in, ZipEntry entry, File root) throws IOException { 085 if (entry.getName().contains("..")) { 086 return; 087 } 088 089 if (!entry.isDirectory()) { // create the directtory 090 File file = new File(root, entry.getName()); 091 if (!file.getParentFile().mkdirs()) { // make sure all parent 092 // directory exists 093 throw new IOException("Failed to create directory: " + file.getParent()); 094 } 095 // write the file content 096 FileOutputStream out = new FileOutputStream(file); 097 try { 098 FileUtils.copy(in, out); 099 } finally { 100 out.close(); 101 } 102 } 103 } 104 105}