Skip to content

Commit

Permalink
DELTASPIKE-24 rework Deactivation logic
Browse files Browse the repository at this point in the history
This introduces 3 new features
a.) allow deactivation and also re-activation based on ordinals
b.) make it a 1-liner to use for external Extensions
c.) Deativatable is now a pure Marker Interface
  • Loading branch information
struberg committed Jan 22, 2012
1 parent f5d1995 commit e3f7e3e
Show file tree
Hide file tree
Showing 15 changed files with 178 additions and 333 deletions.

This file was deleted.

@@ -0,0 +1,122 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.deltaspike.core.api.activation;

import org.apache.deltaspike.core.api.config.ConfigResolver;
import org.apache.deltaspike.core.api.util.ClassUtils;

import javax.enterprise.inject.Typed;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;

/**
* Helper methods for {@link ClassDeactivator}
*/
@Typed()
public final class ClassDeactivation
{
private static final Logger LOG = Logger.getLogger(ClassDeactivation.class.getName());

/**
* This Map holds the ClassLoader as first level to make it possible to have different configurations per
* WebApplication in an EAR or other Multi-ClassLoader scenario.
*
* The Map then contains a List of {@link ClassDeactivator}s in order of their configured ordinal.
*/
private static Map<ClassLoader, List<ClassDeactivator>> classDeactivatorMap
= new ConcurrentHashMap<ClassLoader, List<ClassDeactivator>>();

private ClassDeactivation()
{
// private ct to prevent utility class from instantiation.
}

/**
* Evaluates if the given {@link Deactivatable} is active.
*
* @param deactivatableClazz {@link Deactivatable} under test.
* @return <code>true</code> if it is active, <code>false</code> otherwise
*/
public static synchronized boolean isActivated(Class<? extends Deactivatable> deactivatableClazz)
{
List<ClassDeactivator> classDeactivators = getClassDeactivators();

Boolean isActivated = Boolean.TRUE; // by default a class is always activated.

for (ClassDeactivator classDeactivator : classDeactivators)
{
Boolean isLocallyActivated = classDeactivator.isActivated(deactivatableClazz);
if (isLocallyActivated != null)
{
isActivated = isLocallyActivated;
}
}

if (!isActivated)
{
LOG.info("Deactivating class " + deactivatableClazz);
}

return isActivated;
}


/**
* @return the List of configured @{link ClassDeactivator}s for the current context ClassLoader.
*/
private static List<ClassDeactivator> getClassDeactivators()
{
List<ClassDeactivator> classDeactivators = classDeactivatorMap.get(ClassUtils.getClassLoader(null));
if (classDeactivators == null)
{
classDeactivators = getConfiguredClassDeactivator();
}

return classDeactivators;
}

private static List<ClassDeactivator> getConfiguredClassDeactivator()
{
List<String> classDeactivatorClassNames = ConfigResolver.getAllPropertyValues(ClassDeactivator.class.getName());

List<ClassDeactivator> classDeactivators = new ArrayList<ClassDeactivator>();

for (String classDeactivatorClassName : classDeactivatorClassNames)
{
LOG.fine("processing ClassDeactivator: " + classDeactivatorClassName);

try
{
ClassDeactivator currentClassDeactivator =
(ClassDeactivator) ClassUtils.instantiateClassForName(classDeactivatorClassName);
classDeactivators.add(currentClassDeactivator);
}
catch (Exception e)
{
LOG.warning(classDeactivatorClassName + " can't be instantiated");
throw new RuntimeException(e);
}
}

return classDeactivators;
}
}
Expand Up @@ -19,26 +19,28 @@
package org.apache.deltaspike.core.api.activation;

import java.io.Serializable;
import java.util.Set;

