package org.springframework.roo.shell.osgi; import java.util.logging.Level; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.ReferenceCardinality; import org.apache.felix.scr.annotations.ReferencePolicy; import org.apache.felix.scr.annotations.ReferenceStrategy; import org.osgi.service.component.ComponentContext; import org.springframework.roo.shell.Shell; import org.springframework.roo.support.osgi.OSGiUtils; /** * Provides an easy way for subclasses to publish flash messages if a * {@link Shell} is available but without creating a dependency on the * {@link Shell} being available. This abstract class also enables subclasses to * safely determine if the {@link Shell} is in development mode. * <p> * Subclasses should not use the normal * {@link Shell#flash(Level, String, String)} method. Instead they should use * {@link #flash(Level, String, String)} and not declare a direct dependency on * {@link Shell}. * <p> * If a {@link Shell} is not available, this class will simply not publish flash * messages. If a {@link Shell} is available, flash messages will be sent to * that {@link Shell}. * * @author Ben Alex * @author Juan Carlos GarcĂ­a * @since 1.1 */ @Component(componentAbstract = true) @Reference(name = "shell", strategy = ReferenceStrategy.EVENT, policy = ReferencePolicy.DYNAMIC, referenceInterface = Shell.class, cardinality = ReferenceCardinality.OPTIONAL_UNARY) public abstract class AbstractFlashingObject { private final Class<?> mutex = getClass(); /** * Provided as a convenience for subclasses so they have a unique slot name * for flash messages. */ protected final String MY_SLOT = getClass().getName(); private Shell shell; protected void activate(final ComponentContext context) { // ROO-3824: Checking -DdevelopmentMode parameter shell.setDevelopmentMode(OSGiUtils.isDevelopmentMode(context)); } protected final void bindShell(final Shell shell) { synchronized (mutex) { this.shell = shell; } } /** * Same signature as {@link Shell#flash(Level, String, String)}. If this * method is called and the {@link Shell} is not available, it will simply * discard the flash message. * * @param level see {@link Shell#flash(Level, String, String)} * @param message see {@link Shell#flash(Level, String, String)} * @param slot see {@link Shell#flash(Level, String, String)} */ protected final void flash(final Level level, final String message, final String slot) { synchronized (mutex) { if (shell != null) { shell.flash(level, message, slot); } } } /** * Delegates to the {@link Shell#isDevelopmentMode()} method if available. * If no {@link Shell} is available, simply returns false. * * @return true if the shell is available and it is in development mode * (false in any other case) */ protected final boolean isDevelopmentMode() { synchronized (mutex) { if (shell != null) { return shell.isDevelopmentMode(); } return false; } } protected final void unbindShell(final Shell shell) { synchronized (mutex) { this.shell = null; } } }