View Javadoc

1   /*
2    * Copyright 2002,2004 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.apache.commons.jelly.tags.bean;
18  
19  import java.lang.reflect.Method;
20  import java.util.HashMap;
21  import java.util.Map;
22  
23  import org.apache.commons.beanutils.MethodUtils;
24  import org.apache.commons.jelly.JellyTagException;
25  import org.apache.commons.jelly.MissingAttributeException;
26  import org.apache.commons.jelly.TagSupport;
27  import org.apache.commons.jelly.XMLOutput;
28  import org.apache.commons.jelly.util.ClassLoaderUtils;
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  
32  
33  /***
34   * Binds a Java bean to the given named Jelly tag so that the attributes of
35   * the tag set the bean properties..
36   *
37   * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
38   * @version $Revision: 155420 $
39   */
40  public class BeandefTag extends TagSupport {
41  
42      /*** The Log to which logging calls will be made. */
43      private static final Log log = LogFactory.getLog(BeandefTag.class);
44  
45      /*** An empty Map as I think Collections.EMPTY_MAP is only JDK 1.3 onwards */
46      private static final Map EMPTY_MAP = new HashMap();
47  
48      protected static final Class[] EMPTY_ARGUMENT_TYPES = {};
49  
50      /*** the name of the tag to create */
51      private String name;
52  
53      /*** the Java class name to use for the tag */
54      private String className;
55  
56      /*** the name of the invoke method */
57      private String methodName;
58  
59      /*** the ClassLoader used to load beans */
60      private ClassLoader classLoader;
61  
62      /*** the library in which to define this new bean tag */
63      private BeanTagLibrary library;
64  
65      public BeandefTag(BeanTagLibrary library) {
66          this.library = library;
67      }
68  
69      // Tag interface
70      //-------------------------------------------------------------------------
71      public void doTag(XMLOutput output) throws MissingAttributeException, JellyTagException {
72          invokeBody(output);
73  
74          if (name == null) {
75              throw new MissingAttributeException("name");
76          }
77          if (className == null) {
78              throw new MissingAttributeException("className");
79          }
80  
81          Class theClass = null;
82          try {
83              theClass = ClassLoaderUtils.loadClass(className, classLoader, getContext().getUseContextClassLoader(), getClass());
84          } catch (ClassNotFoundException e) {
85              log.error( "Could not load class: " + className + " exception: " + e, e );
86              throw new JellyTagException("Could not find class: "
87                      + className
88                      + " using ClassLoader: "
89                      + classLoader);
90          }
91  
92          Method invokeMethod = getInvokeMethod(theClass);
93  
94          // @todo should we allow the variable name to be specified?
95          library.registerBean(name, theClass, invokeMethod);
96      }
97  
98  
99      // Properties
100     //-------------------------------------------------------------------------
101 
102     /***
103      * Sets the name of the tag to create
104      */
105     public void setName(String name) {
106         this.name = name;
107     }
108 
109     /***
110      * Sets the Java class name to use for the tag
111      */
112     public void setClassName(String className) {
113         this.className = className;
114     }
115 
116     /***
117      * Sets the ClassLoader to use to load the class.
118      * If no value is set then the current threads context class
119      * loader is used.
120      */
121     public void setClassLoader(ClassLoader classLoader) {
122         this.classLoader = classLoader;
123     }
124 
125     /***
126      * @return the ClassLoader to use to load classes
127      *  or will use the thread context loader if none is specified.
128      */
129     public ClassLoader getClassLoader() {
130         return ClassLoaderUtils.getClassLoader(classLoader, true, getClass());
131     }
132 
133     /***
134      * @return String
135      */
136     public String getMethodName() {
137         return methodName;
138     }
139 
140     /***
141      * Sets the methodName.
142      * @param methodName The methodName to set
143      */
144     public void setMethodName(String methodName) {
145         this.methodName = methodName;
146     }
147 
148     // Implementation methods
149     //-------------------------------------------------------------------------
150     protected Method getInvokeMethod(Class theClass) {
151         if (methodName != null) {
152             // lets lookup the method name
153             return MethodUtils.getAccessibleMethod(theClass, methodName, EMPTY_ARGUMENT_TYPES);
154         }
155         return null;
156     }
157 }