/**
* <p>A class-deactivator allows to specify deactivated classes which can't be deactivated via std. CDI mechanisms.</p>
* <p>A class-deactivator allows to specify deactivated classes which can't be deactivated via std. CDI mechanisms.
* This might be the case for CDI Extensions because CDI mechanisms are not available at startup time.</p>
*
* <p>A class-deactivator will be resolved from the environment via the default resolvers or via a custom resolver which
* allows to use any type of configuration-format. See {@link org.apache.deltaspike.core.api.config.ConfigResolver}
* for more information about how to configure it. The configuration key is
* <code>org.apache.deltaspike.core.api.activation.ClassDeactivator</code></p>
*
* <p>Furthermore, {@link AbstractClassDeactivator} is a convenience class which
* allows an easier implementation. All classes which implement {@link Deactivatable} in-/directly, can be deactivated
* with this mechanism. For all other classes/beans, you can use the veto mechanism provided by CDI.</p>
* <p>All DlassDeactivators will get picked up in order of their ordinal and might explicitely activate or
* deactivate {@link Deactivatable} classes. Returning a <code>null</code> value means that the ClassDeactivator
* doesn't care about the very Deactivatable class.</p>
*
*/
public interface ClassDeactivator extends Serializable
{
/**
* Provides classes which should be deactivated.
*
* @return classes which should be deactivated
* @return {@link Boolean#FALSE} if class should get activated, {@link Boolean#FALSE} if class must be available
* and <code>null</code> to let it as is (defined by default or other
*/
Set<Class> getDeactivatedClasses();
Boolean isActivated(Class<? extends Deactivatable> deactivatableClazz);
}
Expand Up @@ -19,20 +19,18 @@
package org.apache.deltaspike.core.api.activation;

/**
* Interface to allow easier detection of deactivatable classes.
* These classes are activated by default (e.g. via CDI config).
* <p>Interface to allow easier detection of deactivatable classes.</p>
*
* <p>These classes are activated by default and can be disabled on demand (e.g. via CDI config).
* Since CDI, JSF,... currently don't allow to deactivate default implementations,
* DeltaSpike has to introduce a proprietary mechanism.
* DeltaSpike has to introduce a proprietary mechanism.</p>
*
* <p>This is e.g. used to disable CDI Extensions in DeltaSpike and might get
* used for other Extension libraries as well.</p>
*
* This is e.g. used to disable CDI Extensions in DeltaSpike and might get
* used for other Extension libraries as well.
* <p><b>Note:</b> It is suggested that the implementations
* use the {@link ClassDeactivation} for implementing the lookup</p>
*/
public interface Deactivatable
{
/**
* Returns if the current instance is active or not.
*
* @return true if the current instance is active, false otherwise
*/
boolean isActivated();
}
Expand Up @@ -84,9 +84,13 @@ public static String getPropertyValue(String key)
}

/**
* Resolve all values for the given key, from all registered ConfigSources.
* @param key
* @return List with all found property values, sorted in order of their ordinal.
* Resolve all values for the given key, from all registered ConfigSources ordered by their
* ordinal value in ascending ways. If more {@link ConfigSource}s have the same ordinal, their
* order is undefined.
*
* @param key under which configuration is stored
* @return List with all found property values, sorted in ascending order of their ordinal.
* @see org.apache.deltaspike.core.spi.config.ConfigSource#getOrdinal()
*/
public static List<String> getAllPropertyValues(String key)
{
Expand Down
Expand Up @@ -18,14 +18,14 @@
*/
package org.apache.deltaspike.core.impl.exclude;

import org.apache.deltaspike.core.api.activation.ClassDeactivation;
import org.apache.deltaspike.core.api.activation.Deactivatable;
import org.apache.deltaspike.core.api.exclude.Exclude;
import org.apache.deltaspike.core.api.interpreter.ExpressionInterpreter;
import org.apache.deltaspike.core.api.projectstage.ProjectStage;
import org.apache.deltaspike.core.api.util.ClassUtils;
import org.apache.deltaspike.core.impl.interpreter.PropertyExpressionInterpreter;
import org.apache.deltaspike.core.impl.projectstage.ProjectStageProducer;
import org.apache.deltaspike.core.impl.util.ClassDeactivation;

import javax.enterprise.event.Observes;
import javax.enterprise.inject.spi.AfterDeploymentValidation;
Expand All @@ -44,6 +44,8 @@ public class ExcludeExtension implements Extension, Deactivatable
{
private static final Logger LOG = Logger.getLogger(ExcludeExtension.class.getName());

private Boolean isActivated = null;

/**
* triggers initialization in any case
* @param afterDeploymentValidation observed event
Expand Down Expand Up @@ -197,12 +199,12 @@ private void veto(ProcessAnnotatedType<?> processAnnotatedType, String vetoType)
processAnnotatedType.getAnnotatedType().getJavaClass());
}

/**
* {@inheritDoc}
*/
@Override
public boolean isActivated()
{
return ClassDeactivation.isClassActivated(getClass());
if (isActivated == null)
{
isActivated = ClassDeactivation.isActivated(getClass());
}
return isActivated;
}
}

0 comments on commit e3f7e3e

Please sign in to comment.