/*
* (C) Copyright 2006-2014 Nuxeo SA (http://nuxeo.com/) and others.
*
* Licensed 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.
*
* Contributors:
* Bogdan Stefanescu
* Mathieu Guillaume
*/
package org.nuxeo.connect.update.util;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.apache.commons.io.IOUtils;
import org.nuxeo.connect.update.LocalPackage;
import org.nuxeo.connect.update.NuxeoValidationState;
import org.nuxeo.connect.update.PackageDependency;
import org.nuxeo.connect.update.PackageType;
import org.nuxeo.connect.update.PackageVisibility;
import org.nuxeo.connect.update.ProductionState;
import org.nuxeo.connect.update.Version;
import org.nuxeo.connect.update.model.PackageDefinition;
import org.nuxeo.connect.update.model.TaskDefinition;
import org.nuxeo.connect.update.xml.FormDefinition;
import org.nuxeo.connect.update.xml.FormsDefinition;
import org.nuxeo.connect.update.xml.PackageDefinitionImpl;
import org.nuxeo.connect.update.xml.TaskDefinitionImpl;
import org.nuxeo.connect.update.xml.XmlSerializer;
import org.nuxeo.runtime.api.Framework;
/**
* Build an XML representation of a package.
*
* @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
*/
public class PackageBuilder {
protected final PackageDefinition def;
protected final List<FormDefinition> installForms;
protected final List<FormDefinition> uninstallForms;
protected final List<FormDefinition> validationForms;
protected final List<String> platforms;
protected final List<PackageDependency> dependencies;
protected final List<PackageDependency> conflicts;
protected final List<PackageDependency> provides;
protected final LinkedHashMap<String, InputStream> entries;
public PackageBuilder() {
def = new PackageDefinitionImpl();
platforms = new ArrayList<>();
dependencies = new ArrayList<>();
conflicts = new ArrayList<>();
provides = new ArrayList<>();
entries = new LinkedHashMap<>();
installForms = new ArrayList<>();
validationForms = new ArrayList<>();
uninstallForms = new ArrayList<>();
}
public PackageBuilder name(String name) {
def.setName(name);
return this;
}
public PackageBuilder version(Version version) {
def.setVersion(version);
return this;
}
public PackageBuilder version(String version) {
def.setVersion(new Version(version));
return this;
}
public PackageBuilder type(String type) {
def.setType(PackageType.getByValue(type));
return this;
}
public PackageBuilder type(PackageType type) {
def.setType(type);
return this;
}
/**
* @since 5.6
*/
public PackageBuilder visibility(String visibility) {
return visibility(PackageVisibility.valueOf(visibility));
}
/**
* @since 5.6
*/
public PackageBuilder visibility(PackageVisibility visibility) {
try {
def.getClass().getMethod("setVisibility", PackageVisibility.class);
def.setVisibility(visibility);
} catch (NoSuchMethodException e) {
// Ignore visibility with old Connect Client versions
}
return this;
}
public PackageBuilder title(String title) {
def.setTitle(title);
return this;
}
public PackageBuilder description(String description) {
def.setDescription(description);
return this;
}
public PackageBuilder classifier(String classifier) {
def.setClassifier(classifier);
return this;
}
public PackageBuilder vendor(String vendor) {
def.setVendor(vendor);
return this;
}
public PackageBuilder homePage(String homePage) {
def.setHomePage(homePage);
return this;
}
public PackageBuilder installer(TaskDefinition task) {
def.setInstaller(task);
return this;
}
public PackageBuilder installer(String type, boolean restart) {
def.setInstaller(new TaskDefinitionImpl(type, restart));
return this;
}
public PackageBuilder uninstaller(TaskDefinition task) {
def.setUninstaller(task);
return this;
}
public PackageBuilder uninstaller(String type, boolean restart) {
def.setUninstaller(new TaskDefinitionImpl(type, restart));
return this;
}
public PackageBuilder validationState(NuxeoValidationState validationState) {
try {
def.getClass().getMethod("setValidationState", NuxeoValidationState.class);
def.setValidationState(validationState);
} catch (NoSuchMethodException e) {
// Ignore setValidationState with old Connect Client versions
}
return this;
}
public PackageBuilder productionState(ProductionState productionState) {
try {
def.getClass().getMethod("setProductionState", ProductionState.class);
def.setProductionState(productionState);
} catch (NoSuchMethodException e) {
// Ignore setProductionState with old Connect Client versions
}
return this;
}
public PackageBuilder supported(boolean supported) {
try {
def.getClass().getMethod("setSupported", boolean.class);
def.setSupported(supported);
} catch (NoSuchMethodException e) {
// Ignore setSupported with old Connect Client versions
}
return this;
}
public PackageBuilder hotReloadSupport(boolean hotReloadSupport) {
try {
def.getClass().getMethod("setHotReloadSupport", boolean.class);
def.setHotReloadSupport(hotReloadSupport);
} catch (NoSuchMethodException e) {
// Ignore setHotReloadSupport with old Connect Client versions
}
return this;
}
public PackageBuilder requireTermsAndConditionsAcceptance(boolean requireTermsAndConditionsAcceptance) {
try {
def.getClass().getMethod("setRequireTermsAndConditionsAcceptance", boolean.class);
def.setRequireTermsAndConditionsAcceptance(requireTermsAndConditionsAcceptance);
} catch (NoSuchMethodException e) {
// Ignore setRequireTermsAndConditionsAcceptance with old Connect
// Client versions
}
return this;
}
public PackageBuilder validator(String validator) {
def.setValidator(validator);
return this;
}
public PackageBuilder platform(String platform) {
platforms.add(platform);
return this;
}
public PackageBuilder dependency(String expr) {
dependencies.add(new PackageDependency(expr));
return this;
}
public PackageBuilder conflict(String expr) {
conflicts.add(new PackageDependency(expr));
return this;
}
public PackageBuilder provide(String expr) {
provides.add(new PackageDependency(expr));
return this;
}
public PackageBuilder addInstallForm(FormDefinition form) {
installForms.add(form);
return this;
}
public PackageBuilder addUninstallForm(FormDefinition form) {
uninstallForms.add(form);
return this;
}
public PackageBuilder addValidationForm(FormDefinition form) {
validationForms.add(form);
return this;
}
public PackageBuilder addLicense(String content) {
return addLicense(new ByteArrayInputStream(content.getBytes()));
}
public PackageBuilder addLicense(InputStream in) {
return addEntry(LocalPackage.LICENSE, in);
}
public PackageBuilder addInstallScript(String content) {
return addInstallScript(new ByteArrayInputStream(content.getBytes()));
}
public PackageBuilder addInstallScript(InputStream in) {
return addEntry(LocalPackage.INSTALL, in);
}
public PackageBuilder addUninstallScript(String content) {
return addUninstallScript(new ByteArrayInputStream(content.getBytes()));
}
public PackageBuilder addUninstallScript(InputStream in) {
return addEntry(LocalPackage.UNINSTALL, in);
}
public PackageBuilder addTermsAndConditions(String content) {
return addTermsAndConditions(new ByteArrayInputStream(content.getBytes()));
}
public PackageBuilder addTermsAndConditions(InputStream in) {
return addEntry(LocalPackage.TERMSANDCONDITIONS, in);
}
/**
* The entry content will be copied into the zip at build time and the given input stream will be closed. (event if
* an exception occurs) - so you don't need to handle stream closing.
*/
public PackageBuilder addEntry(String path, InputStream in) {
entries.put(path, in);
return this;
}
public String buildManifest() {
if (!platforms.isEmpty()) {
def.setTargetPlatforms(platforms.toArray(new String[platforms.size()]));
}
if (!dependencies.isEmpty()) {
def.setDependencies(dependencies.toArray(new PackageDependency[dependencies.size()]));
}
if (!conflicts.isEmpty()) {
def.setConflicts(conflicts.toArray(new PackageDependency[conflicts.size()]));
}
if (!provides.isEmpty()) {
def.setProvides(provides.toArray(new PackageDependency[provides.size()]));
}
return new XmlSerializer().toXML(def);
}
public File build() throws IOException {
try {
String mf = buildManifest();
File file = Framework.createTempFile(def.getId(), ".zip");
Framework.trackFile(file, file);
ZipOutputStream zout = new ZipOutputStream(new FileOutputStream(file));
try {
ZipEntry entry = new ZipEntry(LocalPackage.MANIFEST);
zout.putNextEntry(entry);
zout.write(mf.getBytes());
zout.closeEntry();
for (Map.Entry<String, InputStream> stream : entries.entrySet()) {
entry = new ZipEntry(stream.getKey());
zout.putNextEntry(entry);
IOUtils.copy(stream.getValue(), zout);
zout.closeEntry();
}
if (!installForms.isEmpty()) {
addForms(installForms, LocalPackage.INSTALL_FORMS, zout);
}
if (!uninstallForms.isEmpty()) {
addForms(uninstallForms, LocalPackage.UNINSTALL_FORMS, zout);
}
if (!validationForms.isEmpty()) {
addForms(validationForms, LocalPackage.VALIDATION_FORMS, zout);
}
} finally {
zout.close();
}
return file;
} finally { // close streams
for (InputStream in : entries.values()) {
IOUtils.closeQuietly(in);
}
}
}
protected void addForms(List<FormDefinition> formDefs, String path, ZipOutputStream zout) throws IOException {
int i = 0;
FormsDefinition forms = new FormsDefinition();
FormDefinition[] ar = new FormDefinition[formDefs.size()];
for (FormDefinition form : formDefs) {
ar[i++] = form;
}
forms.setForms(ar);
String xml = new XmlSerializer().toXML(forms);
ZipEntry entry = new ZipEntry(path);
zout.putNextEntry(entry);
IOUtils.copy(new ByteArrayInputStream(xml.getBytes()), zout);
zout.closeEntry();
}
}