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