public InstallTask createTask()

in src/main/java/org/apache/sling/installer/core/impl/tasks/BundleTaskCreator.java [144:304]


    public InstallTask createTask(final TaskResourceGroup resourceList) {
	    // quick check of the resource type.
	    final TaskResource toActivate = resourceList.getActiveResource();
	    if ( toActivate.getType().equals(PersistentResourceList.RESTART_ACTIVE_BUNDLES_TYPE) ) {
	        return new RestartActiveBundlesTask(resourceList, this.taskSupport);
	    }
	    if ( !toActivate.getType().equals(InstallableResource.TYPE_BUNDLE) ) {
	        return null;
	    }

	    // check if symbolic name and version is provided in the attributes
        if ( toActivate.getAttribute(Constants.BUNDLE_SYMBOLICNAME) == null ) {
            final Util.BundleHeaders headers = Util.readBundleHeaders(toActivate, logger);
            if ( headers == null ) {
                String message = MessageFormat.format("Resource of type bundle {0} is not really a bundle - manifest entries are missing.", toActivate);
                logger.info(message);
                return new ChangeStateTask(resourceList, ResourceState.IGNORED, message);
            }
            toActivate.setAttribute(Constants.BUNDLE_SYMBOLICNAME, headers.symbolicName);
            toActivate.setAttribute(Constants.BUNDLE_VERSION, headers.version);
            if ( headers.activationPolicy != null ) {
                toActivate.setAttribute(Constants.BUNDLE_ACTIVATIONPOLICY, headers.activationPolicy);
            }
        }
        final String symbolicName = (String)toActivate.getAttribute(Constants.BUNDLE_SYMBOLICNAME);
        final boolean isInstallerCoreBundle = this.bundleContext.getBundle().getSymbolicName().equals(symbolicName);

        // Uninstall
        final InstallTask result;
		if (toActivate.getState() == ResourceState.UNINSTALL) {
            // find the info with the exact version
            final BundleInfo info = this.getBundleInfo(
                    symbolicName,
                    (String)toActivate.getAttribute(Constants.BUNDLE_VERSION));
		    // Remove corresponding bundle if present and if we installed it
		    if ( info != null ) {
	            // if this is an uninstall, check if we have to install an older version
	            // in this case we should do an update instead of uninstall/install (!)
                Iterator<TaskResource> candidatesIt = ((EntityResourceList)resourceList).getActiveResourceIterator();
                TaskResource second = null;
                while (candidatesIt != null && second == null && candidatesIt.hasNext()) {
                    TaskResource candidate = candidatesIt.next();
                    boolean sameVersion = toActivate.getVersion().equals(candidate.getVersion());
                    if (!sameVersion) {
                        if (bundleBlacklist.isBlacklisted(symbolicName, candidate.getVersion())) {
                            String message = MessageFormat.format("Uninstalling blacklisted bundle {0} found at {1}", symbolicName, candidate.getURL());
                            logger.info(message);
                            // blacklisted candidates should be uninstalled to no longer be taken into account anymore
                            ((RegisteredResourceImpl)candidate).setState(ResourceState.UNINSTALL, message);
                        } else {
                            second = candidate;
                        }
                    }
                }
	            if ( second != null &&
	                ( second.getState() == ResourceState.IGNORED || second.getState() == ResourceState.INSTALLED || second.getState() == ResourceState.INSTALL ) ) {
                    second.setAttribute(FORCE_INSTALL_VERSION, info.version.toString());
                    BundleUtil.clearBundleStart(second);
                    logger.debug("Detected downgrade of bundle {}", symbolicName);
                    result = new ChangeStateTask(resourceList, ResourceState.UNINSTALLED, null);
	            } else {
	                // prevent uninstalling the installer itself!
	                if ( isInstallerCoreBundle ) {
	                    logger.debug("Prevent completely uninstalling installer bundle {}", symbolicName);
	                    result = new ChangeStateTask(resourceList, ResourceState.UNINSTALLED, null);
	                } else {
	                    result = new BundleRemoveTask(resourceList, this.taskSupport);
	                }
	            }
		    } else {
	            logger.debug("Bundle {}:{} is not installed anymore - nothing to remove.", symbolicName,
	                    toActivate.getAttribute(Constants.BUNDLE_VERSION));
	            result = new ChangeStateTask(resourceList, ResourceState.UNINSTALLED, null);
	        }

		// Install
		} else {
		    // check for installer and system update
		    final Integer asyncTaskCounter = (Integer)toActivate.getAttribute(InstallTask.ASYNC_ATTR_NAME);
		    if ( asyncTaskCounter != null ) {
                if ( isInstallerCoreBundle ) {
                    result = new InstallerBundleUpdateTask(resourceList, this.taskSupport);
                } else {
                    // system bundle
                    result = new ChangeStateTask(resourceList, ResourceState.INSTALLED, null,
                                    new String[] {InstallTask.ASYNC_ATTR_NAME}, null);
                }
		    } else {
                final Version newVersion = new Version((String) toActivate.getAttribute(Constants.BUNDLE_VERSION));
                if (bundleBlacklist.isBlacklisted(symbolicName, newVersion)) {
                    String message = MessageFormat.format("Ignoring blacklisted bundle {0} found at {1}", symbolicName, toActivate.getURL());
                    logger.info(message);
                    result = new ChangeStateTask(resourceList, ResourceState.IGNORED, message);
                } else {

                    // if not isMultiVersion for install and update, we want the bundle with the
                    // highest version - otherwise only check for very same version (potential updates of snapshots)
                    String bundleVersion = null;
                    if (this.isMultiVersion) {
                        bundleVersion = newVersion.toString();
                    }

                    final BundleInfo info = this.getBundleInfo(symbolicName, bundleVersion);

                    // check if we should start the bundle as we installed it in the previous run
                    if (info == null) {
                        // bundle is not installed yet: install
                        result = new BundleInstallTask(resourceList, this.taskSupport);
                    } else if (BundleUtil.isBundleStart(toActivate)) {
                        result = new BundleStartTask(resourceList, info.id, this.taskSupport);
                    } else {
                        boolean doUpdate = false;

                        final int compare = info.version.compareTo(newVersion);
                        if (compare < 0) {
                            // installed version is lower -> update
                            doUpdate = true;
                        } else if (compare > 0) {
                            final String forceVersion = (String) toActivate.getAttribute(FORCE_INSTALL_VERSION);
                            if (forceVersion != null && info.version.compareTo(new Version(forceVersion)) == 0) {
                                doUpdate = true;
                            } else {
                                logger.debug("Bundle " + info.symbolicName + " " + newVersion
                                        + " is not installed, bundle with higher version is already installed.");
                            }
                        } else if (compare == 0 && BundleInfo.isSnapshot(newVersion)) {

                            // installed, same version but SNAPSHOT
                            doUpdate = true;
                        }
                        if (doUpdate) {

                            logger.debug("Scheduling update of {}", toActivate);
                            // check if this is the system bundle
                            if (Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(symbolicName)) {
                                result = new SystemBundleUpdateTask(resourceList, this.taskSupport);
                                // check if this is a installer update
                            } else if (isInstallerCoreBundle) {
                                result = new InstallerBundleUpdateTask(resourceList, this.taskSupport);
                            } else {
                                result = new BundleUpdateTask(resourceList, this.taskSupport);
                            }
                        } else if (compare == 0 && (isInstallerCoreBundle
                                || Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(symbolicName))) {
                            // the installer core bundle / system bundle has been updated, just set state
                            result = new ChangeStateTask(resourceList, ResourceState.INSTALLED,
                                    "This is the system bundle, therefore nothing was actually done!");
                        } else {
                            String message = MessageFormat.format(
                                    "Nothing to install for {0}, same or newer version {1} already installed.",
                                    toActivate, newVersion);
                            logger.debug(message);
                            result = new ChangeStateTask(resourceList, ResourceState.IGNORED, message);
                        }
                    }
    			}
		    }
            toActivate.setAttribute(FORCE_INSTALL_VERSION, null);
		}
		return result;
	}