1 /*
2 * ====================================================================
3 *
4 * The Apache Software License, Version 1.1
5 *
6 * Copyright (c) 1999-2002 The Apache Software Foundation. All rights
7 * reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. The end-user documentation included with the redistribution, if
22 * any, must include the following acknowlegement:
23 * "This product includes software developed by the
24 * Apache Software Foundation (http://www.apache.org/)."
25 * Alternately, this acknowlegement may appear in the software itself,
26 * if and wherever such third-party acknowlegements normally appear.
27 *
28 * 4. The names "The Jakarta Project", "Commons", and "Apache Software
29 * Foundation" must not be used to endorse or promote products derived
30 * from this software without prior written permission. For written
31 * permission, please contact apache@apache.org.
32 *
33 * 5. Products derived from this software may not be called "Apache"
34 * nor may "Apache" appear in their names without prior written
35 * permission of the Apache Group.
36 *
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This software consists of voluntary contributions made by many
52 * individuals on behalf of the Apache Software Foundation. For more
53 * information on the Apache Software Foundation, please see
54 * <http://www.apache.org/>.
55 *
56 */
57 package org.apache.commons.jelly.impl;
58
59 import org.apache.commons.discovery.ServiceDiscovery;
60 import org.apache.commons.discovery.ServiceInfo;
61
62 import org.apache.commons.jelly.TagLibrary;
63
64 import org.apache.commons.logging.Log;
65 import org.apache.commons.logging.LogFactory;
66
67
68 /***
69 * <p><code>DefaultTagLibraryResolver</code> is a default implemenation
70 * which attempts to interpret the URI as a String called 'jelly:className'
71 * and class load the given Java class. Otherwise META-INF/services/jelly/uri
72 * is searched for on the thread context's class path and, if found, that
73 * class will be loaded.</p>
74 *
75 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
76 * @version $Revision: 1.12 $
77 */
78 public class DefaultTagLibraryResolver implements TagLibraryResolver {
79
80 /*** The Log to which logging calls will be made. */
81 private static final Log log = LogFactory.getLog(DefaultTagLibraryResolver.class);
82
83 private ServiceDiscovery discovery;
84
85 /***
86 * The class loader to use for instantiating application objects.
87 * If not specified, the context class loader, or the class loader
88 * used to load this class itself, is used, based on the value of the
89 * <code>useContextClassLoader</code> variable.
90 */
91 private ClassLoader classLoader;
92
93 /***
94 * Do we want to use the Context ClassLoader when loading classes
95 * for instantiating new objects? Default is <code>false</code>.
96 */
97 private boolean useContextClassLoader = false;
98
99
100 public DefaultTagLibraryResolver() {
101 }
102
103
104 // TagLibraryResolver interface
105 //-------------------------------------------------------------------------
106
107 /***
108 * Attempts to resolve the given URI to be associated with a TagLibrary
109 * otherwise null is returned to indicate no tag library could be found
110 * so that the namespace URI should be treated as just vanilla XML.
111 */
112 public TagLibrary resolveTagLibrary(String uri) {
113 ServiceDiscovery discovery = getServiceDiscovery();
114 String name = uri;
115 if ( uri.startsWith( "jelly:" ) ) {
116 name = "jelly." + uri.substring(6);
117 }
118
119 log.info( "Looking up service name: " + name );
120
121 ServiceInfo[] infoArray = discovery.findServices(name);
122
123 if ( infoArray != null && infoArray.length > 0 ) {
124 for (int i = 0; i < infoArray.length; i++ ) {
125 ServiceInfo info = infoArray[i];
126 try {
127 Class typeClass = info.getLoader().loadClass( info.getImplName() );
128 if ( typeClass != null ) {
129 return newInstance(uri, typeClass);
130 }
131 }
132 catch (Exception e) {
133 log.error( "Could not load service: " + info.getImplName()
134 + " with loader: " + info.getLoader()
135 );
136 }
137 }
138 }
139 else {
140 log.info( "Could not find any services for name: " + name );
141 }
142 return null;
143 }
144
145 // Properties
146 //-------------------------------------------------------------------------
147
148 /***
149 * Return the class loader to be used for instantiating application objects
150 * when required. This is determined based upon the following rules:
151 * <ul>
152 * <li>The class loader set by <code>setClassLoader()</code>, if any</li>
153 * <li>The thread context class loader, if it exists and the
154 * <code>useContextClassLoader</code> property is set to true</li>
155 * <li>The class loader used to load the XMLParser class itself.
156 * </ul>
157 */
158 public ClassLoader getClassLoader() {
159 if (this.classLoader != null) {
160 return (this.classLoader);
161 }
162 if (this.useContextClassLoader) {
163 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
164 if (classLoader != null) {
165 return (classLoader);
166 }
167 }
168 return (this.getClass().getClassLoader());
169 }
170
171 /***
172 * Set the class loader to be used for instantiating application objects
173 * when required.
174 *
175 * @param classLoader The new class loader to use, or <code>null</code>
176 * to revert to the standard rules
177 */
178 public void setClassLoader(ClassLoader classLoader) {
179 this.classLoader = classLoader;
180 }
181
182 /***
183 * Return the boolean as to whether the context classloader should be used.
184 */
185 public boolean getUseContextClassLoader() {
186 return useContextClassLoader;
187 }
188
189 /***
190 * Determine whether to use the Context ClassLoader (the one found by
191 * calling <code>Thread.currentThread().getContextClassLoader()</code>)
192 * to resolve/load classes. If not
193 * using Context ClassLoader, then the class-loading defaults to
194 * using the calling-class' ClassLoader.
195 *
196 * @param boolean determines whether to use JellyContext ClassLoader.
197 */
198 public void setUseContextClassLoader(boolean use) {
199 useContextClassLoader = use;
200 }
201
202 /***
203 * @return the ServiceDiscovery instance to use to locate services.
204 * This object is lazily created if it has not been configured.
205 */
206 public ServiceDiscovery getServiceDiscovery() {
207 if ( discovery == null ) {
208 discovery = ServiceDiscovery.getServiceDiscovery();
209 discovery.addClassLoader( getClassLoader() );
210 }
211 return discovery;
212 }
213
214 /***
215 * Sets the fully configured ServiceDiscovery instance to be used to
216 * lookup services
217 */
218 public void setServiceDiscovery(ServiceDiscovery discovery) {
219 this.discovery = discovery;
220 }
221
222 // Implementation methods
223 //-------------------------------------------------------------------------
224
225 /***
226 * Instantiates the given class name. Otherwise an exception is logged
227 * and null is returned
228 */
229 protected TagLibrary loadClass(String uri, String className) {
230 try {
231 Class theClass = getClassLoader().loadClass(className);
232 if ( theClass != null ) {
233 return newInstance(uri, theClass);
234 }
235 }
236 catch (ClassNotFoundException e) {
237 log.error("Could not find the class: " + className + " when trying to resolve URI: " + uri, e);
238 }
239 return null;
240 }
241
242
243 /***
244 * Creates a new instance of the given TagLibrary class or
245 * return null if it could not be instantiated.
246 */
247 protected TagLibrary newInstance(String uri, Class theClass) {
248 try {
249 Object object = theClass.newInstance();
250 if (object instanceof TagLibrary) {
251 return (TagLibrary) object;
252 }
253 else {
254 log.error(
255 "The tag library object mapped to: "
256 + uri
257 + " is not a TagLibrary. Object = "
258 + object);
259 }
260 }
261 catch (Exception e) {
262 log.error(
263 "Could not instantiate instance of class: " + theClass.getName() + ". Reason: " + e,
264 e);
265 }
266 return null;
267 }
268
269 }
This page was automatically generated by Maven