blob: 5175aa81804904b8013fee692fb8fd99e4fc7ede [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.sling.distribution.packaging.impl;
import static java.util.UUID.randomUUID;
import javax.annotation.Nonnull;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.DigestOutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import org.apache.commons.io.IOUtils;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.distribution.DistributionRequest;
import org.apache.sling.distribution.common.DistributionException;
import org.apache.sling.distribution.packaging.DistributionPackage;
import org.apache.sling.distribution.packaging.DistributionPackageBuilder;
import org.apache.sling.distribution.serialization.DistributionContentSerializer;
import org.apache.sling.distribution.serialization.DistributionExportFilter;
import org.apache.sling.distribution.serialization.DistributionExportOptions;
import org.apache.sling.distribution.serialization.impl.vlt.VltUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.apache.sling.distribution.util.impl.DigestUtils.openDigestOutputStream;
import static org.apache.sling.distribution.util.impl.DigestUtils.readDigestMessage;
/**
* A {@link DistributionPackageBuilder} based on files.
*/
public class FileDistributionPackageBuilder extends AbstractDistributionPackageBuilder {
private final Logger log = LoggerFactory.getLogger(getClass());
private final File tempDirectory;
private final String digestAlgorithm;
private final DistributionContentSerializer distributionContentSerializer;
private final NavigableMap<String, List<String>> nodeFilters;
private final NavigableMap<String, List<String>> propertyFilters;
public FileDistributionPackageBuilder(String type,
DistributionContentSerializer distributionContentSerializer,
String tempFilesFolder,
String digestAlgorithm, String[] nodeFilters,
String[] propertyFilters) {
super(type);
this.distributionContentSerializer = distributionContentSerializer;
this.nodeFilters = VltUtils.parseFilters(nodeFilters);
this.propertyFilters = VltUtils.parseFilters(propertyFilters);
this.digestAlgorithm = digestAlgorithm;
File tempDirectory = VltUtils.getTempFolder(tempFilesFolder);
if (tempDirectory == null) {
tempDirectory = new File(System.getProperty("java.io.tmpdir"));
}
this.tempDirectory = tempDirectory;
}
@Override
protected DistributionPackage createPackageForAdd(@Nonnull ResourceResolver resourceResolver, @Nonnull final DistributionRequest request) throws DistributionException {
DistributionPackage distributionPackage;
OutputStream outputStream = null;
String digestMessage = null;
final File file;
try {
file = File.createTempFile("distrpck-create-" + randomUUID(), "." + getType(), tempDirectory);
if (digestAlgorithm != null) {
outputStream = openDigestOutputStream(new FileOutputStream(file), digestAlgorithm);
} else {
outputStream = new FileOutputStream(file);
}
final DistributionExportFilter filter = distributionContentSerializer.isRequestFiltering() ? null : DistributionExportFilter.createFilter(request, nodeFilters, propertyFilters);
DistributionExportOptions distributionExportOptions = new DistributionExportOptions(request, filter);
distributionContentSerializer.exportToStream(resourceResolver, distributionExportOptions, outputStream);
outputStream.flush();
if (digestAlgorithm != null) {
digestMessage = readDigestMessage((DigestOutputStream) outputStream);
}
distributionPackage = new FileDistributionPackage(file, getType(), digestAlgorithm, digestMessage);
} catch (IOException e) {
throw new DistributionException(e);
} finally {
IOUtils.closeQuietly(outputStream);
}
return distributionPackage;
}
@Override
protected DistributionPackage readPackageInternal(@Nonnull ResourceResolver resourceResolver, @Nonnull InputStream stream)
throws DistributionException {
DistributionPackage distributionPackage;
final File file;
DigestOutputStream outputStream = null;
try {
String name;
// stable id
Map<String, Object> info = new HashMap<String, Object>();
DistributionPackageUtils.readInfo(stream, info);
Object remoteId = info.get(DistributionPackageUtils.PROPERTY_REMOTE_PACKAGE_ID);
if (remoteId != null) {
name = remoteId.toString();
log.debug("preserving remote id {}", name);
} else {
name = "distrpck-read-" + System.nanoTime();
log.debug("generating a new id {}", name);
}
file = File.createTempFile(name, "." + getType(), tempDirectory);
outputStream = openDigestOutputStream(new FileOutputStream(file), digestAlgorithm);
IOUtils.copy(stream, outputStream);
outputStream.flush();
String digestMessage = readDigestMessage(outputStream);
distributionPackage = new FileDistributionPackage(file, getType(), digestAlgorithm, digestMessage);
} catch (Exception e) {
throw new DistributionException(e);
} finally {
IOUtils.closeQuietly(outputStream);
}
return distributionPackage;
}
@Override
protected boolean installPackageInternal(@Nonnull ResourceResolver resourceResolver, @Nonnull InputStream inputStream)
throws DistributionException {
try {
distributionContentSerializer.importFromStream(resourceResolver, inputStream);
return true;
} finally {
IOUtils.closeQuietly(inputStream);
}
}
@Override
protected DistributionPackage getPackageInternal(@Nonnull ResourceResolver resourceResolver, @Nonnull String id) {
File file = new File(tempDirectory, id);
if (!file.exists()) {
log.warn("file package does not exist", file.getAbsolutePath());
return null;
}
return new FileDistributionPackage(file, getType(), null, null);
}
}