001package org.hl7.fhir.utilities;
002
003/*
004  Copyright (c) 2011+, HL7, Inc.
005  All rights reserved.
006  
007  Redistribution and use in source and binary forms, with or without modification, 
008  are permitted provided that the following conditions are met:
009    
010   * Redistributions of source code must retain the above copyright notice, this 
011     list of conditions and the following disclaimer.
012   * Redistributions in binary form must reproduce the above copyright notice, 
013     this list of conditions and the following disclaimer in the documentation 
014     and/or other materials provided with the distribution.
015   * Neither the name of HL7 nor the names of its contributors may be used to 
016     endorse or promote products derived from this software without specific 
017     prior written permission.
018  
019  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
020  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
021  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
022  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
023  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
024  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
025  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
026  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
027  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
028  POSSIBILITY OF SUCH DAMAGE.
029  
030 */
031
032
033
034import java.io.BufferedInputStream;
035import java.io.BufferedOutputStream;
036import java.io.ByteArrayInputStream;
037import java.io.File;
038import java.io.FileInputStream;
039import java.io.FileNotFoundException;
040import java.io.FileOutputStream;
041import java.io.IOException;
042import java.io.InputStream;
043import java.util.HashSet;
044import java.util.Set;
045import java.util.zip.CRC32;
046import java.util.zip.Deflater;
047import java.util.zip.ZipEntry;
048import java.util.zip.ZipInputStream;
049import java.util.zip.ZipOutputStream;
050
051public class ZipGenerator {
052
053  private Set<String> names = new HashSet<String>();
054        FileOutputStream dest;
055        ZipOutputStream out;
056
057        public ZipGenerator(String filename) throws FileNotFoundException  {
058                dest = new FileOutputStream(filename);
059                out = new ZipOutputStream(new BufferedOutputStream(dest));
060    out.setLevel(Deflater.BEST_COMPRESSION);
061        }
062
063        public void close() throws IOException  {
064                out.close();
065        }
066
067        static final int BUFFER = 2048;
068
069        public void addFromZip(String zipFilename) throws IOException {
070                byte[] buf = new byte[1024];
071
072                ZipInputStream zin = new ZipInputStream(
073                                new FileInputStream(zipFilename));
074
075                try {
076                        ZipEntry entry = zin.getNextEntry();
077                        while (entry != null) {
078                                String name = entry.getName();
079
080                                names.add(name);
081                                // Add ZIP entry to output stream.
082                                out.putNextEntry(new ZipEntry(name));
083                                // Transfer bytes from the ZIP file to the output file
084                                int len;
085                                while ((len = zin.read(buf)) > 0) {
086                                        out.write(buf, 0, len);
087                                }
088
089                                entry = zin.getNextEntry();
090                        }
091                } finally {
092                        zin.close();
093                }
094        }
095
096        public void addFolder(String actualDir, String statedDir, boolean omitIfExists) throws IOException  {
097                File fd = new CSFile(actualDir);
098                String files[] = fd.list();
099                for (String f : files) {
100                        if (new CSFile(Utilities.path(actualDir, f)).isDirectory())
101                                addFolder(Utilities.path(actualDir, f), Utilities.pathURL(statedDir, f), omitIfExists);
102                        else
103                                addFileName(Utilities.pathURL(statedDir, f), Utilities.path(actualDir, f), omitIfExists);
104                }
105        }
106
107  public void addFolder(String actualDir, String statedDir, boolean omitIfExists, String noExt) throws IOException  {
108    File fd = new CSFile(actualDir);
109    String files[] = fd.list();
110    for (String f : files) {
111      if (new CSFile(Utilities.path(actualDir, f)).isDirectory())
112        addFolder(Utilities.path(actualDir, f), Utilities.pathURL(statedDir, f), omitIfExists, noExt);
113      else if (noExt == null || !f.endsWith(noExt))
114        addFileName(Utilities.pathURL(statedDir, f), Utilities.path(actualDir, f), omitIfExists);
115    }
116  }
117
118        public void addFiles(String actualDir, String statedDir, String ext, String noExt) throws FileNotFoundException, IOException {
119                byte data[] = new byte[BUFFER];
120                statedDir = statedDir.replace("\\", "/");
121                File f = new CSFile(actualDir);
122
123                String files[] = f.list();
124                if (files == null) {
125      System.out.println("no files found in "+f.getName());
126                } else {
127                  for (int i = 0; i < files.length; i++) {
128                    if ( new CSFile(actualDir + files[i]).isFile() && ((ext == null || files[i].endsWith(ext)) && (noExt == null || !files[i].endsWith(noExt)))) {
129                      FileInputStream fi = new FileInputStream(actualDir + files[i]);
130                      BufferedInputStream origin = new BufferedInputStream(fi, BUFFER);
131                      ZipEntry entry = new ZipEntry(statedDir + files[i]);
132                      names.add(statedDir + files[i]);
133                      out.putNextEntry(entry);
134                      int count;
135                      while ((count = origin.read(data, 0, BUFFER)) != -1) {
136                        out.write(data, 0, count);
137                      }
138                      origin.close();
139                    }
140                  }
141                }
142        }
143
144  public void addFilesFiltered(String actualDir, String statedDir, String ext, String[] noExt) throws FileNotFoundException, IOException {
145    byte data[] = new byte[BUFFER];
146    statedDir = statedDir.replace("\\", "/");
147    File f = new CSFile(actualDir);
148
149    String files[] = f.list();
150    for (int i = 0; i < files.length; i++) {
151      if ( new CSFile(actualDir + files[i]).isFile() && ((ext == null || files[i].endsWith(ext)))) {
152        boolean ok = true;
153        for (String n : noExt) {
154          ok = ok && !files[i].endsWith(n);
155        }
156        if (ok) {
157          FileInputStream fi = new FileInputStream(actualDir + files[i]);
158          BufferedInputStream origin = new BufferedInputStream(fi, BUFFER);
159          ZipEntry entry = new ZipEntry(statedDir + files[i]);
160          names.add(statedDir + files[i]);
161          out.putNextEntry(entry);
162          int count;
163          while ((count = origin.read(data, 0, BUFFER)) != -1) {
164            out.write(data, 0, count);
165          }
166          origin.close();
167        }
168      }
169    }
170  }
171
172        public void addFileSource(String path, String cnt, boolean omitIfExists) throws IOException  {
173                File tmp = Utilities.createTempFile("tmp", ".tmp");
174                TextFile.stringToFile(cnt, tmp.getAbsolutePath());
175                addFileName(path, tmp.getAbsolutePath(), omitIfExists);
176                tmp.delete();
177        }
178
179        public void addFileName(String statedPath, String actualPath, boolean omitIfExists) throws IOException  {
180          if (!omitIfExists || !names.contains(statedPath)) {
181            byte data[] = new byte[BUFFER];
182            FileInputStream fi = new FileInputStream(actualPath);
183            BufferedInputStream origin = new BufferedInputStream(fi, BUFFER);
184            ZipEntry entry = new ZipEntry(statedPath);
185            names.add(statedPath);
186            out.putNextEntry(entry);
187            int count;
188            while ((count = origin.read(data, 0, BUFFER)) != -1) {
189              out.write(data, 0, count);
190            }
191            origin.close();
192          }
193        }
194
195  public void addBytes(String statedPath, byte[] content, boolean omitIfExists) throws IOException  {
196    if (!omitIfExists || !names.contains(statedPath)) {
197      byte data[] = new byte[BUFFER];
198      InputStream fi = new ByteArrayInputStream(content);
199      BufferedInputStream origin = new BufferedInputStream(fi, BUFFER);
200      ZipEntry entry = new ZipEntry(statedPath);
201      names.add(statedPath);
202      out.putNextEntry(entry);
203      int count;
204      while ((count = origin.read(data, 0, BUFFER)) != -1) {
205        out.write(data, 0, count);
206      }
207      origin.close();
208    }
209  }
210
211  public void addMimeTypeFile(String statedPath, String actualPath) throws IOException  {
212  //  byte data[] = new byte[BUFFER];
213    CRC32 crc = new CRC32();
214    
215  //  FileInputStream fi = new FileInputStream(actualPath);
216  //  BufferedInputStream origin = new BufferedInputStream(fi, BUFFER);
217    out.setLevel(0);
218    ZipEntry entry = new ZipEntry(statedPath);
219    entry.setExtra(null);
220    names.add(statedPath);
221    String contents = "application/epub+zip";
222    crc.update(contents.getBytes());
223    entry.setCompressedSize(contents.length());
224    entry.setSize(contents.length());
225    entry.setCrc(crc.getValue());
226    entry.setMethod(ZipEntry.STORED);
227    out.putNextEntry(entry);
228 //   int count;
229//    while ((count = origin.read(data, 0, BUFFER)) != -1) {
230//      out.write(data, 0, count);
231//    }
232  //  origin.close();
233    out.write(contents.getBytes(),0,contents.length());
234    out.setLevel(Deflater.BEST_COMPRESSION);
235  }
236
237  public void addStream(String statedPath, InputStream fi, boolean omitIfExists) throws IOException  {
238    if (!omitIfExists || !names.contains(statedPath)) {
239      byte data[] = new byte[BUFFER];
240      BufferedInputStream origin = new BufferedInputStream(fi, BUFFER);
241      ZipEntry entry = new ZipEntry(statedPath);
242      names.add(statedPath);
243      out.putNextEntry(entry);
244      int count;
245      while ((count = origin.read(data, 0, BUFFER)) != -1) {
246        out.write(data, 0, count);
247      }
248      origin.close();
249    }
250  }
251
252}