diff --git a/impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/bootstrap/CoreBootstrap.java b/impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/bootstrap/CoreBootstrap.java index 325c52d..c3bc13e 100644 --- a/impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/bootstrap/CoreBootstrap.java +++ b/impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/bootstrap/CoreBootstrap.java @@ -86,9 +86,9 @@ public class CoreBootstrap implements Extension { } public void initializeCustomContexts(@Observes final AfterBeanDiscovery event) { - //StaticContext já é criado e gerenciado por esta chamada + // StaticContext já é criado e gerenciado por esta chamada ContextManager.initialize(event); - + ContextManager.activate(StaticContext.class, StaticScoped.class); } @@ -97,7 +97,7 @@ public class CoreBootstrap implements Extension { } public void engineOff(@Observes final BeforeShutdown event) { - ContextManager.deactivate(StaticContext.class, StaticScoped.class); + ContextManager.shutdown(); getLogger().info(getBundle().getString("engine-off")); } } diff --git a/impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/context/ContextManager.java b/impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/context/ContextManager.java index a3d1aa8..1277c49 100644 --- a/impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/context/ContextManager.java +++ b/impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/context/ContextManager.java @@ -9,6 +9,7 @@ import java.util.Locale; import javax.enterprise.context.ContextNotActiveException; import javax.enterprise.context.spi.Context; import javax.enterprise.inject.spi.AfterBeanDiscovery; +import javax.enterprise.inject.spi.BeanManager; import org.slf4j.Logger; @@ -20,62 +21,82 @@ import br.gov.frameworkdemoiselle.util.Beans; import br.gov.frameworkdemoiselle.util.ResourceBundle; /** - *

Manage custom contexts relevant to Demoiselle operations.

- * - *

When starting, the ContextManager must be initialized by calling {@link #initialize(AfterBeanDiscovery event)} - * inside any methods observing the {@link AfterBeanDiscovery} event. Upon initialization a {@link StaticContext} will be - * created to handle {@link StaticScoped} beans (but not activated, you must call {@link #activate(Class customContextClass, Class scope)} - * to activate this context).

- * - *

If an extension wants to manage another custom context, it must first call {@link #add(CustomContext context, AfterBeanDiscovery event)} - * to add it's context to the list of managed contexts and then call {@link #activate(Class customContextClass, Class scope)} whenever - * it wants to activate this added context (contexts added through the {@link #add(CustomContext context, AfterBeanDiscovery event)} method are also - * not activated upon adding).

+ *

+ * Manage custom contexts relevant to Demoiselle operations. + *

+ *

+ * When starting, the ContextManager must be initialized by calling {@link #initialize(AfterBeanDiscovery event)} inside + * any methods observing the {@link AfterBeanDiscovery} event. Upon initialization a {@link StaticContext} will be + * created to handle {@link StaticScoped} beans (but not activated, you must call + * {@link #activate(Class customContextClass, Class scope)} to activate this context). + *

+ *

+ * If an extension wants to manage another custom context, it must first call + * {@link #add(CustomContext context, AfterBeanDiscovery event)} to add it's context to the list of managed contexts and + * then call {@link #activate(Class customContextClass, Class scope)} whenever it wants to activate this added context + * (contexts added through the {@link #add(CustomContext context, AfterBeanDiscovery event)} method are also not + * activated upon adding). + *

* * @author serpro - * */ public class ContextManager { - - private static List contexts = Collections.synchronizedList(new ArrayList()); - + + private static List contexts = Collections + .synchronizedList(new ArrayList()); + private static boolean initialized = false; - + private static ResourceBundle bundle; - + private static Logger logger; - + /** - *

Initializes this manager and adds the {@link StaticContext} context to the list of managed contexts. Other - * contexts must be added before they can be activated.

- * - *

It's OK to call this method multiple times, it will be initialized only once.

+ *

+ * Initializes this manager and adds the {@link StaticContext} context to the list of managed contexts. Other + * contexts must be added before they can be activated. + *

+ *

+ * It's OK to call this method multiple times, it will be initialized only once. + *

* - * @param event The CDI event indicating all beans have been discovered. + * @param event + * The CDI event indicating all beans have been discovered. */ - public static void initialize(AfterBeanDiscovery event){ - if (initialized){ + public static void initialize(AfterBeanDiscovery event) { + if (initialized) { return; } - - add(new StaticContext(),event); - initialized=true; + + add(new StaticContext(), event); + initialized = true; } - + /** - *

Adds a context to the list of managed contexts.

- * - *

A context added through this method will be deactivated before management can start. Only after calling - * {@link #activate(Class customContextClass, Class scope)} the context will be activated.

- * - *

Trying to add a context already managed will result in this method call being ignored.

+ *

+ * Adds a context to the list of managed contexts. + *

+ *

+ * A context added through this method will be deactivated before management can start. Only after calling + * {@link #activate(Class customContextClass, Class scope)} the context will be activated. + *

+ *

+ * Trying to add a context already managed will result in this method call being ignored. + *

* - * @param context The context to be added - * @param event The CDI event indicating all beans have been discovered. + * @param context + * The context to be added + * @param event + * The CDI event indicating all beans have been discovered. */ - public static void add(CustomContext context,AfterBeanDiscovery event){ - for (CustomContextCounter contextCounter : contexts){ - if (contextCounter.isSame(context.getClass(), context.getScope())){ + public static void add(CustomContext context, AfterBeanDiscovery event) { + for (CustomContextCounter contextCounter : contexts) { + if (contextCounter.isSame(context.getClass(), context.getScope())) { + + ContextManager.getLogger().trace( + ContextManager.getBundle().getString("bootstrap-context-already-managed", + context.getClass().getCanonicalName(), context.getScope().getCanonicalName())); + return; } } @@ -84,154 +105,172 @@ public class ContextManager { event.addContext(context); contexts.add(new CustomContextCounter(context)); } - + /** - *

Activates a managed context.

- * - *

To be activated, a context must fulfill the following requisites: + *

+ * Activates a managed context. + *

+ *

+ * To be activated, a context must fulfill the following requisites: *

    - * - *
  • Must be managed by this class (be of type {@link StaticScoped} or be added with {@link #add(CustomContext context, AfterBeanDiscovery event)})
  • + *
  • Must be managed by this class (be of type {@link StaticScoped} or be added with + * {@link #add(CustomContext context, AfterBeanDiscovery event)})
  • *
  • Must be of a scope not already attached to another active context
  • - * *
*

* - * @param customContextClass Type of context to activate - * @param scope The scope to activate this context for - * @return true if there is a managed context of the provided type and scope and no other context is active for the provided scope, - * false if there is a managed context of the provided type and scope but another context is active for the provided scope. - * - * @throws DemoiselleException if there is no managed context of the provided type and scope. + * @param customContextClass + * Type of context to activate + * @param scope + * The scope to activate this context for + * @return true if there is a managed context of the provided type and scope and no other context is + * active for the provided scope, false if there is a managed context of the provided type and + * scope but another context is active for the provided scope. + * @throws DemoiselleException + * if there is no managed context of the provided type and scope. */ - public static synchronized void activate(Class customContextClass , Class scope){ - if (!initialized){ + public static synchronized void activate(Class customContextClass, + Class scope) { + if (!initialized) { throw new DemoiselleException(getBundle().getString("custom-context-manager-not-initialized")); } - - for (CustomContextCounter context : contexts){ - if ( context.isSame(customContextClass, scope) ){ + + for (CustomContextCounter context : contexts) { + if (context.isSame(customContextClass, scope)) { context.activate(); return; } } - throw new DemoiselleException(getBundle().getString("custom-context-not-found",customContextClass.getCanonicalName(),scope.getSimpleName())); + throw new DemoiselleException(getBundle().getString("custom-context-not-found", + customContextClass.getCanonicalName(), scope.getSimpleName())); } - + /** - *

Deactivates a managed context.

- * - *

To be deactivated, a context must fulfill the following requisites: + *

+ * Deactivates a managed context. + *

+ *

+ * To be deactivated, a context must fulfill the following requisites: *

    - * - *
  • Must be managed by this class (be of type {@link StaticScoped} or be added with {@link #add(CustomContext context, AfterBeanDiscovery event)})
  • + *
  • Must be managed by this class (be of type {@link StaticScoped} or be added with + * {@link #add(CustomContext context, AfterBeanDiscovery event)})
  • *
  • Must have been activated by a previous call to {@link #activate(Class customContextClass, Class scope)}
  • *
  • This previous call must have returned true. - * *
*

* - * @param customContextClass Type of context to deactivate - * @param scope The scope the context controled when it was active - * @return true if there was an active context of this type and scope and it was activated by a previous - * call to {@link #activate(Class customContextClass, Class scope)} - * - * @throws DemoiselleException if there is no managed context of the provided type and scope. + * @param customContextClass + * Type of context to deactivate + * @param scope + * The scope the context controled when it was active + * @return true if there was an active context of this type and scope and it was activated by a + * previous call to {@link #activate(Class customContextClass, Class scope)} + * @throws DemoiselleException + * if there is no managed context of the provided type and scope. */ - public static synchronized void deactivate(Class customContextClass,Class scope){ - if (!initialized){ + public static synchronized void deactivate(Class customContextClass, + Class scope) { + if (!initialized) { throw new DemoiselleException(getBundle().getString("custom-context-manager-not-initialized")); } - - for (CustomContextCounter context : contexts){ - if (context.isSame(customContextClass, scope)){ + + for (CustomContextCounter context : contexts) { + if (context.isSame(customContextClass, scope)) { context.deactivate(); return; } } - throw new DemoiselleException(getBundle().getString("custom-context-not-found",customContextClass.getCanonicalName(),scope.getSimpleName())); + throw new DemoiselleException(getBundle().getString("custom-context-not-found", + customContextClass.getCanonicalName(), scope.getSimpleName())); } - static Logger getLogger(){ - if (logger==null){ + public static synchronized void shutdown() { + for (CustomContextCounter context : contexts) { + context.deactivate(); + } + + contexts.clear(); + initialized = false; + } + + static Logger getLogger() { + if (logger == null) { logger = LoggerProducer.create(ContextManager.class); } - + return logger; } - - static ResourceBundle getBundle(){ - if (bundle==null){ - bundle = ResourceBundleProducer.create("demoiselle-core-bundle",Locale.getDefault()); + + static ResourceBundle getBundle() { + if (bundle == null) { + bundle = ResourceBundleProducer.create("demoiselle-core-bundle", Locale.getDefault()); } - + return bundle; } } + /** - * Class that counts how many attemps to activate and deactivate this context received, avoiding cases - * where one client activates given context and another one deactivates it, leaving the first client - * with no active context before completion. + * Class that counts how many attemps to activate and deactivate this context received, avoiding cases where one client + * activates given context and another one deactivates it, leaving the first client with no active context before + * completion. * * @author serpro - * */ -class CustomContextCounter{ +class CustomContextCounter { + private CustomContext context; + private int activationCounter = 0; - + public CustomContextCounter(CustomContext customContext) { this.context = customContext; } - - public boolean isSame(Class customContextClass,Class scope){ - if (context.getClass().getCanonicalName().equals( customContextClass.getCanonicalName() ) - && context.getScope().equals(scope)){ + + public boolean isSame(Class customContextClass, Class scope) { + if (context.getClass().getCanonicalName().equals(customContextClass.getCanonicalName()) + && context.getScope().equals(scope)) { return true; } - + return false; } - - public CustomContext getInternalContext(){ + + public CustomContext getInternalContext() { return this.context; } - - public synchronized void activate(){ - try{ - Context c = Beans.getBeanManager().getContext(context.getScope()); - if (c==context){ + + public synchronized void activate() { + try { + BeanManager beanManager = Beans.getReference(BeanManager.class); + Context c = beanManager.getContext(context.getScope()); + if (c == context) { activationCounter++; } - } - catch(ContextNotActiveException ce){ + } catch (ContextNotActiveException ce) { context.setActive(true); activationCounter++; ContextManager.getLogger().trace( - ContextManager.getBundle().getString("custom-context-was-activated" - , context.getClass().getCanonicalName() - ,context.getScope().getCanonicalName() - )); + ContextManager.getBundle().getString("custom-context-was-activated", + context.getClass().getCanonicalName(), context.getScope().getCanonicalName())); } } - - public synchronized void deactivate(){ - try{ + + public synchronized void deactivate() { + try { Context c = Beans.getBeanManager().getContext(context.getScope()); - if (c==context){ + if (c == context) { activationCounter--; - if (activationCounter==0){ + if (activationCounter == 0) { context.setActive(false); ContextManager.getLogger().trace( - ContextManager.getBundle().getString("custom-context-was-deactivated" - , context.getClass().getCanonicalName() - ,context.getScope().getCanonicalName() - )); + ContextManager.getBundle().getString("custom-context-was-deactivated", + context.getClass().getCanonicalName(), context.getScope().getCanonicalName())); } } + } catch (ContextNotActiveException ce) { } - catch(ContextNotActiveException ce){} } } diff --git a/impl/core/src/main/resources/demoiselle-core-bundle.properties b/impl/core/src/main/resources/demoiselle-core-bundle.properties index dbb2440..8e604b9 100644 --- a/impl/core/src/main/resources/demoiselle-core-bundle.properties +++ b/impl/core/src/main/resources/demoiselle-core-bundle.properties @@ -53,6 +53,7 @@ transaction-commited=Transa\u00E7\u00E3o finalizada com sucesso transaction-rolledback=Transa\u00E7\u00E3o finalizada com rollback bootstrap.configuration.processing=Processando {0} +bootstrap-context-already-managed=O contexto {0} para o escopo {1} j\u00E1 \u00E9 gerenciado loading-configuration-class=Carregando a classe de configura\u00E7\u00E3o {0} configuration-field-loaded=Configura\u00E7\u00E3o {0} atribu\u00EDda a {1} com o valor {2} -- libgit2 0.21.2