in vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageImpl.java [371:552]
private void extract(Set<PackageId> processed, ImportOptions options, boolean createSnapshot, boolean replaceSnapshot)
throws RepositoryException, PackageException, IOException {
getPackage();
getDefinition();
if (def != null) {
processed.add(def.getId());
}
if (options.getDependencyHandling() != null && options.getDependencyHandling() != DependencyHandling.IGNORE) {
installDependencies(processed, options, createSnapshot, replaceSnapshot);
}
// get a copy of the import options (bug 35164)
ImportOptions opts = options.copy();
// check for disable intermediate saves (GRANITE-1047)
if (this.getDefinition().getBoolean(JcrPackageDefinition.PN_DISABLE_INTERMEDIATE_SAVE) ) {
// MAX_VALUE disables saving completely, therefore we have to use a lower value!
opts.setAutoSaveThreshold(Integer.MAX_VALUE - 1);
}
InstallContextImpl ctx = pack.prepareExtract(node.getSession(), opts, mgr.getSecurityConfig(), mgr.isStrictByDefault(),
mgr.overwritePrimaryTypesOfFoldersByDefault(), mgr.getDefaultIdConflictPolicy());
JcrPackage snap = null;
if (!opts.isDryRun() && createSnapshot) {
ExportOptions eOpts = new ExportOptions();
eOpts.setListener(opts.getListener());
snap = snapshot(eOpts, replaceSnapshot, opts.getAccessControlHandling());
}
List<String> subPackages = new ArrayList<>();
pack.extract(ctx, subPackages);
if (def != null && !opts.isDryRun()) {
def.touchLastUnpacked();
}
// process sub packages
Session s = node.getSession();
List<JcrPackageImpl> subPacks = new LinkedList<>();
// contains a value only if a more recent version of the package with the given id (from the key) is already installed
Map<PackageId, PackageId> newerPackageIdPerSubPackage = new HashMap<>();
for (String path: subPackages) {
if (s.nodeExists(path)) {
JcrPackageImpl p = new JcrPackageImpl(mgr, s.getNode(path));
if (!p.isValid()) {
// check if package was included as pure .zip or .jar
try {
p.tryUnwrap();
} catch (Exception e) {
log.info("Sub package {} not valid: {}", path, e.getMessage());
log.debug("Sub package {} not valid", path, e);
}
}
if (p.isValid()) {
JcrPackageDefinitionImpl def = (JcrPackageDefinitionImpl) p.getDefinition();
PackageId pId = def.getId();
// check if package is at the correct location
String expectedPath = mgr.getInstallationPath(pId) + ".zip";
if (!expectedPath.equals(path)) {
if (s.nodeExists(expectedPath)) {
log.info("(Removed duplicated sub-package in {}. Still present at {}", path, expectedPath);
s.getNode(path).remove();
s.save();
} else {
log.info("Moving sub-package in place: {} -> {}", path, expectedPath);
s.getWorkspace().move(path, expectedPath);
}
path = expectedPath;
// re-acquire the package and definition
p.close();
p = new JcrPackageImpl(mgr, s.getNode(path));
def = (JcrPackageDefinitionImpl) p.getDefinition();
}
// ensure that sub package is marked as not-installed. it might contain wrong data in vlt:definition (JCRVLT-114)
def.clearLastUnpacked(false);
// add dependency to the parent package if required
Dependency[] oldDeps = def.getDependencies();
Dependency[] newDeps = DependencyUtil.addExact(oldDeps, pack.getId());
if (oldDeps != newDeps) {
def.setDependencies(newDeps, false);
}
String pName = pId.getName();
Version pVersion = pId.getVersion();
// get the list of packages available in the same group
JcrPackageManager pkgMgr = new JcrPackageManagerImpl(mgr);
List<JcrPackage> listPackages = pkgMgr.listPackages(pId.getGroup(), true);
// loop in the list of packages returned previously by package manager
for (JcrPackage listedPackage: listPackages) {
JcrPackageDefinition listedPackageDef = listedPackage.getDefinition();
if (listedPackageDef == null) {
continue;
}
PackageId listedPackageId = listedPackageDef.getId();
if (listedPackageId.equals(pId)) {
continue;
}
// check that the listed package is actually from same name (so normally only version would differ)
// if that package is valid, installed, and the version is more recent than the one in our sub package
// then we can stop the loop here
if (pName.equals(listedPackageId.getName()) && listedPackage.isValid() && listedPackage.isInstalled()
&& listedPackageId.getVersion().compareTo(pVersion) > 0) {
newerPackageIdPerSubPackage.put(pId, listedPackageId);
break;
}
}
subPacks.add(p);
}
}
}
// don't extract sub packages if not recursive
if (!opts.isNonRecursive() && !subPacks.isEmpty()) {
try {
DependencyUtil.sortPackages(subPacks);
} catch (CyclicDependencyException e) {
if (opts.isStrict(mgr.isStrictByDefault())) {
throw e;
}
}
List<PackageId> subIds = new LinkedList<PackageId>();
SubPackageHandling sb = pack.getSubPackageHandling();
for (JcrPackageImpl p: subPacks) {
boolean skip = false;
PackageId id = p.getDefinition().getId();
SubPackageHandling.Option option = sb.getOption(id);
String msg = null;
// should the package be skipped due to a newer version already installed?
if (option == SubPackageHandling.Option.INSTALL || option == SubPackageHandling.Option.EXTRACT) {
PackageId newerPackageId = newerPackageIdPerSubPackage.get(id);
if (newerPackageId != null) {
msg = String.format(Locale.ENGLISH, "Skipping installation of subpackage '%s' due to newer installed version: '%s'", id, newerPackageId);
skip = true;
}
}
if (!skip) {
if (option == SubPackageHandling.Option.ADD || option == SubPackageHandling.Option.IGNORE) {
msg = "Skipping installation of subpackage " + id + " due to option " + option;
skip = true;
} else if (option == SubPackageHandling.Option.INSTALL || option == SubPackageHandling.Option.FORCE_INSTALL) {
msg = "Starting installation of subpackage " + id;
} else {
msg = "Starting extraction of subpackage " + id;
}
}
if (options.isDryRun()) {
msg = "Dry run: " + msg;
}
if (options.getListener() != null) {
options.getListener().onMessage(ProgressTrackerListener.Mode.TEXT, msg, "");
} else {
log.debug(msg);
}
if (!skip) {
if (createSnapshot && (option == SubPackageHandling.Option.INSTALL || option == SubPackageHandling.Option.FORCE_INSTALL)) {
p.extract(options, true, true);
subIds.add(id);
} else {
p.extract(options, false, true);
}
}
p.close();
}
// register sub packages in snapshot and on package for uninstall
if (snap != null) {
((JcrPackageDefinitionImpl) snap.getDefinition()).setSubPackages(subIds);
}
if (def != null) {
def.setSubPackages(subIds);
}
s.save();
}
if (createSnapshot) {
mgr.dispatch(PackageEvent.Type.INSTALL, def.getId(), null);
} else {
mgr.dispatch(PackageEvent.Type.EXTRACT, def.getId(), null);
}
}