Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*************************************************************************
*
* ADOBE CONFIDENTIAL
* __________________
*
* Copyright 2012 Adobe Systems Incorporated
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Adobe Systems Incorporated and its suppliers,
* if any. The intellectual and technical concepts contained
* herein are proprietary to Adobe Systems Incorporated and its
* suppliers and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe Systems Incorporated.
**************************************************************************/
package com.adobe.cq.upgradesexecutor;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import javax.jcr.Item;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import com.adobe.granite.ui.clientlibs.HtmlLibraryManager;
import com.day.cq.compat.codeupgrade.CodeUpgradeTask;
import com.day.cq.compat.codeupgrade.CodeUpgradeTaskFilter;
import com.day.cq.compat.codeupgrade.MigrationModeCheck;
import org.apache.commons.collections.CollectionUtils;
import org.apache.sling.installer.api.info.Resource;
import org.apache.sling.hc.api.Result;
import org.apache.sling.hc.api.ResultLog;
import org.apache.sling.hc.api.execution.HealthCheckExecutionResult;
import org.apache.sling.hc.api.execution.HealthCheckExecutor;
import org.apache.sling.installer.api.info.ResourceGroup;
import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.launchpad.api.StartupHandler;
import org.apache.sling.launchpad.api.StartupMode;
import org.apache.sling.settings.SlingSettingsService;
import org.apache.sling.startupfilter.StartupInfoProvider;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.util.tracker.ServiceTracker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** Run CodeUpgradeTasks, synchronously in the Activator.start() method */
public class Activator implements BundleActivator {
private final Logger log = LoggerFactory.getLogger(getClass());
/** If this property is true, upgrades execute whatever the StartupMode is.
* Useful for troubleshooting the upgrade code. */
public static final String FORCE_UPGRADES_PATH = "/var/upgrade/status/upgradesExecutor.forceUpgrades";
private ExecutionConditionCodeUpgradeTaskServiceTracker st;
final List tasks = new ArrayList();
private Set cachedActiveResourceURLSet = new HashSet();
private static final int OSGI_INSTALLER_NO_ACTIVITY_TIMEOUT = 60000;
private long cachedNoActivityOsgiInstallerTime = 0;
/** Provides informational status messages in the 503 responses that CQ
* returns during startup.
*/
class InfoProvider implements StartupInfoProvider {
private String progressInfo = "Initializing";
private volatile CodeUpgradeTask task;
public String getProgressInfo() {
if (task != null) {
String info = task.getProgressInfo();
if (info == null) {
info = "No info yet";
}
return "Running " + task + ": " + info;
}
return progressInfo;
}
void say(String info) {
log.info(info);
progressInfo = info;
}
void setTask(CodeUpgradeTask t) {
task = t;
}
}
/** When this bundle starts, execute all available CodeUpgradeTasks
* if StartupMode is UPDATE.
*/
public void start(BundleContext context) throws Exception {
// Nothing to do unless startup mode is UPDATE
final ServiceReference ref = context.getServiceReference(StartupHandler.class.getName());
if (ref == null) {
throw new IllegalStateException(
"StartupHandler not found, cannot decide whether to run upgrade code or not");
}
final StartupHandler sh = (StartupHandler) context.getService(ref);
final StartupMode sm = sh.getMode();
final ServiceReference migCheckRef = context.getServiceReference(MigrationModeCheck.class.getName());
ServiceTracker migCheckTracker = new ServiceTracker(context, migCheckRef, null);
migCheckTracker.open();
MigrationModeCheck checker = null;
try {
checker = (MigrationModeCheck)migCheckTracker.waitForService(2 * 60 * 1000);
} catch (Exception ex) {
// handling via null check
} finally {
migCheckTracker.close();
}
if (checker == null) {
log.error("Could not get MigrationModeCheck service, execution of CodeUpgradeTasks aborted");
return;
}
boolean delayedMigrationActive = checker.isDelayedMigrationActive();
// If we have a repository service and the FORCE_UPGRADES_PATH property is
// true, force upgrade code to run
if (!delayedMigrationActive && sm != StartupMode.UPDATE ) {
boolean force = false;
final ServiceReference repoRef = context.getServiceReference(SlingRepository.class.getName());
if (repoRef != null) {
final SlingRepository repo = (SlingRepository) context.getService(repoRef);
final Session s = repo.loginAdministrative(repo.getDefaultWorkspace());
try {
if (s.itemExists(FORCE_UPGRADES_PATH)) {
final Item it = s.getItem(FORCE_UPGRADES_PATH);
if (!it.isNode()) {
force = s.getProperty(FORCE_UPGRADES_PATH).getBoolean();
log.warn("{}=true will force upgrade code to run every time this bundle is started - "
+ " if this is not desired, remove that property",
FORCE_UPGRADES_PATH);
}
}
} finally {
s.logout();
}
}
if (force) {
log.info("StartupMode is {} but {} is true, executing upgrade tasks", sm, FORCE_UPGRADES_PATH);
} else {
log.info("UPGRADE NOT NEEDED - StartupMode is {}", sm);
return;
}
}
log.info("UPGRADE / Content Migration STARTS - StartupMode is {}", sm);
// StartupInfoProvider progress info is included in the 503
// response that CQ provides during startup
final InfoProvider ip = new InfoProvider();
ServiceRegistration reg = null;
try {
reg = context.registerService(StartupInfoProvider.class.getName(), ip, null);
final ServiceReference slingInfoProviderServiceRef = context.getServiceReference(
org.apache.sling.installer.api.info.InfoProvider.class.getName());
final org.apache.sling.installer.api.info.InfoProvider slingInfoProvider = slingInfoProviderServiceRef != null ?
(org.apache.sling.installer.api.info.InfoProvider) context.getService(slingInfoProviderServiceRef) : null;
st = new ExecutionConditionCodeUpgradeTaskServiceTracker(context);
st.open();
while (true) {
Thread.sleep(1000);
if (st.isCodeUpgradeExecutionConditonSatisfied()) {
finishUpgradeExecution(context, ip);
break;
} else if (timeout(slingInfoProvider)) {
log.error("OSGI installer finished and the upgrade task condition was not satisfied. Executing installed upgrade tasks" +
" but most likely one of the mandatory upgrade tasks was not executed. Please check the log file.");
finishUpgradeExecution(context, ip);
break;
}
}
} finally {
if (reg != null) {
reg.unregister();
}
st.close();
}
}
private boolean timeout(org.apache.sling.installer.api.info.InfoProvider slingInfoProvider) throws InterruptedException {
if (slingInfoProvider != null) {
List currentActiveResources = slingInfoProvider.getInstallationState().getActiveResources();
Set currentActiveResourceURLSet = extractResourceURLSet(currentActiveResources);
// if no change in osgi installer for more then {@code OSGI_INSTALLER_NO_ACTIVITY_TIMEOUT} then timeout is activated
if (CollectionUtils.isEqualCollection(currentActiveResourceURLSet, cachedActiveResourceURLSet)) {
long currentTime = System.currentTimeMillis();
if (cachedNoActivityOsgiInstallerTime == 0) {
cachedNoActivityOsgiInstallerTime = currentTime;
} else {
if (currentTime - cachedNoActivityOsgiInstallerTime > OSGI_INSTALLER_NO_ACTIVITY_TIMEOUT) {
return true;
}
}
} else {
cachedNoActivityOsgiInstallerTime = 0;
}
cachedActiveResourceURLSet = currentActiveResourceURLSet;
return false;
} else {
log.error("Could not obtain OSGI installer state. Waiting 2 minutes for the upgrade tasks to install and then execute them.");
Thread.sleep(120000);
return true;
}
}
private Set extractResourceURLSet(List currentActiveResources) {
Set resources = new HashSet();
for (ResourceGroup resourceGroup : currentActiveResources) {
for (Resource resource : resourceGroup.getResources()) {
resources.add(resource.getURL());
}
}
return resources;
}
private void finishUpgradeExecution(BundleContext context, InfoProvider ip) {
runUpgradeTasks(context, ip);
invalidateCaches(context);
executePostUpgradeHC(context);
updateInstallPropertiesFile(context);
}
private class ExecutionConditionCodeUpgradeTaskServiceTracker extends ServiceTracker {
private boolean codeUpgradeExecutionConditonSatisfied;
public ExecutionConditionCodeUpgradeTaskServiceTracker(BundleContext context) {
super(context, CodeUpgradeTask.class.getName(), null);
}
@Override
public T addingService(ServiceReference reference) {
T service = super.addingService(reference);
if ("com.day.cq.compat.codeupgrade.impl.ExecutionConditionCodeUpgradeTask".equals(service.getClass().getName())) {
codeUpgradeExecutionConditonSatisfied = true;
}
return service;
}
public boolean isCodeUpgradeExecutionConditonSatisfied() {
return codeUpgradeExecutionConditonSatisfied;
}
}
//if a temporary property file exists, then it contains the new build number and we must updated the quickstart.properties file
private void updateInstallPropertiesFile(BundleContext context) {
final ServiceReference ref = context.getServiceReference(SlingSettingsService.class.getName());
if (ref == null) {
throw new IllegalStateException("SlingSettingsService not found.");
}
SlingSettingsService slingSettings = (SlingSettingsService) context.getService(ref);
File confFolder = new File(slingSettings.getSlingHomePath(), "conf");
File tmpInstallFile = new File(confFolder, "quickstart.properties_tmp");
if (tmpInstallFile.exists()) {
File installFile = new File(confFolder, "quickstart.properties");
if (installFile.exists() && installFile.delete()) {
tmpInstallFile.renameTo(installFile);
}
}
}
private void executePostUpgradeHC(BundleContext context) {
log.info("Start executing post-upgrade health checks.");
final ServiceReference ref = context.getServiceReference(HealthCheckExecutor.class.getName());
if (ref == null) {
throw new IllegalStateException("HealthCheckExecutor not found.");
}
final HealthCheckExecutor healthCheckExecutor = (HealthCheckExecutor) context.getService(ref);
for (HealthCheckExecutionResult healthCheckExecutionResult : healthCheckExecutor.execute("post-upgrade")) {
Result result = healthCheckExecutionResult.getHealthCheckResult();
String hcName = healthCheckExecutionResult.getHealthCheckMetadata().getName();
if (!result.isOk()) {
log.error("{} health check failed:", hcName);
for (Iterator it = result.iterator(); it.hasNext();) {
ResultLog.Entry logEntry = it.next();
Result.Status status = logEntry.getStatus();
if (Result.Status.INFO != status && Result.Status.DEBUG != status) {
log.error(logEntry.getMessage());
}
}
} else {
log.info("{} health check ran successfully.", hcName);
}
}
log.info("Finished executing post-upgrade health checks.");
}
public void stop(BundleContext context) throws Exception {
if (st != null) {
st.close();
}
}
private void runUpgradeTasks(BundleContext context, InfoProvider ip) {
ip.say("Collecting CodeUpgradeTasks");
try {
// Get CodeUpgradeTaskFilters
final ServiceReference[] filterRefs = context.getServiceReferences(CodeUpgradeTaskFilter.class.getName(), null);
log.info("UPGRADE TASK FILTERS - {} {} services found", filterRefs.length, CodeUpgradeTaskFilter.class.getName());
if (filterRefs != null && filterRefs.length > 0) {
Arrays.sort(filterRefs);
}
List filters = new LinkedList();
for (ServiceReference filterRef : filterRefs) {
filters.add((CodeUpgradeTaskFilter) context.getService(filterRef));
}
// Get tasks and sort by service ranking
final ServiceReference[] refs = context.getServiceReferences(CodeUpgradeTask.class.getName(), null);
if (refs == null || refs.length < 1) {
log.info("NO UPGRADE TASKS - no {} services found, nothing to do", CodeUpgradeTask.class.getName());
return;
}
Arrays.sort(refs);
// Collect tasks
final List tasks = new ArrayList();
for (ServiceReference ref : refs) {
CodeUpgradeTask cut = (CodeUpgradeTask) context.getService(ref);
boolean isSkipped = false;
Iterator filterIt = filters.iterator();
while (filterIt.hasNext() && !isSkipped) {
CodeUpgradeTaskFilter filter = filterIt.next();
log.debug("Checking CodeUpgradeTask {} with CodeUpgradeTaskFilter {}", cut.getClass().getSimpleName(),
filter.getClass().getSimpleName());
isSkipped |= filter.isSkipped(cut);
if (isSkipped) {
log.info("Skipped CodeUpgradeTask {} due to CodeUpgradeTaskFilter {}", cut.getClass().getSimpleName(),
filter.getClass().getSimpleName());
}
}
if (!isSkipped) {
tasks.add(cut);
}
}
// Execute tasks
final long startTime = System.currentTimeMillis();
ip.say("Checking " + refs.length + " candidate CodeUpgradeTasks: " + tasks);
int successful = 0;
int failed = 0;
int skipped = 0;
for (CodeUpgradeTask t : tasks) {
try {
if (t.upgradeNeeded()) {
ip.say("UPGRADE TASK STARTING: " + t);
ip.setTask(t);
t.run();
ip.setTask(null);
ip.say("UPGRADE TASK DONE: " + t);
successful++;
} else {
skipped++;
ip.say("UPGRADE TASK SKIPPED: " + t);
}
} catch (RuntimeException e) {
failed++;
ip.say("UPGRADE TASK FAILED: " + t);
} finally {
ip.setTask(null);
}
}
final long elapsed = System.currentTimeMillis() - startTime;
log.info("UPGRADE FINISHED: From a total of {} CodeUpgradeTasks: {} were successfully executed, {} failed and {} skipped. " +
"Total execution time about {} seconds", refs.length, successful, failed, skipped, elapsed / 1000);
} catch (InvalidSyntaxException e) {
log.error("Could not get ServiceReferences", e);
}
}
private void invalidateCaches(BundleContext context) {
final ServiceReference ref = context.getServiceReference(HtmlLibraryManager.class);
if (ref != null) {
HtmlLibraryManager mgr = context.getService(ref);
try {
mgr.invalidateOutputCache();
log.info("Cleaned HtmlLibraryManager output cache.");
} catch (RepositoryException e) {
log.error("Can't clean HtmlLibraryManager output cache.");
}
} else {
log.error("Reference to HtmlLibraryManager not found - couldn't clean output cache.");
}
}
}