All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.liferay.portal.zip.ZipWriterImpl Maven / Gradle / Ivy

/**
 * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */

package com.liferay.portal.zip;

import com.liferay.exportimport.kernel.lar.ExportImportThreadLocal;
import com.liferay.petra.io.StreamUtil;
import com.liferay.petra.memory.DeleteFileFinalizeAction;
import com.liferay.petra.memory.FinalizeManager;
import com.liferay.petra.string.StringBundler;
import com.liferay.petra.string.StringPool;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.util.FileUtil;
import com.liferay.portal.kernel.util.SystemProperties;
import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
import com.liferay.portal.kernel.zip.ZipWriter;
import com.liferay.portal.util.PropsValues;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;

import java.lang.reflect.Field;

import java.net.URI;

import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;

import java.util.AbstractMap;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * @author Raymond Augé
 */
public class ZipWriterImpl implements ZipWriter {

	public ZipWriterImpl() {
		this(
			new File(
				StringBundler.concat(
					SystemProperties.get(SystemProperties.TMP_DIR),
					StringPool.SLASH, PortalUUIDUtil.generate(), ".zip")));

		FinalizeManager.register(
			_file, new DeleteFileFinalizeAction(_file.getAbsolutePath()),
			FinalizeManager.PHANTOM_REFERENCE_FACTORY);
	}

	public ZipWriterImpl(File file) {
		_file = file.getAbsoluteFile();

		URI fileURI = _file.toURI();

		_uri = URI.create("jar:file:" + fileURI.getRawPath());

		try (FileSystem fileSystem = FileSystems.newFileSystem(
				_uri, Collections.singletonMap("create", "true"))) {
		}
		catch (IOException ioException) {
			throw new UncheckedIOException(ioException);
		}
	}

	@Override
	public void addEntry(String name, byte[] bytes) throws IOException {
		if (bytes == null) {
			return;
		}

		if (ExportImportThreadLocal.isExportInProcess()) {
			if (_exportEntries == null) {
				_exportEntries = new LinkedList<>();
			}

			_exportEntries.add(
				new AbstractMap.SimpleImmutableEntry<>(name, bytes));

			_exportEntriesBytes += bytes.length;

			if (_exportEntriesBytes >=
					PropsValues.ZIP_FILE_WRITER_EXPORT_BUFFER_SIZE) {

				_writeExportEntries();
			}

			return;
		}

		try (FileSystem fileSystem = FileSystems.newFileSystem(
				_uri, Collections.emptyMap())) {

			Path path = fileSystem.getPath(name);

			_createDirectories(fileSystem, path.getParent());

			Files.write(
				path, bytes, StandardOpenOption.CREATE,
				StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE);
		}
	}

	@Override
	public void addEntry(String name, InputStream inputStream)
		throws IOException {

		if (inputStream == null) {
			return;
		}

		if (ExportImportThreadLocal.isExportInProcess()) {
			addEntry(name, StreamUtil.toByteArray(inputStream));

			return;
		}

		try (FileSystem fileSystem = FileSystems.newFileSystem(
				_uri, Collections.emptyMap())) {

			Path path = fileSystem.getPath(name);

			_createDirectories(fileSystem, path.getParent());

			Files.copy(inputStream, path, StandardCopyOption.REPLACE_EXISTING);
		}
	}

	@Override
	public void addEntry(String name, String s) throws IOException {
		if (s == null) {
			return;
		}

		addEntry(name, s.getBytes(StringPool.UTF8));
	}

	@Override
	public void addEntry(String name, StringBuilder sb) throws IOException {
		if (sb == null) {
			return;
		}

		addEntry(name, sb.toString());
	}

	/**
	 * @deprecated As of Athanasius (7.3.x), replaced by {@link #getFile()}
	 */
	@Deprecated
	@Override
	public byte[] finish() throws IOException {
		return FileUtil.getBytes(getFile());
	}

	@Override
	public File getFile() {
		if (_exportEntries != null) {
			_writeExportEntries();
		}

		return _file;
	}

	/**
	 * @deprecated As of Athanasius (7.3.x), replaced by {@link #getFile()}
	 */
	@Deprecated
	@Override
	public String getPath() {
		return _file.getPath();
	}

	/**
	 * @deprecated As of Athanasius (7.3.x), replaced by {@link #getFile()}
	 */
	@Deprecated
	@Override
	public void umount() {
	}

	private void _createDirectories(FileSystem fileSystem, Path parentPath)
		throws IOException {

		if ((parentPath == null) || Files.exists(parentPath)) {
			return;
		}

		Files.createDirectories(parentPath);

		boolean needUTF8 = false;

		String pathString = parentPath.toString();

		for (int i = 0; i < pathString.length(); i++) {
			if (pathString.charAt(i) > 128) {
				needUTF8 = true;

				break;
			}
		}

		if (!needUTF8) {
			return;
		}

		try {
			Class fileSystemClass = fileSystem.getClass();

			Field inodesField = fileSystemClass.getDeclaredField("inodes");

			inodesField.setAccessible(true);

			Map inodes = (Map)inodesField.get(fileSystem);

			for (Object inode : inodes.keySet()) {
				try {
					Class inodeClass = inode.getClass();

					Field flagField = inodeClass.getDeclaredField("flag");

					flagField.setAccessible(true);

					int flag = flagField.getInt(inode);

					if ((flag & 2048) == 0) {
						flagField.setInt(inode, flag | 2048);
					}
				}
				catch (NoSuchFieldException noSuchFieldException) {
					if (_log.isDebugEnabled()) {
						_log.debug(noSuchFieldException);
					}
				}
			}
		}
		catch (ReflectiveOperationException reflectiveOperationException) {
			if (_log.isWarnEnabled()) {
				_log.warn(
					"Unable to force UTF-8 encoding for directory " +
						parentPath,
					reflectiveOperationException);
			}
		}
	}

	private void _writeExportEntries() {
		try (FileSystem fileSystem = FileSystems.newFileSystem(
				_uri, Collections.emptyMap())) {

			Iterator> iterator =
				_exportEntries.iterator();

			while (iterator.hasNext()) {
				Map.Entry entry = iterator.next();

				iterator.remove();

				Path path = fileSystem.getPath(entry.getKey());

				_createDirectories(fileSystem, path.getParent());

				Files.write(
					path, entry.getValue(), StandardOpenOption.CREATE,
					StandardOpenOption.TRUNCATE_EXISTING,
					StandardOpenOption.WRITE);
			}

			_exportEntries = null;
			_exportEntriesBytes = 0;
		}
		catch (IOException ioException) {
			throw new UncheckedIOException(ioException);
		}
	}

	private static final Log _log = LogFactoryUtil.getLog(ZipWriterImpl.class);

	private List> _exportEntries;
	private long _exportEntriesBytes;
	private final File _file;
	private final URI _uri;

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy