Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * 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.tuscany.sca.stripes;
 
 import java.util.Map;
 
 import  javax.servlet.ServletContext;
 
 import  net.sourceforge.stripes.action.ActionBeanContext;
 import  net.sourceforge.stripes.controller.StripesFilter;
 import  net.sourceforge.stripes.exception.StripesRuntimeException;
 import  net.sourceforge.stripes.util.Log;
 import  net.sourceforge.stripes.util.ReflectUtil;
 

Static helper class that is used to lookup SCA references and inject them into objects (often ActionBeans). Is capable of injecting references through setter methods (property access) and also through direct field access if the security policy allows it. Methods and fields must be annotated using the SCA @Reference annotation.

Methods and fields may be public, protected, package-access or private. If they are not public an attempt is made to call Method.setAccessible(boolean) in order to make them accessible from this class. If the attempt fails, an exception will be thrown.

Method names can take any form. For example setSomeBean(Bean b) or someBean(bean b). In both cases, if a specific Reference name is not supplied, the default name of someBean will be used.

The value of the @Reference annotation should be the reference on the SCA component with an <implementation.web> componentType.

The first time that any of the injection methods in this class is called with a specific type of object, the object's class is examined for annotated fields and methods. The discovered fields and methods are then cached for future usage.

Created for Tuscany from the Stripes SpringHelper written by Dan Hayes and Tim Fennell
 
 public class TuscanyHelper {
     private static final Log log = Log.getInstance(TuscanyHelper.class);

    
Lazily filled in map of Class to methods annotated with Reference.
 
     private static Map<Class<?>, Collection<Method>> methodMap =
             new ConcurrentHashMap<Class<?>, Collection<Method>>();

    
Lazily filled in map of Class to fields annotated with Reference.
 
     private static Map<Class<?>, Collection<Field>> fieldMap =
             new ConcurrentHashMap<Class<?>, Collection<Field>>();

    
Injects SCA References using the ComponentContext that is derived from the ServletContext, which is in turn looked up using the ActionBeanContext.

Parameters:
bean the object into which to inject SCA reference
context the ActionBeanContext represented by the current request
 
     public static void injectBeans(Object bean, ActionBeanContext context) {
         injectBeans(bean, StripesFilter.getConfiguration().getServletContext());
     }

    
Looks for all methods and fields annotated with @Reference and attempts to lookup and inject a managed bean into the field/property. If any annotated element cannot be injected an exception is thrown.

Parameters:
bean the bean into which to inject SCA reference
ctx the SCA ComponentContext
 
     public static void injectBeans(Object bean, ServletContext ctx) {
         // First inject any values using annotated methods
         for (Method m : getMethods(bean.getClass())) {
             try {
                 Reference scaReference = m.getAnnotation(Reference.class);
                 boolean nameSupplied = !"".equals(scaReference.name());
                String name = nameSupplied ? scaReference.name() : methodToPropertyName(m);
                Class<?> beanType = m.getParameterTypes()[0];
                Object managedBean = findReference(ctxnamebeanType, !nameSupplied);
                m.invoke(beanmanagedBean);
            }
            catch (Exception e) {
                throw new StripesRuntimeException("Exception while trying to lookup and inject " +
                    "an SCA Reference into a bean of type " + bean.getClass().getSimpleName() +
                    " using method " + m.toString(), e);
            }
        }
        // And then inject any properties that are annotated
        for (Field f : getFields(bean.getClass())) {
            try {
                Reference scaReference = f.getAnnotation(Reference.class);
                boolean nameSupplied = !"".equals(scaReference.name());
                String name = nameSupplied ? scaReference.name() : f.getName();
                Object managedBean = findReference(ctxnamef.getType(), !nameSupplied);
                f.set(beanmanagedBean);
            }
            catch (Exception e) {
                throw new StripesRuntimeException("Exception while trying to lookup and inject " +
                    "an SCA Referenceinto a bean of type " + bean.getClass().getSimpleName() +
                    " using field access on field " + f.toString(), e);
            }
        }
    }

    
Fetches the methods on a class that are annotated with Reference. The first time it is called for a particular class it will introspect the class and cache the results. All non-overridden methods are examined, including protected and private methods. If a method is not public an attempt it made to make it accessible - if it fails it is removed from the collection and an error is logged.

Parameters:
clazz the class on which to look for Reference annotated methods
Returns:
the collection of methods with the annotation
    protected static Collection<MethodgetMethods(Class<?> clazz) {
        Collection<Methodmethods = .get(clazz);
        if (methods == null) {
            methods = ReflectUtil.getMethods(clazz);
            Iterator<Methoditerator = methods.iterator();
            while (iterator.hasNext()) {
                Method method = iterator.next();
                if (!method.isAnnotationPresent(Reference.class)) {
                    iterator.remove();
                }
                else {
                    // If the method isn't public, try to make it accessible
                    if (!method.isAccessible()) {
                        try {
                            method.setAccessible(true);
                        }
                        catch (SecurityException se) {
                            throw new StripesRuntimeException(
                                "Method " + clazz.getName() + "." + method.getName() + "is marked " +
                                "with @Reference and is not public. An attempt to call " +
                                "setAccessible(true) resulted in a SecurityException. Please " +
                                "either make the method public or modify your JVM security " +
                                "policy to allow Stripes to setAccessible(true)."se);
                        }
                    }
                    // Ensure the method has only the one parameter
                    if (method.getParameterTypes().length != 1) {
                        throw new StripesRuntimeException(
                            "A method marked with @Reference must have exactly one parameter: " +
                            "the bean to be injected. Method [" + method.toGenericString() + "] has " +
                            method.getParameterTypes().length + " parameters."
                        );
                    }
                }
            }
            .put(clazzmethods);
        }
        return methods;
    }

    
Fetches the fields on a class that are annotated with Refernece. The first time it is called for a particular class it will introspect the class and cache the results. All non-overridden fields are examined, including protected and private fields. If a field is not public an attempt it made to make it accessible - if it fails it is removed from the collection and an error is logged.

Parameters:
clazz the class on which to look for Reference annotated fields
Returns:
the collection of methods with the annotation
    protected static Collection<FieldgetFields(Class<?> clazz) {
        Collection<Fieldfields = .get(clazz);
        if (fields == null) {
            fields = ReflectUtil.getFields(clazz);
            Iterator<Fielditerator = fields.iterator();
            while (iterator.hasNext()) {
                Field field = iterator.next();
                if (!field.isAnnotationPresent(Reference.class)) {
                    iterator.remove();
                }
                else if (!field.isAccessible()) {
                    // If the field isn't public, try to make it accessible
                    try {
                        field.setAccessible(true);
                    }
                    catch (SecurityException se) {
                        throw new StripesRuntimeException(
                            "Field " + clazz.getName() + "." + field.getName() + "is marked " +
                            "with @Reference and is not public. An attempt to call " +
                            "setAccessible(true) resulted in a SecurityException. Please " +
                            "either make the field public, annotate a public setter instead " +
                            "or modify your JVM security policy to allow Stripes to " +
                            "setAccessible(true)."se);
                    }
                }
            }
            .put(clazzfields);
        }
        return fields;
    }

    
Looks up an SCA Reference from a ComponentContext. First looks for a bean with name specified. If no such bean exists, looks for a bean by type. If there is only one bean of the appropriate type, it is returned. If zero or more than one bean of the correct type exists, an exception is thrown.

Parameters:
ctx the SCA ComponentContext
name the name of the reference to look for
type the type of bean to look for
allowFindByType true to indicate that finding a bean by type is acceptable if find by name fails.
Throws:
RuntimeException various subclasses of RuntimeException are thrown if it is not possible to find a unique matching bean in the ComponentContext given the constraints supplied.
    protected static Object findReference(ServletContext ctx,
                                           String name,
                                           Class<?> type,
                                           boolean allowFindByType) {
        // First try to lookup using the name provided
            Object bean =  ContextHelper.getReference(nametypectx);
            if (bean == null) {
                throw new StripesRuntimeException("no reference defined:" + name);
            }
            .debug("Found sca reference with name ["name"] and type [",
                      bean.getClass().getName(), "]");
            return bean;
// TODO: Support get by type (sca autowire?)            
            
//        // If we got here then we didn't find a bean yet, try by type
//        String[] beanNames = ctx.getBeanNamesForType(type);
//        if (beanNames.length == 0) {
//            throw new StripesRuntimeException(
//                "Unable to find SpringBean with name [" + name + "] or type [" +
//                type.getName() + "] in the Spring application context.");
//        }
//        else if (beanNames.length > 1) {
//            throw new StripesRuntimeException(
//                "Unable to find SpringBean with name [" + name + "] or unique bean with type [" +
//                type.getName() + "] in the Spring application context. Found " + beanNames.length +
//                "beans of matching type.");
//        }
//        else {
//            log.warn("Found unique SpringBean with type [" + type.getName() + "]. Matching on ",
//                     "type is a little risky so watch out!");
//            return ctx.getBean(beanNames[0], type);
//        }
    }

    
A slightly unusual, and somewhat "loose" conversion of a method name to a property name. Assumes that the name is in fact a mutator for a property and will do the usual setFoo to foo conversion if the method follows the normal syntax, otherwise will just return the method name.

Parameters:
m the method to determine the property name of
Returns:
a String property name
    protected static String methodToPropertyName(Method m) {
        String name = m.getName();
        if (name.startsWith("set") && name.length() > 3) {
            String ret = name.substring(3,4).toLowerCase();
            if (name.length() > 4) ret += name.substring(4);
            return ret;
        }
        else {
            return name;
        }
    }
New to GrepCode? Check out our FAQ X