Home » geronimo-2.2-source-release » org.apache.geronimo.gbean.runtime » [javadoc | source]

    1   /**
    2    *  Licensed to the Apache Software Foundation (ASF) under one or more
    3    *  contributor license agreements.  See the NOTICE file distributed with
    4    *  this work for additional information regarding copyright ownership.
    5    *  The ASF licenses this file to You under the Apache License, Version 2.0
    6    *  (the "License"); you may not use this file except in compliance with
    7    *  the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    *  Unless required by applicable law or agreed to in writing, software
   12    *  distributed under the License is distributed on an "AS IS" BASIS,
   13    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    *  See the License for the specific language governing permissions and
   15    *  limitations under the License.
   16    */
   17   
   18   package org.apache.geronimo.gbean.runtime;
   19   
   20   import org.apache.geronimo.gbean.DynamicGAttributeInfo;
   21   import org.apache.geronimo.gbean.DynamicGBean;
   22   import org.apache.geronimo.gbean.GAttributeInfo;
   23   import org.apache.geronimo.gbean.InvalidConfigurationException;
   24   import org.apache.geronimo.gbean.annotation.EncryptionSetting;
   25   import org.apache.geronimo.kernel.ClassLoading;
   26   
   27   import java.lang.reflect.Method;
   28   
   29   /**
   30    * @version $Rev: 798794 $ $Date: 2009-07-28 23:54:50 -0700 (Tue, 28 Jul 2009) $
   31    */
   32   public class GBeanAttribute {
   33       private final GBeanInstance gbeanInstance;
   34   
   35       private final String name;
   36   
   37       private final Class type;
   38   
   39       private final boolean readable;
   40   
   41       private final MethodInvoker getInvoker;
   42   
   43       private final boolean writable;
   44   
   45       private final MethodInvoker setInvoker;
   46   
   47       private final boolean persistent;
   48   
   49       private final boolean manageable;
   50   
   51       private final EncryptionSetting encrypted;
   52   
   53       private Object persistentValue;
   54       /**
   55        * Is this a special attribute like objectName, classLoader or gbeanContext?
   56        * Special attributes are injected at startup just like persistent attrubutes, but are
   57        * otherwise unmodifiable.
   58        */
   59       private final boolean special;
   60   
   61       private final boolean framework;
   62   
   63       private final boolean dynamic;
   64   
   65       private final GAttributeInfo attributeInfo;
   66   
   67       static GBeanAttribute createSpecialAttribute(GBeanAttribute attribute, GBeanInstance gbeanInstance, String name, Class type, Object value) {
   68           return new GBeanAttribute(attribute, gbeanInstance, name, type, value);
   69       }
   70   
   71       private GBeanAttribute(GBeanAttribute attribute, GBeanInstance gbeanInstance, String name, Class type, Object value) {
   72           this.special = true;
   73           this.persistentValue = value;
   74   
   75           this.framework = false;
   76           this.dynamic = false;
   77   
   78           if (gbeanInstance == null || name == null || type == null) {
   79               throw new IllegalArgumentException("null param(s) supplied");
   80           }
   81   
   82           // if we have an attribute verify the gbean instance, name and types match
   83           if (attribute != null) {
   84               assert (gbeanInstance == attribute.gbeanInstance);
   85               assert (name.equals(attribute.name));
   86               if (type != attribute.type) {
   87                   throw new InvalidConfigurationException("Special attribute " + name +
   88                           " must have the type " + type.getName() + ", but is " +
   89                           attribute.type.getName() + ": targetClass=" + gbeanInstance.getType().getName());
   90               }
   91               if (attribute.isPersistent()) {
   92                   throw new InvalidConfigurationException("Special attributes must not be persistent:" +
   93                           " name=" + name + ", targetClass=" + gbeanInstance.getType().getName());
   94               }
   95           }
   96   
   97           this.gbeanInstance = gbeanInstance;
   98           this.name = name;
   99           this.type = type;
  100   
  101           // getter
  102           this.getInvoker = null;
  103           this.readable = true;
  104   
  105           // setter
  106           if (attribute != null) {
  107               this.setInvoker = attribute.setInvoker;
  108           } else {
  109               this.setInvoker = null;
  110           }
  111           this.writable = false;
  112   
  113           // persistence
  114           this.persistent = false;
  115   
  116           // not manageable
  117           this.manageable = false;
  118   
  119           // special attributes are not encrypted
  120           this.encrypted = EncryptionSetting.PLAINTEXT;
  121   
  122           // create an attribute info for this gbean
  123           if (attribute != null) {
  124               GAttributeInfo attributeInfo = attribute.getAttributeInfo();
  125               this.attributeInfo = new GAttributeInfo(this.name,
  126                       this.type.getName(),
  127                       this.persistent,
  128                       this.manageable,
  129                       this.encrypted,
  130                       this.readable,
  131                       this.writable,
  132                       attributeInfo.getGetterName(),
  133                       attributeInfo.getSetterName());
  134           } else {
  135               this.attributeInfo = new GAttributeInfo(this.name,
  136                       this.type.getName(),
  137                       this.persistent,
  138                       this.manageable,
  139                       this.encrypted,
  140                       this.readable,
  141                       this.writable,
  142                       null,
  143                       null);
  144           }
  145       }
  146   
  147       static GBeanAttribute createFrameworkAttribute(GBeanInstance gbeanInstance, String name, Class type, MethodInvoker getInvoker) {
  148           return new GBeanAttribute(gbeanInstance, name, type, getInvoker, null, false, null, true);
  149       }
  150   
  151       static GBeanAttribute createFrameworkAttribute(GBeanInstance gbeanInstance, String name, Class type, MethodInvoker getInvoker, MethodInvoker setInvoker, boolean persistent, Object persistentValue, boolean manageable) {
  152           return new GBeanAttribute(gbeanInstance, name, type, getInvoker, setInvoker, persistent, persistentValue, manageable);
  153       }
  154   
  155       private GBeanAttribute(GBeanInstance gbeanInstance, String name, Class type, MethodInvoker getInvoker, MethodInvoker setInvoker, boolean persistent, Object persistentValue, boolean manageable) {
  156           this.special = false;
  157           this.framework = true;
  158           this.dynamic = false;
  159   
  160           if (gbeanInstance == null || name == null || type == null) {
  161               throw new IllegalArgumentException("null param(s) supplied");
  162           }
  163   
  164           this.gbeanInstance = gbeanInstance;
  165           this.name = name;
  166           this.type = type;
  167   
  168           // getter
  169           this.getInvoker = getInvoker;
  170           this.readable = (this.getInvoker != null);
  171   
  172           // setter
  173           this.setInvoker = setInvoker;
  174           this.writable = (this.setInvoker != null);
  175   
  176           // persistence
  177           this.persistent = persistent;
  178   
  179           // manageable
  180           this.manageable = manageable;
  181   
  182           // create an attribute info for this gbean
  183           attributeInfo = new GAttributeInfo(this.name,
  184                   this.type.getName(),
  185                   this.persistent,
  186                   this.manageable,
  187                   this.readable,
  188                   this.writable,
  189                   null,
  190                   null);
  191   
  192           this.encrypted = attributeInfo.getEncryptedSetting();
  193           this.persistentValue = encrypted.decrypt(persistentValue);
  194       }
  195   
  196       public GBeanAttribute(GBeanInstance gbeanInstance, GAttributeInfo attributeInfo) throws InvalidConfigurationException {
  197           this.special = false;
  198           this.framework = false;
  199   
  200           if (gbeanInstance == null || attributeInfo == null) {
  201               throw new IllegalArgumentException("null param(s) supplied");
  202           }
  203           this.gbeanInstance = gbeanInstance;
  204           this.attributeInfo = attributeInfo;
  205           this.name = attributeInfo.getName();
  206           try {
  207               this.type = ClassLoading.loadClass(attributeInfo.getType(), gbeanInstance.getClassLoader());
  208           } catch (ClassNotFoundException e) {
  209               throw new InvalidConfigurationException("Could not load attribute class: " + attributeInfo.getType(), e);
  210           }
  211           this.persistent = attributeInfo.isPersistent();
  212           this.manageable = attributeInfo.isManageable();
  213           this.encrypted = attributeInfo.getEncryptedSetting();
  214   
  215           readable = attributeInfo.isReadable();
  216           writable = attributeInfo.isWritable();
  217   
  218           // If attribute is persistent or not tagged as unreadable, search for a
  219           // getter method
  220           if (attributeInfo instanceof DynamicGAttributeInfo) {
  221               this.dynamic = true;
  222               if (readable) {
  223                   getInvoker = new DynamicGetterMethodInvoker(name);
  224               } else {
  225                   getInvoker = null;
  226               }
  227               if (writable) {
  228                   setInvoker = new DynamicSetterMethodInvoker(name);
  229               } else {
  230                   setInvoker = null;
  231               }
  232           } else {
  233               this.dynamic = false;
  234               if (attributeInfo.getGetterName() != null) {
  235                   try {
  236                       String getterName = attributeInfo.getGetterName();
  237                       Method getterMethod = gbeanInstance.getType().getMethod(getterName, null);
  238   
  239                       if (!getterMethod.getReturnType().equals(type)) {
  240                           if (getterMethod.getReturnType().getName().equals(type.getName())) {
  241                               throw new InvalidConfigurationException("Getter return type in wrong classloader: type: " + type + " wanted in classloader: " + type.getClassLoader() + " actual: " + getterMethod.getReturnType().getClassLoader());
  242                           } else {
  243                               throw new InvalidConfigurationException("Getter method of wrong type: " + getterMethod.getReturnType() + " expected " + getDescription());
  244                           }
  245                       }
  246                       if (AbstractGBeanReference.NO_PROXY) {
  247                           getInvoker = new ReflectionMethodInvoker(getterMethod);
  248                       } else {
  249                           getInvoker = new FastMethodInvoker(getterMethod);
  250                       }
  251                   } catch (NoSuchMethodException e) {
  252                       throw new InvalidConfigurationException("Getter method not found " + getDescription(), e);
  253                   }
  254               } else {
  255                   getInvoker = null;
  256               }
  257   
  258               // If attribute is persistent or not tagged as unwritable, search for a setter method
  259               if (attributeInfo.getSetterName() != null) {
  260                   try {
  261                       String setterName = attributeInfo.getSetterName();
  262                       Method setterMethod = gbeanInstance.getType().getMethod(setterName, new Class[]{type});
  263                       if (AbstractGBeanReference.NO_PROXY) {
  264                           setInvoker = new ReflectionMethodInvoker(setterMethod);
  265                       } else {
  266                           setInvoker = new FastMethodInvoker(setterMethod);
  267                       }
  268                   } catch (NoSuchMethodException e) {
  269                       throw new InvalidConfigurationException("Setter method not found " + getDescription(), e);
  270                   }
  271               } else {
  272                   setInvoker = null;
  273               }
  274           }
  275       }
  276   
  277       public String getName() {
  278           return name;
  279       }
  280   
  281       public GAttributeInfo getAttributeInfo() {
  282           return attributeInfo;
  283       }
  284   
  285       public boolean isReadable() {
  286           return readable;
  287       }
  288   
  289       public boolean isWritable() {
  290           return writable;
  291       }
  292   
  293       public Class getType() {
  294           return type;
  295       }
  296   
  297       public boolean isFramework() {
  298           return framework;
  299       }
  300   
  301       public boolean isDynamic() {
  302           return dynamic;
  303       }
  304   
  305       public boolean isPersistent() {
  306           return persistent;
  307       }
  308   
  309       public boolean isManageable() {
  310           return manageable;
  311       }
  312   
  313       public boolean isEncrypted() {
  314           return encrypted == EncryptionSetting.ENCRYPTED;
  315       }
  316   
  317       public EncryptionSetting getEncryptionSetting() {
  318           return encrypted;
  319       }
  320   
  321       public boolean isSpecial() {
  322           return special;
  323       }
  324   
  325       public Object getPersistentValue() {
  326           if (!persistent && !special) {
  327               throw new IllegalStateException("Attribute is not persistent " + getDescription());
  328           }
  329           return persistentValue;
  330       }
  331   
  332       public void setPersistentValue(Object persistentValue) {
  333           if (!persistent && !special) {
  334               throw new IllegalStateException("Attribute is not persistent " + getDescription());
  335           }
  336   
  337           if (persistentValue == null && type.isPrimitive()) {
  338               throw new IllegalArgumentException("Cannot assign null to a primitive attribute. " + getDescription());
  339           }
  340   
  341           // @todo actually check type
  342           this.persistentValue = encrypted.decrypt(persistentValue);
  343       }
  344   
  345       public Object getValue(Object target) throws Exception {
  346           if (!readable) {
  347               if (persistent) {
  348                   return persistentValue;
  349               } else {
  350                   throw new IllegalStateException("This attribute is not readable. " + getDescription());
  351               }
  352           }
  353   
  354           if (special) {
  355               return persistentValue;
  356           }
  357   
  358           // get the target to invoke
  359           if (target == null && !framework) {
  360               throw new IllegalStateException("GBean does not have a target instance to invoke. " + getDescription());
  361           }
  362   
  363           // call the getter
  364           Object value = getInvoker.invoke(target, null);
  365           return value;
  366       }
  367   
  368       public void setValue(Object target, Object value) throws Exception {
  369           if (!writable) {
  370               if (persistent) {
  371                   throw new IllegalStateException("This persistent attribute is not modifable while the gbean is running. " + getDescription());
  372               } else {
  373                   throw new IllegalStateException("This attribute is not writable. " + getDescription());
  374               }
  375           }
  376   
  377           // the value can not be null for primitives
  378           if (value == null && type.isPrimitive()) {
  379               throw new IllegalArgumentException("Cannot assign null to a primitive attribute. " + getDescription());
  380           }
  381   
  382           // @todo actually check type
  383   
  384           // get the target to invoke
  385           if (target == null && !framework) {
  386               throw new IllegalStateException("GBean does not have a target instance to invoke. " + getDescription());
  387           }
  388   
  389           // call the setter
  390           value = encrypted.decrypt(value);
  391           setInvoker.invoke(target, new Object[]{value});
  392       }
  393   
  394       public String getDescription() {
  395           return "Attribute Name: " + getName() + ", Type: " + getType() + ", GBeanInstance: " + gbeanInstance.getName();
  396       }
  397   
  398       private static final class DynamicGetterMethodInvoker implements MethodInvoker {
  399           private final String name;
  400   
  401           public DynamicGetterMethodInvoker(String name) {
  402               this.name = name;
  403           }
  404   
  405           public Object invoke(Object target, Object[] arguments) throws Exception {
  406               return ((DynamicGBean) target).getAttribute(name);
  407           }
  408       }
  409   
  410       private static final class DynamicSetterMethodInvoker implements MethodInvoker {
  411           private final String name;
  412   
  413           public DynamicSetterMethodInvoker(String name) {
  414               this.name = name;
  415           }
  416   
  417           public Object invoke(Object target, Object[] arguments) throws Exception {
  418               ((DynamicGBean) target).setAttribute(name, arguments[0]);
  419               return null;
  420           }
  421       }
  422   
  423       public void inject(Object target) throws Exception {
  424           if ((persistent || special) && writable && null != persistentValue) {
  425               setValue(target, persistentValue);
  426           }
  427       }
  428   
  429   }

Home » geronimo-2.2-source-release » org.apache.geronimo.gbean.runtime » [javadoc | source]