Commit ef525cbd authored by Lionel Seinturier's avatar Lionel Seinturier
Browse files

New @EagerDestroy method for performing actions when a composite-scoped...

New @EagerDestroy method for performing actions when a composite-scoped component is stopped (requested by Philippe.)
parent 5ae7fc26
Tinfi 1.2.1
-----------
* support property re-injection
* support property re-injection (requested by Christophe)
* new @EagerDestroy method for performing actions when a composite-scoped
component is stopped (requested by Philippe)
Tinfi 1.2
......
......@@ -23,7 +23,5 @@ runtime/oo-dyn/
Having a generic initializer should bypass this difficulty.
runtime-oo/
* support Tinfi specific @Start and @Stop annotations to trigger treatments
whenever the component is started, respectively stopped (suggested by Philippe)
* support polymorphic setter methods in POJOs (see p12 of "SCA Service Component
Architecture Java Component Implementation Specification")
......@@ -26,27 +26,26 @@ package org.ow2.frascati.tinfi.control.content;
import org.objectweb.fractal.api.control.IllegalLifeCycleException;
import org.objectweb.fractal.julia.control.lifecycle.ChainedIllegalLifeCycleException;
import org.objectweb.fractal.julia.control.lifecycle.LifeCycleCoordinator;
import org.ow2.frascati.tinfi.control.property.SCAPropertyController;
/**
* Mixin layer to be included in the lifecycle controller for managing the
* EagerInit policy.
* EagerInit and EagerDestroy policy.
*
* @author Lionel Seinturier <Lionel.Seinturier@univ-lille1.fr>
*/
public abstract class LifeCycleEagerInitMixin implements LifeCycleCoordinator {
public abstract class LifeCycleEagerMixin implements LifeCycleCoordinator {
// -------------------------------------------------------------------------
// Private constructor
// -------------------------------------------------------------------------
private LifeCycleEagerInitMixin() {}
private LifeCycleEagerMixin() {}
// -------------------------------------------------------------------------
// Implementation of the LifeCycleCoordinator interface
// -------------------------------------------------------------------------
public boolean setFcStarted () throws IllegalLifeCycleException {
public boolean setFcStarted() throws IllegalLifeCycleException {
/*
* Notify the SCA content controller that the component has been
......@@ -63,15 +62,36 @@ public abstract class LifeCycleEagerInitMixin implements LifeCycleCoordinator {
return _super_setFcStarted();
}
/**
* @since 1.2.1
*/
public boolean setFcStopped() throws IllegalLifeCycleException {
/*
* Notify the SCA content controller that the component has been
* stopped. This gives the opportunity to eager destory the component
* if the @EagerDestroy annotation has been set.
*/
try {
_this_weaveableSCACC.eagerDestroy();
}
catch( ContentInstantiationException ie ) {
throw new ChainedIllegalLifeCycleException(ie,null,"");
}
return _super_setFcStopped();
}
// -------------------------------------------------------------------------
// Fields and methods required by the mixin class in the base class
// -------------------------------------------------------------------------
public abstract boolean _super_setFcStarted() throws IllegalLifeCycleException;
public abstract boolean _super_setFcStopped() throws IllegalLifeCycleException;
/**
* The {@link SCAPropertyController} interface of the component to which
* The {@link SCAContentController} interface of the component to which
* this controller object belongs.
*/
public SCAContentController _this_weaveableSCACC;
......
......@@ -308,16 +308,69 @@ implements Controller, SCAContentController {
return sm.getFcContent();
}
/**
* Eager initialize the content instance associated with this component.
* Relevant only for composite-scoped components.
*
* @throws ContentInstantiationException
* if the content can not be instantiated or if the component is not
* composite-scoped
*/
public void eagerInit() throws ContentInstantiationException {
if( ccmd.eagerinit != null ) {
if( !(sm instanceof CompositeScopeManager) ) {
String msg =
"Eager initialization is meaningless in scopes other than "+
"COMPOSITE (scope is: "+ccmd.scope.value()+")";
throw new ContentInstantiationException(msg);
}
sm.getFcContent();
if( ccmd.eagerinit == null ) {
return;
}
if( !(sm instanceof CompositeScopeManager) ) {
String msg =
"Eager initialization is meaningless in scopes other than "+
"COMPOSITE (scope is: "+ccmd.scope.value()+")";
throw new ContentInstantiationException(msg);
}
/*
* Retrieve the content to trigger its initialization.
*/
sm.getFcContent();
}
/**
* Eager destroy the content instance associated with this component.
* Relevant only for composite-scoped components.
*
* @throws ContentInstantiationException
* if the content can not be destroyed or if the component is not
* composite-scoped
* @since 1.2.1
*/
public void eagerDestroy() throws ContentInstantiationException {
if( ccmd.eagerDestroyMethod == null ) {
return;
}
if( !(sm instanceof CompositeScopeManager) ) {
String msg =
"Eager destruction is meaningless in scopes other than "+
"COMPOSITE (scope is: "+ccmd.scope.value()+")";
throw new ContentInstantiationException(msg);
}
/*
* Retrieve the content instance and invoke the @EagerDestroy annotated
* method.
*/
Object content = sm.getFcContent();
try {
ccmd.eagerDestroyMethod.invoke(content);
}
catch (IllegalAccessException e) {
throw new ContentInstantiationException(e);
}
catch (InvocationTargetException e) {
throw new ContentInstantiationException(e);
}
}
/**
......
......@@ -85,7 +85,7 @@
)
# LifeCycleController implementation (for primitive or composite components)
# uses LifeCycleEagerInitMixin to notify the SCA content controller of start/stop events
# uses LifeCycleEagerMixin to notify the SCA content controller of start/stop events
(sca-lifecycle-controller-impl
((org.objectweb.fractal.julia.asm.MixinClassGenerator
SCALifeCycleControllerImpl
......@@ -98,7 +98,7 @@
# to notify the encapsulated component (if present) when its state changes:
org.objectweb.fractal.julia.control.lifecycle.ContainerLifeCycleMixin
org.ow2.frascati.tinfi.control.content.UseSCAContentControllerMixin
org.ow2.frascati.tinfi.control.content.LifeCycleEagerInitMixin
org.ow2.frascati.tinfi.control.content.LifeCycleEagerMixin
))
)
......
/***
* OW2 FraSCAti Tinfi
* Copyright (C) 2010 INRIA, USTL
*
* 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 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
*
* Contact: frascati@ow2.org
*
* Author: Lionel Seinturier
*/
package org.ow2.frascati.tinfi.annotations;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* Annotation used to indicate that a component instance should be destroyed
* when its enclosing composite component is stopped.
*
* @author Lionel Seinturier <Lionel.Seinturier@univ-lille1.fr>
* @since 1.2.1
*/
@Target(METHOD)
@Retention(RUNTIME)
public @interface EagerDestroy {
// Indeed nothing
}
......@@ -43,6 +43,7 @@ import org.osoa.sca.annotations.Init;
import org.osoa.sca.annotations.Property;
import org.osoa.sca.annotations.Reference;
import org.osoa.sca.annotations.Scope;
import org.ow2.frascati.tinfi.annotations.EagerDestroy;
import org.ow2.frascati.tinfi.reflect.AnnotatedElementFilter;
import org.ow2.frascati.tinfi.reflect.Filter;
import org.ow2.frascati.tinfi.reflect.Filters;
......@@ -128,6 +129,9 @@ public class ContentClassMetaData {
/** The method annotated with @{@link Destroy}, if any. */
public Method destroyMethod;
/** The method annotated with @{@link EagerDestroy}, if any. */
public Method eagerDestroyMethod;
/** The field or setter method annotated with @{@link Context}, if any. */
public InjectionPoint<Context> contextAnnotatedElement;
......@@ -229,6 +233,15 @@ public class ContentClassMetaData {
destroyMethod =
checkFcUniqueAnnotatedVoidMethod(destroys,Destroy.class);
/*
* Retrieve the setter or field annotated with @EagerDestroy, if any.
* Check that only one such method exists.
*/
filter = new AnnotatedElementFilter(EagerDestroy.class);
Method[] eagerDestroys = Filters.filter(methods,filter);
eagerDestroyMethod =
checkFcUniqueAnnotatedVoidMethod(eagerDestroys,EagerDestroy.class);
/*
* Retrieve the setter or field annotated with @Context, if any.
* Check that only one such element exists.
......@@ -359,15 +372,18 @@ public class ContentClassMetaData {
throw new IllegalContentClassMetaData(msg);
}
Method method = (methods.length==1) ? methods[0] : null;
if( method != null ) {
if( ! method.getReturnType().equals(void.class) ||
method.getParameterTypes().length != 0 ) {
String msg =
"The signature of the @"+annot+" annotated method ("+
method.getName()+") should be ():void";
throw new IllegalContentClassMetaData(msg);
}
if( methods.length == 0 ) {
return null;
}
// methods.length == 1
Method method = methods[0];
if( ! method.getReturnType().equals(void.class) ||
method.getParameterTypes().length != 0 ) {
String msg =
"The signature of the @"+annot+" annotated method ("+
method.getName()+") should be ():void";
throw new IllegalContentClassMetaData(msg);
}
return method;
......
......@@ -113,10 +113,21 @@ public interface SCAContentController {
*
* @throws ContentInstantiationException
* if the content can not be instantiated or if the component is not
* composite-scoped.
* composite-scoped
*/
public void eagerInit() throws ContentInstantiationException;
/**
* Eager destroy the content instance associated with this component.
* Relevant only for composite-scoped components.
*
* @throws ContentInstantiationException
* if the content can not be destroyed or if the component is not
* composite-scoped
* @since 1.2.1
*/
public void eagerDestroy() throws ContentInstantiationException;
/**
* Return <code>true</code> if the specified property is declared by the
* content class managed by this controller.
......
......@@ -25,6 +25,7 @@ package org.ow2.frascati.tinfi;
import org.osoa.sca.annotations.EagerInit;
import org.osoa.sca.annotations.Scope;
import org.ow2.frascati.tinfi.annotations.EagerDestroy;
/**
* Component implementation for testing request-scope components.
......@@ -36,8 +37,17 @@ import org.osoa.sca.annotations.Scope;
public class ScopeCompositeImpl extends ScopeImpl {
static boolean eagerinit = false;
static boolean eagerdestroy = false;
public ScopeCompositeImpl() {
eagerinit = true;
}
/**
* @since 1.2.1
*/
@EagerDestroy
public void whenStopped() {
eagerdestroy = true;
}
}
......@@ -25,6 +25,8 @@ package org.ow2.frascati.tinfi;
import org.junit.Assert;
import org.junit.Test;
import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.util.Fractal;
import org.osoa.sca.ConversationEndedException;
import org.osoa.sca.annotations.Scope;
......@@ -53,16 +55,31 @@ public class ScopeTestCase {
content, t.content);
}
/**
* @since 1.2.1
*/
@Test
public void testScopeCompositeEagerInit() throws Exception {
public void testScopeCompositeEager() throws Exception {
ScopeCompositeImpl.eagerinit = false;
ScopeCompositeImpl.eagerdestroy = false;
String adl = getClass().getPackage().getName()+".ScopeComposite";
TinfiDomain.getService(adl,ScopeItf.class,"s");
Component c = TinfiDomain.getComponent(adl);
Fractal.getLifeCycleController(c).startFc();
Assert.assertTrue(
"Content instance should have been eagerly initialized",
ScopeCompositeImpl.eagerinit);
Assert.assertFalse(
"Content instance should not have been eagerly destroyed before stopping the component",
ScopeCompositeImpl.eagerdestroy);
Fractal.getLifeCycleController(c).stopFc();
Assert.assertTrue(
"Content instance should have been eagerly destroyed",
ScopeCompositeImpl.eagerdestroy);
}
@Test
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment