From b71fd6a98a2bc1f1e26fa73639754b9326ba08e1 Mon Sep 17 00:00:00 2001 From: Victor Alfaro Date: Tue, 12 Nov 2024 09:28:14 -0600 Subject: [PATCH] test --- .../OSGIActionletLateRegistration.java | 96 +++++++++++++------ .../framework/OSGIRegistrationAttempt.java | 54 ----------- .../framework/OSGIRegistrationCheck.java | 63 ++++++++++++ .../org/apache/felix/framework/OSGIUtil.java | 38 ++++---- 4 files changed, 151 insertions(+), 100 deletions(-) delete mode 100644 dotCMS/src/main/java/org/apache/felix/framework/OSGIRegistrationAttempt.java create mode 100644 dotCMS/src/main/java/org/apache/felix/framework/OSGIRegistrationCheck.java diff --git a/dotCMS/src/main/java/org/apache/felix/framework/OSGIActionletLateRegistration.java b/dotCMS/src/main/java/org/apache/felix/framework/OSGIActionletLateRegistration.java index eb0ea046805..c51ead89e4e 100644 --- a/dotCMS/src/main/java/org/apache/felix/framework/OSGIActionletLateRegistration.java +++ b/dotCMS/src/main/java/org/apache/felix/framework/OSGIActionletLateRegistration.java @@ -3,73 +3,115 @@ import com.dotcms.concurrent.DotConcurrentFactory; import com.dotmarketing.portlets.workflows.actionlet.WorkFlowActionlet; import com.dotmarketing.util.Config; +import com.dotmarketing.util.Logger; +import com.liferay.util.StringPool; import org.osgi.framework.BundleContext; import java.util.ArrayList; import java.util.Collection; -import java.util.Hashtable; import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; public class OSGIActionletLateRegistration { - private static final String OSGI_REGISTRATION_ATTEMPTS_MAX_KEY = "OSGI_REGISTRATION_ATTEMPTS_MAX"; + private static final String OSGI_REGISTRATION_CHECKS_MAX_KEY = "OSGI_REGISTRATION_ATTEMPTS_MAX"; private static final int REGISTRATION_DELAY = 500; private static final Object LOCK = new Object(); - private final Hashtable registrationAttempts = new Hashtable<>(); + private final ConcurrentMap registrationChecks = new ConcurrentHashMap<>(); - private Future> registrationFuture; + private Future> registrationCheckFuture; public void addActionlet(final BundleContext context, final WorkFlowActionlet actionlet, final Collection registered) { - registrationAttempts.put(actionlet.getName(), new OSGIRegistrationAttempt(context, actionlet, registered)); + Logger.info(this, String.format("Adding actionlet [%s] for later registration", actionlet.getName())); + registrationChecks.put(actionlet.getName(), new OSGIRegistrationCheck(context, actionlet, registered)); + startIfHasNot(); + } + public List waitForRegistrationChecks() throws InterruptedException, ExecutionException { synchronized (LOCK) { - startIfHasNot(); - } + if (registrationCheckFuture == null) { + return List.of(); + } + while(!registrationCheckFuture.isDone()) { + Logger.info(this, "Waiting for registration checks to finish"); + TimeUnit.MILLISECONDS.sleep(250); + } - } + final List checks = registrationCheckFuture.get(); + cleanUp(); - public boolean isDone() { - final int maxAttempts = Config.getIntProperty(OSGI_REGISTRATION_ATTEMPTS_MAX_KEY, 12); - return registrationAttempts.isEmpty() - || registrationAttempts.values() - .stream() - .allMatch(attempt -> attempt.isReadyToRegister() || attempt.getTries() == maxAttempts); + return checks; + } } private void startIfHasNot() { synchronized (LOCK) { - if (registrationFuture == null) { - registrationFuture = DotConcurrentFactory.getInstance().getSubmitter().submit(this::checkRegistrations); + if (registrationCheckFuture == null) { + registrationCheckFuture = DotConcurrentFactory.getInstance().getSubmitter().submit(this::checkRegistrations); } } } - private boolean checksLeft(int maxAttempts) { - return registrationAttempts.isEmpty() || - registrationAttempts.values() + private boolean checkIfLeft(int maxAttempts) { + return registrationChecks.isEmpty() || + registrationChecks.values() .stream() - .allMatch(attempt -> attempt.isReadyToRegister() || attempt.getTries() == maxAttempts); + .allMatch(attempt -> attempt.isReadyToRegister() || attempt.getAttempts() == maxAttempts); } - private List checkRegistrations() throws InterruptedException { - final int maxAttempts = Config.getIntProperty(OSGI_REGISTRATION_ATTEMPTS_MAX_KEY, 12); - while (!checksLeft(maxAttempts)) { - registrationAttempts.values().forEach(attempt -> { + private List checkRegistrations() throws InterruptedException { + final int maxAttempts = Config.getIntProperty(OSGI_REGISTRATION_CHECKS_MAX_KEY, 10); + Logger.info(this, "Starting OSGI actionlet registration checks"); + + while (!checkIfLeft(maxAttempts)) { + registrationChecks.values().forEach(attempt -> { + Logger.info( + this, + String.format( + "New OSGI registration check for actionlet [%s]", + attempt.getActionlet().getName())); if (OSGIUtil.getInstance().isReadyToRegisterActionlet(attempt.getContext())) { + Logger.info( + this, + String.format( + "Detected that context is ready for actionlet [%s]", + attempt.getActionlet().getName())); attempt.setReadyToRegister(true); - } else if (attempt.getTries() < maxAttempts) { - attempt.incrementTries(); + } else if (attempt.getAttempts() < maxAttempts) { + Logger.info( + this, + String.format( + "Context is NOT ready for actionlet [%s], giving another try", + attempt.getActionlet().getName())); + attempt.incrementAttempts(); } }); TimeUnit.MILLISECONDS.sleep(REGISTRATION_DELAY); } - return new ArrayList<>(registrationAttempts.values()); + final List result = new ArrayList<>(registrationChecks.values()); + Logger.info( + this, + String.format( + "Registration checks finished with following registrations statuses: [%s]", + result.stream() + .map(OSGIRegistrationCheck::toString) + .collect(Collectors.joining(StringPool.COMMA)))); + + return result; + } + + private void cleanUp() { + registrationChecks.clear(); + registrationCheckFuture = null; } } diff --git a/dotCMS/src/main/java/org/apache/felix/framework/OSGIRegistrationAttempt.java b/dotCMS/src/main/java/org/apache/felix/framework/OSGIRegistrationAttempt.java deleted file mode 100644 index 835e6a7fa98..00000000000 --- a/dotCMS/src/main/java/org/apache/felix/framework/OSGIRegistrationAttempt.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.apache.felix.framework; - -import com.dotmarketing.portlets.workflows.actionlet.WorkFlowActionlet; -import org.osgi.framework.BundleContext; - -import java.util.Collection; - -public class OSGIRegistrationAttempt { - - private final BundleContext context; - private final WorkFlowActionlet toRegister; - private final Collection tracked; - private int tries; - private boolean readyToRegister; - - public OSGIRegistrationAttempt(final BundleContext context, - final WorkFlowActionlet toRegister, - final Collection tracked) { - this.context = context; - this.toRegister = toRegister; - this.tracked = tracked; - tries = 0; - readyToRegister = false; - } - - public BundleContext getContext() { - return context; - } - - public WorkFlowActionlet getToRegister() { - return toRegister; - } - - public Collection getTracked() { - return tracked; - } - - public int getTries() { - return tries; - } - - public boolean isReadyToRegister() { - return readyToRegister; - } - - public void setReadyToRegister(boolean readyToRegister) { - this.readyToRegister = readyToRegister; - } - - public void incrementTries() { - tries++; - } - -} diff --git a/dotCMS/src/main/java/org/apache/felix/framework/OSGIRegistrationCheck.java b/dotCMS/src/main/java/org/apache/felix/framework/OSGIRegistrationCheck.java new file mode 100644 index 00000000000..d1b32ad6d9d --- /dev/null +++ b/dotCMS/src/main/java/org/apache/felix/framework/OSGIRegistrationCheck.java @@ -0,0 +1,63 @@ +package org.apache.felix.framework; + +import com.dotmarketing.portlets.workflows.actionlet.WorkFlowActionlet; +import org.osgi.framework.BundleContext; + +import java.util.Collection; +import java.util.Optional; + +public class OSGIRegistrationCheck { + + private final BundleContext context; + private final WorkFlowActionlet actionlet; + private final Collection actionlets; + private int attempts; + private boolean readyToRegister; + + public OSGIRegistrationCheck(final BundleContext context, + final WorkFlowActionlet actionlet, + final Collection actionlets) { + this.context = context; + this.actionlet = actionlet; + this.actionlets = actionlets; + attempts = 0; + readyToRegister = false; + } + + public BundleContext getContext() { + return context; + } + + public WorkFlowActionlet getActionlet() { + return actionlet; + } + + public Collection getActionlets() { + return actionlets; + } + + public int getAttempts() { + return attempts; + } + + public boolean isReadyToRegister() { + return readyToRegister; + } + + public void setReadyToRegister(boolean readyToRegister) { + this.readyToRegister = readyToRegister; + } + + public void incrementAttempts() { + attempts++; + } + + @Override + public String toString() { + return "OSGIRegistrationCheck{" + + "actionlet=" + Optional.ofNullable(actionlet).map(WorkFlowActionlet::getName).orElse(null) + + ", attempts=" + attempts + + ", readyToRegister=" + readyToRegister + + '}'; + } +} diff --git a/dotCMS/src/main/java/org/apache/felix/framework/OSGIUtil.java b/dotCMS/src/main/java/org/apache/felix/framework/OSGIUtil.java index 32550b82e47..a8b3a94fb53 100644 --- a/dotCMS/src/main/java/org/apache/felix/framework/OSGIUtil.java +++ b/dotCMS/src/main/java/org/apache/felix/framework/OSGIUtil.java @@ -136,8 +136,7 @@ public static OSGIUtil getInstance() { private Framework felixFramework; private String felixExtraPackagesFile; private WorkflowAPIOsgiService workflowOsgiService; - private Boolean osgiStarted = false; - private OSGIActionletLateRegistration osgiActionletLateRegistration = new OSGIActionletLateRegistration(); + private OSGIActionletLateRegistration osgiLateRegistration = new OSGIActionletLateRegistration(); //List of jar prefixes of the jars to be included in the osgi-extra.conf file public final List portletIDsStopped = Collections.synchronizedList(new ArrayList<>()); @@ -400,10 +399,11 @@ public synchronized Framework initializeFramework() { felixFramework = null; Logger.error(this, "Could not create framework: " + ex); throw new RuntimeException(ex); + } finally { + registerLateActionlets(); } - setOsgiStarted(true); - System.setProperty(WebKeys.OSGI_ENABLED, osgiStarted.toString()); + System.setProperty(WebKeys.OSGI_ENABLED, Boolean.TRUE.toString()); System.setProperty(WebKeys.DOTCMS_STARTUP_TIME_OSGI, String.valueOf(System.currentTimeMillis() - start)); @@ -430,7 +430,7 @@ public void registerActionlet(final BundleContext context, } public boolean isReadyToRegisterActionlet(final BundleContext context) { - return osgiStarted && context.getServiceReference(WorkflowAPIOsgiService.class.getName()) != null; + return context.getServiceReference(WorkflowAPIOsgiService.class.getName()) != null; } public void tryToRegisterAction(final BundleContext context, @@ -439,26 +439,26 @@ public void tryToRegisterAction(final BundleContext context, if (isReadyToRegisterActionlet(context)) { registerActionlet(context, actionlet, actionlets); } else { - osgiActionletLateRegistration.addActionlet(context, actionlet, actionlets); + osgiLateRegistration.addActionlet(context, actionlet, actionlets); } } - public void addActionletForLater(final BundleContext context, - final WorkFlowActionlet actionlet, - final Collection actionlets) { - - } - - /*public void registerLateActionlets() { - Logger.info(this, String.format("Registering [%d] pending actionlets", actionletsToRegister.size())); - actionletsToRegister.forEach(tuple -> registerActionlet(tuple._1, tuple._2)); - actionletsToRegister.clear(); - }*/ + public void registerLateActionlets() { + final List registrationChecks; + try { + registrationChecks = osgiLateRegistration.waitForRegistrationChecks(); + } catch (Exception e) { + Logger.warn(this, "Could not get late registration checks for actionlets", e); + return; + } + Logger.info(this, String.format("Registering [%d] pending actionlets", registrationChecks.size())); + registrationChecks.stream() + .filter(OSGIRegistrationCheck::isReadyToRegister) + .forEach(check -> registerActionlet(check.getContext(), check.getActionlet(), check.getActionlets())); - private void setOsgiStarted(final boolean osgiStarted) { - this.osgiStarted = osgiStarted; + registrationChecks.clear(); } private void startWatchingUploadFolder(final String uploadFolder) {