/*
* ============================================================================
* GNU Lesser General Public License
* ============================================================================
*
* Beanlet - JSE Application Container.
* Copyright (C) 2006 Leon van Zantvoort
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
* Leon van Zantvoort
* 243 Acalanes Drive #11
* Sunnyvale, CA 94086
* USA
*
* zantvoort@users.sourceforge.net
* http://beanlet.org
*/
package org.beanlet.common;
import org.beanlet.annotation.ElementAnnotation;
import org.beanlet.annotation.PackageElement;
import org.beanlet.annotation.TypeElement;
import org.beanlet.plugin.BeanletConfiguration;
import org.beanlet.RetentionPolicy;
import org.beanlet.Retention;
import org.beanlet.Stateful;
import org.beanlet.Stateless;
import org.beanlet.Lazy;
import org.beanlet.Singleton;
import org.beanlet.Proxy;
import org.beanlet.ScopeAnnotation;
import org.beanlet.BeanletValidationException;
import org.jargo.ComponentConfiguration;
import java.lang.annotation.Annotation;
import java.util.*;
/**
*
* @author Leon van Zantvoort
*/
public final class Beanlets {
public static final String FACTORY_BEANLET_PREFIX = "&";
private static final RetentionPolicy DEFAULT_POLICY;
private static final Class<? extends Throwable>[] DEFAULT_TYPE;
private static final Map<ComponentConfiguration, Beanlets> cache =
new HashMap<ComponentConfiguration, Beanlets>();
public static final boolean CHAIN_JARGO_EXCEPTIONS;
static {
try {
DEFAULT_POLICY = (RetentionPolicy) Retention.class.
getMethod("value").getDefaultValue();
@SuppressWarnings("unchecked")
Class<? extends Throwable>[] tmp = (Class<? extends Throwable>[])
Retention.class.getMethod("type").getDefaultValue();
DEFAULT_TYPE = tmp;
} catch (NoSuchMethodException e) {
throw new AssertionError(e);
}
// PERMISSION: java.util.PropertyPermission "org.beanlet.chainJargoExceptions" "read"
CHAIN_JARGO_EXCEPTIONS = Boolean.getBoolean("org.beanlet.chainJargoExceptions");
}
public static final synchronized Beanlets getInstance(
final ComponentConfiguration<?> configuration) {
Beanlets beanlets = cache.get(configuration);
if (beanlets == null) {
if (configuration instanceof BeanletConfiguration) {
beanlets = new Beanlets((BeanletConfiguration<?>) configuration);
} else {
beanlets = new Beanlets();
}
configuration.getComponentUnit().addDestroyHook(new Runnable() {
public void run() {
synchronized (Beanlets.class) {
cache.remove(configuration);
}
}
});
cache.put(configuration, beanlets);
}
return beanlets;
}
private final Stateful statefulAnnotation;
private final Stateless statelessAnnotation;
private final Singleton singletonAnnotation;
private final Lazy lazyAnnotation;
private final Lazy lazyPackageAnnotation;
private final Retention retentionAnnotation;
private final Proxy proxyAnnotation;
private final List<Class<?>> interfaces;
private final boolean hasScopeAnnotation;
private Beanlets() {
statefulAnnotation = null;
statelessAnnotation = null;
singletonAnnotation = null;
lazyAnnotation = null;
lazyPackageAnnotation = null;
retentionAnnotation = null;
proxyAnnotation = null;
interfaces = Collections.emptyList();
hasScopeAnnotation = false;
}
private Beanlets(BeanletConfiguration configuration) {
// Too bad that we cannot get this info from the meta data object.
statefulAnnotation = configuration.getAnnotationDomain().getDeclaration(
Stateful.class).getAnnotation(
TypeElement.instance(configuration.getType()));
statelessAnnotation = configuration.getAnnotationDomain().getDeclaration(
Stateless.class).getAnnotation(
TypeElement.instance(configuration.getType()));
singletonAnnotation = configuration.getAnnotationDomain().getDeclaration(
Singleton.class).getAnnotation(
TypeElement.instance(configuration.getType()));
lazyAnnotation = configuration.getAnnotationDomain().getDeclaration(
Lazy.class).getAnnotation(
TypeElement.instance(configuration.getType()));
lazyPackageAnnotation = configuration.getAnnotationDomain().getDeclaration(
Lazy.class).getAnnotation(
PackageElement.instance(configuration.getType().getPackage()));
retentionAnnotation = configuration.getAnnotationDomain().getDeclaration(
Retention.class).getAnnotation(
TypeElement.instance(configuration.getType()));
proxyAnnotation = configuration.getAnnotationDomain().getDeclaration(
Proxy.class).getAnnotation(
TypeElement.instance(configuration.getType()));
interfaces = new ArrayList<Class<?>>();
if (proxyAnnotation != null) {
for (Class<?> inf : proxyAnnotation.value()) {
if (inf.isInterface()) {
interfaces.add(inf);
} else {
throw new BeanletValidationException(configuration.getComponentName(),
"Not an interface: '" + inf + "'.");
}
}
}
boolean tmpHasScopeAnnotation = false;
for (ElementAnnotation<TypeElement, ? extends Annotation> ea :
configuration.getAnnotationDomain().
getTypedElements(TypeElement.class, configuration.getType())) {
if (ea.getAnnotation().annotationType().
isAnnotationPresent(ScopeAnnotation.class)) {
tmpHasScopeAnnotation = true;
}
}
hasScopeAnnotation = tmpHasScopeAnnotation;
}
public boolean isStateful() {
return getStateful() != null;
}
public Stateful getStateful() {
return statefulAnnotation;
}
public boolean isStateless() {
return getStateless() != null;
}
public Stateless getStateless() {
return statelessAnnotation;
}
public boolean isVanilla() {
return getSingleton() != null || !hasScopeAnnotation;
}
public boolean isSingleton() {
return getSingleton() != null;
}
public Singleton getSingleton() {
return singletonAnnotation;
}
public boolean isLazy() {
return getLazy() != null && getLazy().value();
}
public Lazy getLazy() {
return lazyAnnotation == null ? lazyPackageAnnotation : lazyAnnotation;
}
public RetentionPolicy getRetentionPolicy() {
return retentionAnnotation == null ? DEFAULT_POLICY :
retentionAnnotation.value();
}
public Class<? extends Throwable>[] getRetentionExceptionType() {
return (retentionAnnotation == null ?
DEFAULT_TYPE : retentionAnnotation.type()).clone();
}
public boolean isPropxy() {
return proxyAnnotation != null;
}
public List<Class<?>> getInterfaces() {
return Collections.unmodifiableList(interfaces);
}
}