blob: e6aec2b9f7bbdf827fc298ad895b95fde0337611 [file] [log] [blame]
/****************************************************************
* 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 org.apache.james.blob.export.file;
import static org.apache.james.blob.api.BlobStore.StoragePolicy.LOW_COST;
import java.io.File;
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.Objects;
import java.util.Optional;
import javax.inject.Inject;
import org.apache.commons.io.FileUtils;
import org.apache.james.blob.api.BlobId;
import org.apache.james.blob.api.BlobStore;
import org.apache.james.blob.export.api.BlobExportMechanism;
import org.apache.james.blob.export.api.ExportedFileNamesGenerator;
import org.apache.james.blob.export.api.FileExtension;
import org.apache.james.core.MailAddress;
import org.apache.james.core.builder.MimeMessageBuilder;
import org.apache.james.dnsservice.api.DNSService;
import org.apache.james.filesystem.api.FileSystem;
import org.apache.james.server.core.MailImpl;
import org.apache.mailet.MailetContext;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
public class LocalFileBlobExportMechanism implements BlobExportMechanism {
private static final String SUBJECT = "Some content had had just been exported";
static final String CORRESPONDING_FILE_HEADER = "corresponding-file";
public static class Configuration {
public static Optional<Configuration> from(org.apache.commons.configuration2.Configuration propertiesConfiguration) {
String exportDirectory = propertiesConfiguration.getString(DIRECTORY_LOCATION_PROPERTY, null);
return Optional.ofNullable(exportDirectory).map(Configuration::new);
}
private static final String DIRECTORY_LOCATION_PROPERTY = "blob.export.localFile.directory";
private static final String DEFAULT_DIRECTORY_LOCATION = "file://var/blobExporting";
public static final Configuration DEFAULT_CONFIGURATION = new Configuration(DEFAULT_DIRECTORY_LOCATION);
private final String exportDirectory;
@VisibleForTesting
Configuration(String exportDirectory) {
Preconditions.checkNotNull(exportDirectory);
this.exportDirectory = exportDirectory;
}
public String getExportDirectory() {
return exportDirectory;
}
@Override
public final boolean equals(Object o) {
if (o instanceof Configuration) {
Configuration that = (Configuration) o;
return Objects.equals(this.exportDirectory, that.exportDirectory);
}
return false;
}
@Override
public final int hashCode() {
return Objects.hash(exportDirectory);
}
}
private final MailetContext mailetContext;
private final BlobStore blobStore;
private final FileSystem fileSystem;
private final DNSService dnsService;
private final Configuration configuration;
@VisibleForTesting
@Inject
public LocalFileBlobExportMechanism(MailetContext mailetContext, BlobStore blobStore, FileSystem fileSystem, DNSService dnsService, Configuration configuration) {
this.mailetContext = mailetContext;
this.blobStore = blobStore;
this.fileSystem = fileSystem;
this.dnsService = dnsService;
this.configuration = configuration;
}
@Override
public ShareeStage blobId(BlobId blobId) {
return mailAddress -> explanation -> fileCustomPrefix -> fileExtension -> () -> {
String fileUrl = copyBlobToFile(blobId, fileCustomPrefix, fileExtension);
sendMail(mailAddress, fileUrl, explanation);
};
}
private String copyBlobToFile(BlobId blobId,
Optional<String> fileCustomPrefix,
Optional<FileExtension> fileExtension) {
try {
File exportingDirectory = fileSystem.getFile(configuration.exportDirectory);
FileUtils.forceMkdir(exportingDirectory);
String fileName = ExportedFileNamesGenerator.generateFileName(fileCustomPrefix, blobId, fileExtension);
String fileURL = configuration.exportDirectory + "/" + fileName;
File file = fileSystem.getFile(fileURL);
FileUtils.copyToFile(blobStore.read(blobStore.getDefaultBucketName(), blobId, LOW_COST), file);
return file.getAbsolutePath();
} catch (IOException e) {
throw new BlobExportException("Error while copying blob to file", e);
}
}
private void sendMail(MailAddress mailAddress, String fileUrl, String explanation) {
try {
MimeMessageBuilder mimeMessage = MimeMessageBuilder.mimeMessageBuilder()
.addHeader(CORRESPONDING_FILE_HEADER, fileUrl)
.addFrom(mailetContext.getPostmaster().asString())
.addToRecipient(mailAddress.asString())
.setSubject(SUBJECT)
.setText(computeMessage(explanation, fileUrl));
MailImpl mail = MailImpl.builder()
.name(MailImpl.getId())
.sender(mailetContext.getPostmaster())
.addRecipient(mailAddress)
.mimeMessage(mimeMessage)
.build();
mailetContext.sendMail(mail);
} catch (Exception e) {
throw new BlobExportException("Error while sending email", e);
}
}
private String computeMessage(String explanationText, String fileUrl) throws UnknownHostException {
String hostname = dnsService.getLocalHost().getHostName();
return explanationText + "\n\n" +
"The content of this blob can be read directly on James host filesystem (" + hostname + ") in this file: " + fileUrl;
}
}