
com.adobe.cq.upgradesexecutor.Activator Maven / Gradle / Ivy
/*************************************************************************
*
* 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.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.jcr.Item;
import javax.jcr.Session;
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.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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.day.cq.compat.codeupgrade.CodeUpgradeTask;
/** 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";
/** 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();
if(sm != StartupMode.UPDATE) {
// If we have a repository service and the FORCE_UPGRADES_PATH property is
// true, force upgrade code to run
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 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);
runUpgradeTasks(context, ip);
} finally {
reg.unregister();
}
}
public void stop(BundleContext context) throws Exception {
// nothing to do
}
private void runUpgradeTasks(BundleContext context, InfoProvider ip) throws InvalidSyntaxException {
ip.say("Collecting CodeUpgradeTasks");
// 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) {
tasks.add((CodeUpgradeTask)context.getService(ref));
}
// Execute tasks
final long startTime = System.currentTimeMillis();
ip.say("Checking " + refs.length + " candidate CodeUpgradeTasks: " + tasks);
int executed = 0;
for(CodeUpgradeTask t : tasks) {
if(t.upgradeNeeded()) {
try {
ip.say("UPGRADE TASK STARTING: " + t);
ip.setTask(t);
t.run();
ip.setTask(null);
ip.say("UPGRADE TASK DONE: " + t);
executed++;
} finally {
ip.setTask(null);
}
} else {
ip.say("UPGRADE TASK SKIPPED: " + t);
}
}
final long elapsed = System.currentTimeMillis() - startTime;
log.info("UPGRADE FINISHED: {} CodeUpgradeTasks executed (out of {}), total time about {} seconds",
new Object[] { executed, refs.length, elapsed / 1000 });
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy