Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2014 Spotify AB.
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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
*
* http://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 com.spotify.docker.client;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.PosixFileAttributeView;
import java.nio.file.attribute.PosixFileAttributes;
import java.nio.file.attribute.PosixFilePermission;
import java.util.EnumSet;
import java.util.Set;
import static org.apache.commons.compress.archivers.tar.TarArchiveOutputStream.BIGNUMBER_POSIX;
import static org.apache.commons.compress.archivers.tar.TarArchiveOutputStream.LONGFILE_POSIX;
/**
* This helper class is used during the docker build command to create a gzip tarball of a directory
* containing a Dockerfile.
*/
class CompressedDirectory {
private static final Logger log = LoggerFactory.getLogger(CompressedDirectory.class);
/**
* Default mode to be applied to tar file entries if detailed Posix-compliant mode cannot be
* obtained.
*/
private static final int DEFAULT_FILE_MODE = TarArchiveEntry.DEFAULT_FILE_MODE;
/**
* Identifier used to indicate the OS supports a Posix compliant view of the file system.
*
* @see PosixFileAttributeView#name()
*/
private static final String POSIX_FILE_VIEW = "posix";
/**
* This method creates a gzip tarball of the specified directory. File permissions will be
* retained. The file will be created in a temporary directory using the
* {@link File#createTempFile(String, String)} method. If the method returns successfully, it is
* the caller's responsibility to delete the file.
*
* @param directory the directory to compress
* @return a File object representing the compressed directory
* @throws IOException
*/
public static File create(final String directory) throws IOException {
return create(Paths.get(directory));
}
/**
* This method creates a gzip tarball of the specified directory. File permissions will be
* retained. The file will be created in a temporary directory using the
* {@link File#createTempFile(String, String)} method. If the method returns successfully, it is
* the caller's responsibility to delete the file.
*
* @param directory the directory to compress
* @return a File object representing the compressed directory
* @throws IOException
*/
public static File create(final Path directory) throws IOException {
final File file = File.createTempFile("docker-client-", ".tar.gz");
try (FileOutputStream fileOut = new FileOutputStream(file);
GzipCompressorOutputStream gzipOut = new GzipCompressorOutputStream(fileOut);
TarArchiveOutputStream tarOut = new TarArchiveOutputStream(gzipOut)) {
tarOut.setLongFileMode(LONGFILE_POSIX);
tarOut.setBigNumberMode(BIGNUMBER_POSIX);
Files.walkFileTree(directory,
EnumSet.of(FileVisitOption.FOLLOW_LINKS),
Integer.MAX_VALUE,
new Visitor(directory, tarOut));
} catch (Throwable t) {
// If an error occurs, delete temporary file before rethrowing exception.
delete(file);
throw t;
}
return file;
}
/**
* Convenience method for deleting files. This method safely handles null values, and will never
* throw an exception.
*
* @param file the file to delete.
* @return true if file was deleted successfully, otherwise false.
*/
public static boolean delete(File file) {
if (file == null) {
return false;
}
boolean deleted = false;
try {
deleted = file.delete();
} catch (Exception ignored) {
}
if (!deleted) {
log.warn("Failed to delete temporary file {}", file.getPath());
}
return deleted;
}
private static class Visitor extends SimpleFileVisitor {
private final Path root;
private final TarArchiveOutputStream tarStream;
private Visitor(final Path root, final TarArchiveOutputStream tarStream) {
this.root = root;
this.tarStream = tarStream;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
final TarArchiveEntry entry = new TarArchiveEntry(file.toFile());
final Path relativePath = root.relativize(file);
entry.setName(relativePath.toString());
entry.setMode(getFileMode(file));
entry.setSize(attrs.size());
tarStream.putArchiveEntry(entry);
Files.copy(file, tarStream);
tarStream.closeArchiveEntry();
return FileVisitResult.CONTINUE;
}
private static int getFileMode(Path file) throws IOException {
if (isPosixComplantFS()) {
return getPosixFileMode(file);
} else {
return DEFAULT_FILE_MODE;
}
}
private static boolean isPosixComplantFS() {
return FileSystems.getDefault().supportedFileAttributeViews().contains(POSIX_FILE_VIEW);
}
private static int getPosixFileMode(Path file) throws IOException {
final PosixFileAttributes attr = Files.readAttributes(file, PosixFileAttributes.class);
final Set perm = attr.permissions();
// retain permissions, note these values are octal
int mode = 0100000;
mode += 0100 * getModeFromPermissions(
perm.contains(PosixFilePermission.OWNER_READ),
perm.contains(PosixFilePermission.OWNER_WRITE),
perm.contains(PosixFilePermission.OWNER_EXECUTE));
mode += 010 * getModeFromPermissions(
perm.contains(PosixFilePermission.GROUP_READ),
perm.contains(PosixFilePermission.GROUP_WRITE),
perm.contains(PosixFilePermission.GROUP_EXECUTE));
mode += getModeFromPermissions(
perm.contains(PosixFilePermission.OTHERS_READ),
perm.contains(PosixFilePermission.OTHERS_WRITE),
perm.contains(PosixFilePermission.OTHERS_EXECUTE));
return mode;
}
private static int getModeFromPermissions(boolean read, boolean write, boolean execute) {
int result = 0;
if (read) {
result += 4;
}
if (write) {
result += 2;
}
if (execute) {
result += 1;
}
return result;
}
}
}