package com.github.dockerjava.core.command;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import com.github.dockerjava.api.command.CopyArchiveToContainerCmd;
import com.github.dockerjava.api.exception.DockerClientException;
import com.github.dockerjava.api.exception.NotFoundException;
import com.github.dockerjava.core.util.CompressArchiveUtil;
public class CopyArchiveToContainerCmdImpl extends AbstrDockerCmd<CopyArchiveToContainerCmd, Void> implements
CopyArchiveToContainerCmd {
private String containerId;
private String remotePath = ".";
private InputStream tarInputStream;
private String hostResource;
private boolean noOverwriteDirNonDir = false;
private boolean dirChildrenOnly = false;
public CopyArchiveToContainerCmdImpl(CopyArchiveToContainerCmd.Exec exec, String containerId) {
super(exec);
withContainerId(containerId);
}
@Override
public CopyArchiveToContainerCmd withContainerId(String containerId) {
checkNotNull(containerId, "containerId was not specified");
this.containerId = containerId;
return this;
}
@Override
public CopyArchiveToContainerCmd withHostResource(String hostResource) {
checkNotNull(hostResource, "hostResource was not specified");
this.hostResource = hostResource;
return this;
}
@Override
public CopyArchiveToContainerCmd withNoOverwriteDirNonDir(boolean noOverwriteDirNonDir) {
this.noOverwriteDirNonDir = noOverwriteDirNonDir;
return this;
}
@Override
public CopyArchiveToContainerCmd withRemotePath(String remotePath) {
checkNotNull(remotePath, "remotePath was not specified");
this.remotePath = remotePath;
return this;
}
@Override
public CopyArchiveToContainerCmd withTarInputStream(InputStream tarInputStream) {
checkNotNull(tarInputStream, "tarInputStream was not specified");
this.tarInputStream = tarInputStream;
return this;
}
@Override
public CopyArchiveToContainerCmd withDirChildrenOnly(boolean dirChildrenOnly) {
this.dirChildrenOnly = dirChildrenOnly;
return this;
}
@Override
public InputStream getTarInputStream() {
return tarInputStream;
}
@Override
public String getContainerId() {
return this.containerId;
}
@Override
public String getHostResource() {
return this.hostResource;
}
@Override
public boolean isNoOverwriteDirNonDir() {
return this.noOverwriteDirNonDir;
}
@Override
public String getRemotePath() {
return this.remotePath;
}
@Override
public boolean isDirChildrenOnly() {
return this.dirChildrenOnly;
}
@Override
public String toString() {
return new ToStringBuilder(this).append("cp ").append(hostResource).append(" ").append(containerId).append(":")
.append(remotePath).toString();
}
private InputStream buildUploadStream(String hostResource, boolean dirChildrenOnly) throws IOException {
Path toUpload = Files.createTempFile("docker-java", ".tar.gz");
CompressArchiveUtil.tar(Paths.get(hostResource), toUpload, true, dirChildrenOnly);
return Files.newInputStream(toUpload);
}
/**
* @throws com.github.dockerjava.api.exception.NotFoundException
* No such container
*/
@Override
public Void exec() throws NotFoundException {
if (StringUtils.isNotEmpty(this.hostResource)) {
// User set host resource and not directly a stream
if (this.tarInputStream != null) {
throw new DockerClientException(
"Only one of host resource or tar input stream should be defined to perform the copy, not both");
}
// We compress the given path, call exec so that the stream is consumed and then close it our self
try (InputStream uploadStream = buildUploadStream(this.hostResource, this.dirChildrenOnly)) {
this.tarInputStream = uploadStream;
return super.exec();
} catch (IOException e) {
throw new DockerClientException("Unable to perform tar on host resource " + this.hostResource, e);
}
} else if (this.tarInputStream == null) {
throw new DockerClientException(
"One of host resource or tar input stream must be defined to perform the copy");
}
// User set a stream, so we will just consume it and let the user close it by him self
return super.exec();
}
}