Java tutorial
/* * Copyright 2015-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.integration.zip.transformer; import java.io.File; import java.util.ArrayList; import java.util.Date; import java.util.zip.Deflater; import org.apache.commons.io.FilenameUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.zeroturnaround.zip.ByteSource; import org.zeroturnaround.zip.FileSource; import org.zeroturnaround.zip.ZipEntrySource; import org.springframework.integration.file.FileHeaders; import org.springframework.integration.transformer.Transformer; import org.springframework.integration.zip.ZipHeaders; import org.springframework.messaging.Message; import org.springframework.util.Assert; import org.springframework.util.FileCopyUtils; import org.springframework.util.StringUtils; /** * {@link Transformer} implementation that applies a Zip transformation to the * message payload. Keep in mind that Zip entry timestamps are recorded only to * two 2 second precision: * * See also: http://mindprod.com/jgloss/zip.html * * If you want to generate Zip files larger than {@code 4GB}, you must use Java 7: * * See also: https://blogs.oracle.com/xuemingshen/entry/zip64_support_for_4g_zipfile * * @author Gunnar Hillert * @author Artem Bilan * @since 1.0 * */ public class ZipTransformer extends AbstractZipTransformer { private static final Log logger = LogFactory.getLog(ZipTransformer.class); private static final String ZIP_EXTENSION = ".zip"; private volatile int compressionLevel = Deflater.DEFAULT_COMPRESSION; private volatile boolean useFileAttributes = true; /** * Sets the compression level. Default is {@link Deflater#DEFAULT_COMPRESSION}. * * @param compressionLevel Must be an integer value from 0-9. */ public void setCompressionLevel(int compressionLevel) { Assert.isTrue(compressionLevel >= 0 && compressionLevel <= 9, "Acceptable levels are 0-9"); this.compressionLevel = compressionLevel; } /** * Specifies whether the name of the file shall be used for the * zip entry. * * @param useFileAttributes Defaults to true if not set explicitly */ public void setUseFileAttributes(boolean useFileAttributes) { this.useFileAttributes = useFileAttributes; } /** * The payload may encompass the following types: * * <ul> * <li>{@link File} *...<li>{@link String} *...<li>byte[] *...<li>{@link Iterable} * </ul> * * When providing an {@link Iterable}, nested Iterables are not supported. However, * payloads can be of of any of the other supported types. * */ @Override protected Object doZipTransform(Message<?> message) throws Exception { final Object payload = message.getPayload(); final Object zippedData; final String baseFileName = this.fileNameGenerator.generateFileName(message); final String zipEntryName; final String zipFileName; if (message.getHeaders().containsKey(ZipHeaders.ZIP_ENTRY_FILE_NAME)) { zipEntryName = (String) message.getHeaders().get(ZipHeaders.ZIP_ENTRY_FILE_NAME); } else { zipEntryName = baseFileName; } if (message.getHeaders().containsKey(FileHeaders.FILENAME)) { zipFileName = (String) message.getHeaders().get(FileHeaders.FILENAME); } else { zipFileName = baseFileName + ZIP_EXTENSION; } final Date lastModifiedDate; if (message.getHeaders().containsKey(ZipHeaders.ZIP_ENTRY_LAST_MODIFIED_DATE)) { lastModifiedDate = (Date) message.getHeaders().get(ZipHeaders.ZIP_ENTRY_LAST_MODIFIED_DATE); } else { lastModifiedDate = new Date(); } java.util.List<ZipEntrySource> entries = new ArrayList<ZipEntrySource>(); if (payload instanceof Iterable<?>) { int counter = 1; String baseName = FilenameUtils.getBaseName(zipEntryName); String fileExtension = FilenameUtils.getExtension(zipEntryName); if (StringUtils.hasText(fileExtension)) { fileExtension = FilenameUtils.EXTENSION_SEPARATOR_STR + fileExtension; } for (Object item : (Iterable<?>) payload) { final ZipEntrySource zipEntrySource = createZipEntrySource(item, lastModifiedDate, baseName + "_" + counter + fileExtension, this.useFileAttributes); if (logger.isDebugEnabled()) { logger.debug("ZipEntrySource path: '" + zipEntrySource.getPath() + "'"); } entries.add(zipEntrySource); counter++; } } else { final ZipEntrySource zipEntrySource = createZipEntrySource(payload, lastModifiedDate, zipEntryName, this.useFileAttributes); entries.add(zipEntrySource); } final byte[] zippedBytes = SpringZipUtils.pack(entries, this.compressionLevel); if (ZipResultType.FILE.equals(this.zipResultType)) { final File zippedFile = new File(this.workDirectory, zipFileName); FileCopyUtils.copy(zippedBytes, zippedFile); zippedData = zippedFile; } else if (ZipResultType.BYTE_ARRAY.equals(this.zipResultType)) { zippedData = zippedBytes; } else { throw new IllegalStateException("Unsupported zipResultType " + this.zipResultType); } if (this.deleteFiles) { if (payload instanceof Iterable<?>) { for (Object item : (Iterable<?>) payload) { deleteFile(item); } } else { deleteFile(payload); } } return getMessageBuilderFactory().withPayload(zippedData).copyHeaders(message.getHeaders()) .setHeader(FileHeaders.FILENAME, zipFileName).build(); } private void deleteFile(Object fileToDelete) { if (fileToDelete instanceof File && !((File) fileToDelete).delete() && logger.isWarnEnabled()) { logger.warn("Failed to delete File '" + fileToDelete + "'"); } } private ZipEntrySource createZipEntrySource(Object item, Date lastModifiedDate, String zipEntryName, boolean useFileAttributes) { if (item instanceof File) { final File filePayload = (File) item; final String fileName = useFileAttributes ? filePayload.getName() : zipEntryName; if (((File) item).isDirectory()) { throw new UnsupportedOperationException("Zipping of directories is not supported."); } return new FileSource(fileName, filePayload); } else if (item instanceof byte[] || item instanceof String) { byte[] bytesToCompress = null; if (item instanceof String) { bytesToCompress = ((String) item).getBytes(this.charset); } else { bytesToCompress = (byte[]) item; } return new ByteSource(zipEntryName, bytesToCompress, lastModifiedDate.getTime()); } else { throw new IllegalArgumentException("Unsupported payload type. The only supported payloads are " + "java.io.File, java.lang.String, and byte[]"); } } }