Java tutorial
/* * (C) Copyright 2006-2016 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: * Mathieu Guillaume * Julien Carsique * Yannis JULIENNE * */ package org.nuxeo.connect.packages.dependencies; import java.io.BufferedReader; import java.io.IOException; import java.io.PrintStream; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.collections.MapUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.equinox.p2.cudf.metadata.InstallableUnit; import org.eclipse.equinox.p2.cudf.solver.OptimizationFunction.Criteria; import org.nuxeo.connect.data.DownloadablePackage; import org.nuxeo.connect.packages.PackageManager; import org.nuxeo.connect.update.PackageDependency; import org.nuxeo.connect.update.PackageType; import org.nuxeo.connect.update.Version; import org.nuxeo.connect.update.VersionRange; /** * @since 1.4 */ public class CUDFHelper { private static final Log log = LogFactory.getLog(CUDFHelper.class); public static final String newLine = System.getProperty("line.separator"); /** * Convenient default value about SNAPSHOT inclusion in the CUDF universe. Prefer use of parameter in the relevant * methods. * * @since 1.4.13 * @see #initMapping(PackageDependency[], PackageDependency[], PackageDependency[]) * @see #setAllowSNAPSHOT(boolean) */ public static boolean defaultAllowSNAPSHOT = false; protected PackageManager pm; /** * Map of all NuxeoCUDFPackage per Nuxeo version, per package name nuxeo2CUDFMap = { "pkgName", { nuxeoVersion, * NuxeoCUDFPackage }} */ protected Map<String, Map<Version, NuxeoCUDFPackage>> nuxeo2CUDFMap = new HashMap<>(); /** * Map of all NuxeoCUDFPackage per CUDF unique ID (pkgName-pkgCUDFVersion) CUDF2NuxeoMap = { * "pkgName-pkgCUDFVersion", NuxeoCUDFPackage } */ protected Map<String, NuxeoCUDFPackage> CUDF2NuxeoMap = new HashMap<>(); private String targetPlatform; private boolean allowSNAPSHOT = defaultAllowSNAPSHOT; private boolean keep = true; /** * @since 5.9.2 * @param keep Whether to keep the installed packages in the resolution */ public void setKeep(boolean keep) { this.keep = keep; } public CUDFHelper(PackageManager pm) { this.pm = pm; } /** * Map "name, version-classifier" to "name-classifier, version" (with -SNAPSHOT being a specific case) */ public void initMapping() { initMapping(null, null, null); } /** * @param upgrades Packages for which we'll feed the CUDF universe with the remote one if they're SNAPSHOT, in order * to allow their upgrade * @param installs * @param removes * @since 1.4.11 */ public void initMapping(PackageDependency[] installs, PackageDependency[] removes, PackageDependency[] upgrades) { nuxeo2CUDFMap.clear(); CUDF2NuxeoMap.clear(); Map<String, PackageDependency> upgradesMap = new HashMap<>(); Set<String> involvedPackages = new HashSet<>(); List<String> installedOrRequiredSNAPSHOTPackages = new ArrayList<>(); if (upgrades != null) { computeInvolvedPackages(upgrades, upgradesMap, involvedPackages, installedOrRequiredSNAPSHOTPackages); } if (installs != null) { computeInvolvedPackages(installs, involvedPackages, installedOrRequiredSNAPSHOTPackages); } if (removes != null) { computeInvolvedPackages(removes, involvedPackages, installedOrRequiredSNAPSHOTPackages); } // Build a map <pkgName,pkg> List<DownloadablePackage> allPackages = getAllPackages(); Map<String, List<DownloadablePackage>> allPackagesMap = new HashMap<>(); for (DownloadablePackage pkg : allPackages) { String key = pkg.getName(); List<DownloadablePackage> list; if (!allPackagesMap.containsKey(key)) { list = new ArrayList<>(); allPackagesMap.put(key, list); } else { list = allPackagesMap.get(key); } list.add(pkg); // in the mean time, add installed packages to the involved packages list if (keep && pkg.getPackageState().isInstalled()) { involvedPackages.add(pkg.getName()); } } for (DownloadablePackage pkg : allPackages) { computeInvolvedReferences(involvedPackages, installedOrRequiredSNAPSHOTPackages, pkg, allPackagesMap); } installedOrRequiredSNAPSHOTPackages.addAll(getInstalledSNAPSHOTPackages()); // for each unique "name-classifier", sort versions so we can attribute them a "CUDF posint" version populate // Nuxeo2CUDFMap and the reverse CUDF2NuxeoMap for (DownloadablePackage pkg : allPackages) { // ignore not involved packages if (!involvedPackages.contains(pkg.getName())) { if (installedOrRequiredSNAPSHOTPackages.contains(pkg.getName())) { log.error("Ignore installedOrRequiredSNAPSHOTPackage " + pkg); } // check provides boolean involved = false; PackageDependency[] provides = pkg.getProvides(); for (PackageDependency provide : provides) { if (involvedPackages.contains(provide.getName())) { involved = true; break; } } if (!involved) { log.debug("Ignore " + pkg + " (not involved by request)"); continue; } } // ignore incompatible packages when a targetPlatform is set if (!pkg.getPackageState().isInstalled() && !TargetPlatformFilterHelper.isCompatibleWithTargetPlatform(pkg, targetPlatform)) { log.debug("Ignore " + pkg + " (incompatible target platform)"); continue; } // Exclude SNAPSHOT by default for non Studio packages if (!allowSNAPSHOT && pkg.getVersion().isSnapshot() && pkg.getType() != PackageType.STUDIO && !installedOrRequiredSNAPSHOTPackages.contains(pkg.getName())) { log.debug("Ignore " + pkg + " (excluded SNAPSHOT)"); continue; } // SNAPSHOT upgrade requires referring the remote package if (pkg.getVersion().isSnapshot() && pkg.isLocal() && upgradesMap.containsKey(pkg.getName())) { PackageDependency upgrade = upgradesMap.get(pkg.getName()); if (upgrade.getVersionRange().matchVersion(pkg.getVersion())) { DownloadablePackage remotePackage = pm.getRemotePackage(pkg.getId()); if (remotePackage != null) { log.debug(String.format("Upgrade with remote %s", remotePackage)); pkg = remotePackage; } } } NuxeoCUDFPackage nuxeoCUDFPackage = new NuxeoCUDFPackage(pkg); // if (!keep && !involvedPackages.contains(pkg.getName())) { // nuxeoCUDFPackage.setInstalled(false); // } Map<Version, NuxeoCUDFPackage> pkgVersions = nuxeo2CUDFMap.get(nuxeoCUDFPackage.getCUDFName()); if (pkgVersions == null) { pkgVersions = new TreeMap<>(); nuxeo2CUDFMap.put(nuxeoCUDFPackage.getCUDFName(), pkgVersions); } pkgVersions.put(nuxeoCUDFPackage.getNuxeoVersion(), nuxeoCUDFPackage); } for (String key : nuxeo2CUDFMap.keySet()) { Map<Version, NuxeoCUDFPackage> pkgVersions = nuxeo2CUDFMap.get(key); int posInt = 1; for (Version version : pkgVersions.keySet()) { NuxeoCUDFPackage pkg = pkgVersions.get(version); pkg.setCUDFVersion(posInt++); CUDF2NuxeoMap.put(pkg.getCUDFName() + "-" + pkg.getCUDFVersion(), pkg); } } if (log.isDebugEnabled()) { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); PrintStream out = new PrintStream(outputStream); MapUtils.verbosePrint(out, "nuxeo2CUDFMap", nuxeo2CUDFMap); MapUtils.verbosePrint(out, "CUDF2NuxeoMap", CUDF2NuxeoMap); log.debug(outputStream.toString()); IOUtils.closeQuietly(out); } } /** * Parse request to compute the list of directly involved packages * * @since 1.4.18 */ protected void computeInvolvedPackages(PackageDependency[] packageDependencies, Set<String> involvedPackages, List<String> installedOrRequiredSNAPSHOTPackages) { computeInvolvedPackages(packageDependencies, null, involvedPackages, installedOrRequiredSNAPSHOTPackages); } /** * Parse request to compute the list of directly involved packages * * @since 1.4.18 */ protected void computeInvolvedPackages(PackageDependency[] packageDependencies, Map<String, PackageDependency> upgradesMap, Set<String> involvedPackages, List<String> installedOrRequiredSNAPSHOTPackages) { for (PackageDependency packageDependency : packageDependencies) { if (upgradesMap != null) { upgradesMap.put(packageDependency.getName(), packageDependency); } involvedPackages.add(packageDependency.getName()); addIfSNAPSHOT(installedOrRequiredSNAPSHOTPackages, packageDependency); } } /** * Browse the given package's "dependencies", "conflicts" and "provides" to populate the list of involved packages * * @param installedOrRequiredSNAPSHOTPackages * @since 1.4.18 */ protected void computeInvolvedReferences(Set<String> involvedPackages, List<String> installedOrRequiredSNAPSHOTPackages, DownloadablePackage pkg, Map<String, List<DownloadablePackage>> allPackagesMap) { if (involvedPackages.contains(pkg.getName())) { computeInvolvedReferences(involvedPackages, installedOrRequiredSNAPSHOTPackages, pkg.getDependencies(), allPackagesMap); computeInvolvedReferences(involvedPackages, installedOrRequiredSNAPSHOTPackages, pkg.getConflicts(), allPackagesMap); for (PackageDependency pkgDep : pkg.getProvides()) { involvedPackages.add(pkgDep.getName()); } } } /** * Browse the given packages' "dependencies", "conflicts" and "provides" to populate the list of involved packages * * @since 1.4.18 */ protected void computeInvolvedReferences(Set<String> involvedPackages, List<String> installedOrRequiredSNAPSHOTPackages, PackageDependency[] pkgDeps, Map<String, List<DownloadablePackage>> allPackagesMap) { for (PackageDependency pkgDep : pkgDeps) { if (involvedPackages.add(pkgDep.getName())) { addIfSNAPSHOT(installedOrRequiredSNAPSHOTPackages, pkgDep); List<DownloadablePackage> downloadablePkgDeps = allPackagesMap.get(pkgDep.getName()); if (downloadablePkgDeps == null) { log.warn("Unknown dependency: " + pkgDep); continue; } for (DownloadablePackage downloadablePkgDep : downloadablePkgDeps) { computeInvolvedReferences(involvedPackages, installedOrRequiredSNAPSHOTPackages, downloadablePkgDep, allPackagesMap); } } } } protected void addIfSNAPSHOT(List<String> installedOrRequiredSNAPSHOTPackages, PackageDependency pd) { Version minVersion = pd.getVersionRange().getMinVersion(); Version maxVersion = pd.getVersionRange().getMaxVersion(); if (minVersion != null && minVersion.isSnapshot() || maxVersion != null && maxVersion.isSnapshot()) { installedOrRequiredSNAPSHOTPackages.add(pd.getName()); } } protected List<String> getInstalledSNAPSHOTPackages() { List<String> installedSNAPSHOTPackages = new ArrayList<>(); for (DownloadablePackage pkg : pm.listInstalledPackages()) { if (pkg.getVersion().isSnapshot()) { installedSNAPSHOTPackages.add(pkg.getName()); } } return installedSNAPSHOTPackages; } protected List<DownloadablePackage> getAllPackages() { return pm.listAllPackages(); } /** * @param cudfKey in the form "pkgName-pkgCUDFVersion" * @return NuxeoCUDFPackage corresponding to the given cudfKey */ public NuxeoCUDFPackage getCUDFPackage(String cudfKey) { return CUDF2NuxeoMap.get(cudfKey); } /** * @param cudfName a package name * @return all NuxeoCUDFPackage versions corresponding to the given package */ public Map<Version, NuxeoCUDFPackage> getCUDFPackages(String cudfName) { return nuxeo2CUDFMap.get(cudfName); } /** * @param pkgName a package name * @return the NuxeoCUDFPackage corresponding to the given package name which is installed. Null if not found. */ public NuxeoCUDFPackage getInstalledCUDFPackage(String pkgName) { Map<Version, NuxeoCUDFPackage> packages = getCUDFPackages(pkgName); if (packages != null) { for (NuxeoCUDFPackage pkg : packages.values()) { if (pkg.isInstalled()) { return pkg; } } } return null; } /** * @return a CUDF universe as a String * @throws DependencyException */ public String getCUDFFile() throws DependencyException { StringBuilder sb = new StringBuilder(); for (String cudfKey : CUDF2NuxeoMap.keySet()) { sb.append(formatCUDF(CUDF2NuxeoMap.get(cudfKey))); sb.append(newLine); } return sb.toString(); } /** * @return A string representation of a {@link NuxeoCUDFPackage} * @since 1.4.20 */ public String formatCUDF(NuxeoCUDFPackage cudfPackage) throws DependencyException { StringBuilder sb2 = new StringBuilder(); sb2.append(cudfPackage.getCUDFStanza()); sb2.append(CUDFPackage.TAG_DEPENDS + formatCUDFDeps(cudfPackage.getDependencies(), false, true) + newLine); // Add conflicts to other versions of the same package String conflictsFormatted = formatCUDFDeps(cudfPackage.getConflicts(), false, false); conflictsFormatted += (conflictsFormatted.trim().length() > 0 ? ", " : "") + cudfPackage.getCUDFName() + " != " + cudfPackage.getCUDFVersion(); sb2.append(CUDFPackage.TAG_CONFLICTS + conflictsFormatted + newLine); sb2.append(CUDFPackage.TAG_PROVIDES + formatCUDFDeps(cudfPackage.getProvides(), false, false) + newLine); return sb2.toString(); } protected String formatCUDFDeps(PackageDependency[] dependencies, boolean failOnError, boolean warnOnError) throws DependencyException { if (dependencies == null) { return ""; } StringBuilder sb = new StringBuilder(); for (PackageDependency packageDependency : dependencies) { String cudfName = NuxeoCUDFPackage.getCUDFName(packageDependency); Map<Version, NuxeoCUDFPackage> versionsMap = nuxeo2CUDFMap.get(cudfName); if (versionsMap == null) { String errMsg = "Missing mapping for " + packageDependency + " with target platform " + targetPlatform; if (failOnError) { throw new DependencyException(errMsg); } else if (warnOnError) { log.warn(errMsg); } else { log.debug(errMsg); } continue; } VersionRange versionRange = packageDependency.getVersionRange(); int cudfMinVersion, cudfMaxVersion; if (versionRange.getMinVersion() == null) { cudfMinVersion = -1; } else { CUDFPackage cudfPackage = versionsMap.get(versionRange.getMinVersion()); cudfMinVersion = (cudfPackage == null) ? -1 : cudfPackage.getCUDFVersion(); } if (versionRange.getMaxVersion() == null) { cudfMaxVersion = -1; } else { CUDFPackage cudfPackage = versionsMap.get(versionRange.getMaxVersion()); cudfMaxVersion = (cudfPackage == null) ? -1 : cudfPackage.getCUDFVersion(); } if (cudfMinVersion == cudfMaxVersion) { if (cudfMinVersion == -1) { sb.append(cudfName + ", "); } else { sb.append(cudfName + " = " + cudfMinVersion + ", "); } continue; } if (cudfMinVersion != -1) { sb.append(cudfName + " >= " + cudfMinVersion + ", "); } if (cudfMaxVersion != -1) { sb.append(cudfName + " <= " + cudfMaxVersion + ", "); } } if (sb.length() > 0) { // remove ending comma return sb.toString().substring(0, sb.length() - 2); } else { return ""; } } /** * Parse a CUDF universe string * * @param reader * @return The CUDF universe as a map of {@link NuxeoCUDFPackageDescription} per CUDF unique ID * (pkgName-pkgCUDFVersion). The map uses the natural ordering of its keys. * @throws IOException * @throws DependencyException * @since 1.4.20 * @see #getCUDFFile() * @see #formatCUDF(NuxeoCUDFPackage) */ public Map<String, NuxeoCUDFPackageDescription> parseCUDFFile(BufferedReader reader) throws IOException, DependencyException { Map<String, NuxeoCUDFPackageDescription> map = new TreeMap<>(); NuxeoCUDFPackageDescription nuxeoCUDFPkgDesc = null; Pattern linePattern = Pattern.compile(CUDFPackage.LINE_PATTERN); while (reader.ready()) { String line = reader.readLine(); if (line == null) { break; } line = line.trim(); log.debug("Parsing line >> " + line); if (line.trim().isEmpty()) { if (nuxeoCUDFPkgDesc == null) { throw new DependencyException("Invalid CUDF file starting with an empty line"); } map.put(nuxeoCUDFPkgDesc.getCUDFName() + "-" + nuxeoCUDFPkgDesc.getCUDFVersion(), nuxeoCUDFPkgDesc); nuxeoCUDFPkgDesc = null; } else { Matcher m = linePattern.matcher(line); if (!m.matches()) { throw new DependencyException("Invalid CUDF line: " + line); } String tag = m.group(1); if (tag.endsWith(":")) { tag += " "; } String value = m.group(2); if (nuxeoCUDFPkgDesc == null) { if (!CUDFPackage.TAG_PACKAGE.equals(tag)) { throw new DependencyException( "Invalid CUDF file not starting with " + CUDFPackage.TAG_PACKAGE); } nuxeoCUDFPkgDesc = new NuxeoCUDFPackageDescription(); nuxeoCUDFPkgDesc.setCUDFName(value); continue; } switch (tag) { case CUDFPackage.TAG_VERSION: nuxeoCUDFPkgDesc.setCUDFVersion(Integer.parseInt(value)); break; case CUDFPackage.TAG_INSTALLED: nuxeoCUDFPkgDesc.setInstalled(Boolean.parseBoolean(value)); break; case CUDFPackage.TAG_DEPENDS: nuxeoCUDFPkgDesc.setDependencies(parseCUDFDeps(value)); break; case CUDFPackage.TAG_CONFLICTS: nuxeoCUDFPkgDesc.setConflicts(parseCUDFDeps(value)); break; case CUDFPackage.TAG_PROVIDES: nuxeoCUDFPkgDesc.setProvides(parseCUDFDeps(value)); break; case CUDFPackage.TAG_REQUEST: case CUDFPackage.TAG_INSTALL: case CUDFPackage.TAG_REMOVE: case CUDFPackage.TAG_UPGRADE: log.debug("Ignore request stanza " + line); break; case CUDFPackage.TAG_PACKAGE: default: throw new DependencyException("Invalid CUDF line: " + line); } } } if (nuxeoCUDFPkgDesc != null) { // CUDF file without newline at end of file map.put(nuxeoCUDFPkgDesc.getCUDFName() + "-" + nuxeoCUDFPkgDesc.getCUDFVersion(), nuxeoCUDFPkgDesc); } return map; } /** * @param value CUDF dependencies * @return An array of {@link PackageDependency} * @throws DependencyException In case of parsing issue * @since 1.4.20 * @see CUDFPackage#TAG_DEPENDS * @see CUDFPackage#TAG_CONFLICTS * @see CUDFPackage#TAG_PROVIDES * @see #formatCUDFDeps(PackageDependency[], boolean, boolean) */ protected List<PackageDependency> parseCUDFDeps(String value) throws DependencyException { // Map<Version, NuxeoCUDFPackage> versionsMap = nuxeo2CUDFMap.get(cudfName); // CUDF2NuxeoMap. Map<String, PackageDependency> deps = new HashMap<>(); if (value.trim().length() == 0) { return new ArrayList<>(deps.values()); } for (String pkgDep : value.split(",")) { String[] split = pkgDep.trim().split("\\s"); if (split.length == 1) { deps.put(pkgDep.trim(), new PackageDependency(pkgDep.trim())); continue; } if (split.length != 3) { throw new DependencyException("Invalid dependency value: " + value); } String name = split[0].trim(); String rel = split[1].trim(); Version version = new Version(split[2].trim()); PackageDependency previous = deps.get(name); switch (rel) { case "=": if (previous != null) { throw new DependencyException("Conflicting dependency value: " + value + " with " + previous); } deps.put(name, new PackageDependency(name, version, version)); break; case "<": // Not managed, let's consider it's "<=" case "<=": if (previous == null) { deps.put(name, new PackageDependency(name, Version.ZERO, version)); } else { VersionRange versionRange = previous.getVersionRange(); if (versionRange.getMaxVersion() != null) { throw new DependencyException( "Conflicting dependency value: " + value + " with " + previous); } versionRange.setMaxVersion(version); } break; case ">": // Not managed, let's consider it's ">=" case ">=": if (previous == null) { deps.put(name, new PackageDependency(name, version)); } else { VersionRange versionRange = previous.getVersionRange(); if (versionRange.getMinVersion() != null) { throw new DependencyException( "Conflicting dependency value: " + value + " with " + previous); } versionRange.setMinVersion(version); } break; case "!=": // Not managed, ignore break; default: throw new DependencyException("Invalid dependency value: " + value); } } return new ArrayList<>(deps.values()); } /** * @param pkgInstall * @param pkgRemove * @param pkgUpgrade * @return a CUDF string with packages universe and request stanza * @throws DependencyException */ public String getCUDFFile(PackageDependency[] pkgInstall, PackageDependency[] pkgRemove, PackageDependency[] pkgUpgrade) throws DependencyException { initMapping(pkgInstall, pkgRemove, pkgUpgrade); StringBuilder sb = new StringBuilder(getCUDFFile()); sb.append(CUDFPackage.TAG_REQUEST + newLine); sb.append(CUDFPackage.TAG_INSTALL + formatCUDFDeps(pkgInstall, true, true) + newLine); sb.append(CUDFPackage.TAG_REMOVE + formatCUDFDeps(pkgRemove, true, true) + newLine); sb.append(CUDFPackage.TAG_UPGRADE + formatCUDFDeps(pkgUpgrade, true, true) + newLine); return sb.toString(); } /** * @param solution CUDF solution * @param details * @param isSubResolution if true, do not check for optional dependencies on installed packages * @return a DependencyResolution built from the given CUDF solution * @throws DependencyException */ public DependencyResolution buildResolution(Collection<InstallableUnit> solution, Map<Criteria, List<String>> details, boolean isSubResolution) throws DependencyException { if (solution == null) { throw new DependencyException("No solution found."); } log.debug("\nP2CUDF resolution details: "); for (Criteria criteria : Criteria.values()) { if (!details.get(criteria).isEmpty()) { log.debug(criteria.label + ": " + details.get(criteria)); } } DependencyResolution res = new DependencyResolution(); completeResolution(res, details, solution); if (res.isFailed()) { throw new DependencyException(res.failedMessage); } res.markAsSuccess(); if (!isSubResolution) { pm.checkOptionalDependenciesOnInstalledPackages(res); } pm.order(res); return res; } /** * TODO NXP-9268 should use results from {@link Criteria#NOTUPTODATE} and {@link Criteria#RECOMMENDED} * * @param res * @param details * @param solution */ protected void completeResolution(DependencyResolution res, Map<Criteria, List<String>> details, Collection<InstallableUnit> solution) { // Complete with removals for (String pkgName : details.get(Criteria.REMOVED)) { NuxeoCUDFPackage pkg = getInstalledCUDFPackage(pkgName); if (pkg != null) { res.markPackageForRemoval(pkg.getNuxeoName(), pkg.getNuxeoVersion(), true); } } List<InstallableUnit> sortedSolution = new ArrayList<>(solution); Collections.sort(sortedSolution); log.debug("Solution: " + sortedSolution); if (log.isTraceEnabled()) { log.trace("P2CUDF printed solution"); for (InstallableUnit iu : sortedSolution) { log.trace(" package: " + iu.getId()); log.trace(" version: " + iu.getVersion().getMajor()); log.trace(" installed: " + iu.isInstalled()); } } for (InstallableUnit iu : sortedSolution) { NuxeoCUDFPackage pkg = getCUDFPackage(iu.getId() + "-" + iu.getVersion()); if (pkg == null) { log.warn("Couldn't find " + pkg); continue; } if (details.get(Criteria.NEW).contains(iu.getId()) || details.get(Criteria.VERSION_CHANGED).contains(iu.getId())) { if (!res.addPackage(pkg.getNuxeoName(), pkg.getNuxeoVersion(), true)) { log.error("Failed to add " + pkg); } } else if (!details.get(Criteria.REMOVED).contains(iu.getId())) { if (!res.addUnchangedPackage(pkg.getNuxeoName(), pkg.getNuxeoVersion())) { log.error("Failed to add " + pkg); } } else { log.debug("Ignored: " + pkg); } } } public void setTargetPlatform(String targetPlatform) { this.targetPlatform = targetPlatform; } /** * @since 1.4.13 */ public void setAllowSNAPSHOT(boolean allowSNAPSHOT) { this.allowSNAPSHOT = allowSNAPSHOT; } }