Commit 669420d2 authored by Lionel Seinturier's avatar Lionel Seinturier
Browse files

Check that the content class implements the server interfaces.

parent cceeebb5
/***
* OW2 FraSCAti Tinfi
* Copyright (C) 2012 Inria, Univ. Lille 1
*
* 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.control.content;
import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.api.Type;
import org.objectweb.fractal.api.control.IllegalLifeCycleException;
import org.objectweb.fractal.api.type.ComponentType;
import org.objectweb.fractal.api.type.InterfaceType;
import org.ow2.frascati.tinfi.api.control.ContentInstantiationException;
import org.ow2.frascati.tinfi.api.control.SCAContentController;
/**
* Type checking management.
*
* @author Lionel Seinturier <Lionel.Seinturier@univ-lille1.fr>
* @since 1.4.5
*/
public abstract class TypeCheckSCAContentMixin
implements SCAContentController {
// -------------------------------------------------------------------------
// Implementation of the SCAContentController interface
// -------------------------------------------------------------------------
public void setFcContentClass( Class<?> c )
throws IllegalLifeCycleException, ContentInstantiationException {
Type type = _this_weaveableC.getFcType();
checkType(type,c);
_super_setFcContentClass(c);
}
public void setFcContent( Object content )
throws IllegalLifeCycleException, ContentInstantiationException {
Type type = _this_weaveableC.getFcType();
Class<?> cl = content.getClass();
checkType(type,cl);
_super_setFcContent(content);
}
// -------------------------------------------------------------------------
// Implementation specific
// -------------------------------------------------------------------------
private void checkType( Type type, Class<?> contentClass )
throws ContentInstantiationException {
/*
* Check that the content class implements the server interfaces.
*/
ComponentType ct = (ComponentType) type;
InterfaceType[] its = ct.getFcInterfaceTypes();
for (InterfaceType it : its) {
// Skip client interfaces
if( it.isFcClientItf() ) {
continue;
}
// Skip control interfaces
String name = it.getFcItfName();
if( name.equals("component") || name.endsWith("-controller") ) {
continue;
}
/*
* Workaround since Object.class.getClassLoader() returns null.
* Object.class as a content class is not a priori a useful case,
* but it uses it in test cases, and anyway the workaround is needed
* if Object.class is used elsewhere.
*/
String signature = it.getFcItfSignature();
if( contentClass.equals(Object.class) ) {
String msg =
"Object.class is not adequate since the content class "+
"should implement "+signature;
throw new ContentInstantiationException(msg);
}
// Check that the class implements the server interface
Class<?> cl = load(contentClass,signature);
if( ! cl.isAssignableFrom(contentClass) ) {
String msg = contentClass+" should implement "+signature;
throw new ContentInstantiationException(msg);
}
}
}
/**
* Load the class whose name is specified with the class loader of the
* specified class.
*
* @param main the class used to retrieve the class loader
* @param name the name of the class to load
* @throws ContentInstantiationException if the class cannot be loader
*/
private Class<?> load( Class<?> main, String name )
throws ContentInstantiationException {
ClassLoader loader = main.getClassLoader();
try {
return loader.loadClass(name);
}
catch( ClassNotFoundException cnfe ) {
throw new ContentInstantiationException(cnfe);
}
}
// -------------------------------------------------------------------------
// Fields and methods required by the mixin class in the base class
// -------------------------------------------------------------------------
protected abstract void _super_setFcContentClass(Class<?> c)
throws IllegalLifeCycleException, ContentInstantiationException;
protected abstract void _super_setFcContent(Object content)
throws IllegalLifeCycleException, ContentInstantiationException;
private Component _this_weaveableC;
}
......@@ -23,7 +23,9 @@
package org.ow2.frascati.tinfi.opt.oo;
import org.objectweb.fractal.api.factory.InstantiationException;
import org.objectweb.fractal.api.type.InterfaceType;
import org.objectweb.fractal.juliac.Utils;
import org.objectweb.fractal.juliac.visit.BlockSourceCodeVisitor;
import org.ow2.frascati.tinfi.TinfiComponentInterceptor;
......@@ -46,20 +48,41 @@ extends org.objectweb.fractal.juliac.opt.oo.InitializerOOCtrlClassGenerator {
@Override
protected void generateContentChecks( BlockSourceCodeVisitor mv ) {
// Indeed nothing
String ctrlDesc = membraneDesc.getDescriptor();
String contentClassName =
Utils.getContentClassName(ctrlDesc,contentDesc);
if( contentClassName != null ) {
InterfaceType[] its = ct.getFcInterfaceTypes();
for (int i = 0; i < its.length; i++) {
if( ! its[i].isFcClientItf() ) {
String signature = its[i].getFcItfSignature();
BlockSourceCodeVisitor then =
mv.visitIf(
"!",signature,".class.isAssignableFrom(",
contentClassName,".class)");
then.visitVar(
"String","msg","\""+contentClassName,"should implement",
signature+"\"");
then.visitIns(
"throw","new",
InstantiationException.class.getName()+"(msg)");
then.visitEnd();
}
}
}
}
@Override
public void generateInitializationContextForContent( BlockSourceCodeVisitor mv ) {
mv.visit(" ic.content = ");
if( contentDesc == null ) {
mv.visit("null");
}
else {
mv.visit(contentDesc.toString());
mv.visit(".class");
}
mv.visitln(";");
public void generateInitializationContextForContent(
BlockSourceCodeVisitor mv ) {
mv.visitSet(
"ic.content",
contentDesc==null ?
"null" :
(contentDesc.toString()+".class") );
}
@Override
......
......@@ -56,6 +56,7 @@ import org.ow2.frascati.tinfi.control.content.LifeCycleSCAContentMixin;
import org.ow2.frascati.tinfi.control.content.RequestContextSCAContentMixin;
import org.ow2.frascati.tinfi.control.content.SCAContentControllerMixin;
import org.ow2.frascati.tinfi.control.content.SCAExtendedContentController;
import org.ow2.frascati.tinfi.control.content.TypeCheckSCAContentMixin;
import org.ow2.frascati.tinfi.control.content.UseSCAContentControllerMixin;
import org.ow2.frascati.tinfi.control.intent.LifeCycleIntentMixin;
import org.ow2.frascati.tinfi.control.intent.SCABasicIntentControllerMixin;
......@@ -194,6 +195,7 @@ public class SCAPrimitive {
RequestContextSCAContentMixin.class,
UseComponentMixin.class,
SCAContentControllerMixin.class,
TypeCheckSCAContentMixin.class,
UseLifeCycleControllerMixin.class,
LifeCycleSCAContentMixin.class})
protected SCAExtendedContentController scacc;
......
......@@ -131,17 +131,20 @@ public class Util {
*/
public static void addAllFields( Class<?> cl, List<Field> list ) {
// Stop when java.lang.Object is reached
if( cl.equals(Object.class) ) {
return;
}
// Declared fields
Field[] fields = cl.getDeclaredFields();
for (Field field : fields) {
list.add(field);
}
// Recurse in the parent class up to java.lang.Object
// Recurse in the parent class
Class<?> supercl = cl.getSuperclass();
if( ! supercl.equals(Object.class) ) {
addAllFields(supercl,list);
}
addAllFields(supercl,list);
}
/**
......@@ -171,17 +174,20 @@ public class Util {
*/
public static void addAllMethods( Class<?> cl, List<Method> list ) {
// Stop when java.lang.Object is reached
if( cl.equals(Object.class) ) {
return;
}
// Declared methods
Method[] methods = cl.getDeclaredMethods();
for (Method method : methods) {
list.add(method);
}
// Recurse in the parent class up to java.lang.Object
// Recurse in the parent class
Class<?> supercl = cl.getSuperclass();
if( ! supercl.equals(Object.class) ) {
addAllMethods(supercl,list);
}
addAllMethods(supercl,list);
}
/**
......@@ -259,7 +265,12 @@ public class Util {
public static Annotation getAnnotation(
Class<?> cl, String... annotClassNames ) {
Annotation[] annots = cl.getAnnotations();
// No annotation on Object.class
if( cl.equals(Object.class) ) {
return null;
}
Annotation[] annots = cl.getAnnotations();
for (String annotClassName : annotClassNames) {
for (Annotation annot : annots) {
String name = annot.annotationType().getName();
......@@ -271,7 +282,7 @@ public class Util {
// Recurse in the parent class up to java.lang.Object
Class<?> supercl = cl.getSuperclass();
if( ! supercl.equals(Object.class) ) {
if( supercl!=null && !supercl.equals(Object.class) ) {
Annotation annot = getAnnotation(supercl,annotClassNames);
return annot;
}
......
......@@ -137,6 +137,34 @@ public class SCAContentControllerTestCase {
catch( IllegalLifeCycleException ilce ) {}
}
/**
* Test that when the content class of <code>scaPrimitive</code> components
* is changed, the new class implements the server interfaces.
*
* @since 1.4.5
*/
@Test
public void testSetContentClassImplementsServices()
throws IllegalLifeCycleException, NoSuchInterfaceException {
// Start and invoke the component once
Fractal.getLifeCycleController(client).startFc();
r.getContentClass();
// Reconfigure the content class
Fractal.getLifeCycleController(client).stopFc();
SCAContentController scacc = (SCAContentController)
client.getFcInterface(SCAContentController.NAME);
try {
scacc.setFcContentClass(Object.class);
String msg =
"Classes that do not implement server interfaces should not "+
"be allowed";
Assert.fail(msg);
}
catch( ContentInstantiationException cie ) {}
}
/**
* @since 1.4.3
*/
......@@ -219,4 +247,29 @@ public class SCAContentControllerTestCase {
}
catch( ContentInstantiationException cie ) {}
}
/**
* @since 1.4.5
*/
@Test
public void testSetContentImplementsServices()
throws IllegalLifeCycleException, NoSuchInterfaceException {
// Check that the component is instantiated with the regular content instance
String value = r.getProp();
Assert.assertEquals(SCAContentControllerImpl1.DEFAULT,value);
Fractal.getLifeCycleController(client).stopFc();
// Associate the ad hoc content instance with the component
SCAContentController scacc = (SCAContentController)
client.getFcInterface(SCAContentController.NAME);
try {
scacc.setFcContent(new Object());
String msg =
"Objects that do not implement server interfaces should not "+
"be allowed";
Assert.fail(msg);
}
catch( ContentInstantiationException cie ) {}
}
}
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