Source code: org/apache/axis/AxisProperties.java
1 /*
2 * Copyright 2001-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.axis;
18
19 import org.apache.axis.components.logger.LogFactory;
20 import org.apache.axis.utils.Messages;
21 import org.apache.commons.discovery.ResourceClassIterator;
22 import org.apache.commons.discovery.ResourceNameDiscover;
23 import org.apache.commons.discovery.ResourceNameIterator;
24 import org.apache.commons.discovery.resource.ClassLoaders;
25 import org.apache.commons.discovery.resource.classes.DiscoverClasses;
26 import org.apache.commons.discovery.resource.names.DiscoverMappedNames;
27 import org.apache.commons.discovery.resource.names.DiscoverNamesInAlternateManagedProperties;
28 import org.apache.commons.discovery.resource.names.DiscoverNamesInManagedProperties;
29 import org.apache.commons.discovery.resource.names.DiscoverServiceNames;
30 import org.apache.commons.discovery.resource.names.NameDiscoverers;
31 import org.apache.commons.discovery.tools.ClassUtils;
32 import org.apache.commons.discovery.tools.DefaultClassHolder;
33 import org.apache.commons.discovery.tools.DiscoverClass;
34 import org.apache.commons.discovery.tools.ManagedProperties;
35 import org.apache.commons.discovery.tools.PropertiesHolder;
36 import org.apache.commons.discovery.tools.SPInterface;
37 import org.apache.commons.logging.Log;
38
39 import java.lang.reflect.InvocationTargetException;
40 import java.security.AccessController;
41 import java.security.PrivilegedAction;
42 import java.util.Enumeration;
43 import java.util.Map;
44 import java.util.Properties;
45
46
47 /**
48 * <p>Configuration properties for AXIS.
49 * </p>
50 *
51 * <p>Manage configuration properties according to a secure
52 * scheme similar to that used by classloaders:
53 * <ul>
54 * <li><code>ClassLoader</code>s are organized in a tree hierarchy.</li>
55 * <li>each <code>ClassLoader</code> has a reference
56 * to a parent <code>ClassLoader</code>.</li>
57 * <li>the root of the tree is the bootstrap <code>ClassLoader</code>er.</li>
58 * <li>the youngest decendent is the thread context class loader.</li>
59 * <li>properties are bound to a <code>ClassLoader</code> instance
60 * <ul>
61 * <li><i>non-default</i> properties bound to a parent <code>ClassLoader</code>
62 * instance take precedence over all properties of the same name bound
63 * to any decendent.
64 * Just to confuse the issue, this is the default case.</li>
65 * <li><i>default</i> properties bound to a parent <code>ClassLoader</code>
66 * instance may be overriden by (default or non-default) properties of
67 * the same name bound to any decendent.
68 * </li>
69 * </ul>
70 * </li>
71 * <li>System properties take precedence over all other properties</li>
72 * </ul>
73 * </p>
74 *
75 * @author Richard A. Sitze
76 */
77 public class AxisProperties {
78 /** The <code>Log</code> for all interesting events in this class. */
79 protected static Log log =
80 LogFactory.getLog(AxisProperties.class.getName());
81
82 private static DiscoverNamesInAlternateManagedProperties altNameDiscoverer;
83 private static DiscoverMappedNames mappedNames;
84 private static NameDiscoverers nameDiscoverer;
85 private static ClassLoaders loaders;
86
87 public static void setClassOverrideProperty(Class clazz, String propertyName) {
88 getAlternatePropertyNameDiscoverer()
89 .addClassToPropertyNameMapping(clazz.getName(), propertyName);
90 }
91
92 public static void setClassDefault(Class clazz, String defaultName) {
93 getMappedNames().map(clazz.getName(), defaultName);
94 }
95
96 public static void setClassDefaults(Class clazz, String[] defaultNames) {
97 getMappedNames().map(clazz.getName(), defaultNames);
98 }
99
100 public static synchronized ResourceNameDiscover getNameDiscoverer() {
101 if (nameDiscoverer == null) {
102 nameDiscoverer = new NameDiscoverers();
103 nameDiscoverer.addResourceNameDiscover(getAlternatePropertyNameDiscoverer());
104 nameDiscoverer.addResourceNameDiscover(new DiscoverNamesInManagedProperties());
105 nameDiscoverer.addResourceNameDiscover(new DiscoverServiceNames(getClassLoaders()));
106 nameDiscoverer.addResourceNameDiscover(getMappedNames());
107 }
108 return nameDiscoverer;
109 }
110
111 public static ResourceClassIterator getResourceClassIterator(Class spi) {
112 ResourceNameIterator it = getNameDiscoverer().findResourceNames(spi.getName());
113 return new DiscoverClasses(loaders).findResourceClasses(it);
114 }
115
116 private static synchronized ClassLoaders getClassLoaders() {
117 if (loaders == null) {
118 loaders = ClassLoaders.getAppLoaders(AxisProperties.class, null, true);
119 }
120 return loaders;
121 }
122
123 private static synchronized DiscoverMappedNames getMappedNames() {
124 if (mappedNames == null) {
125 mappedNames = new DiscoverMappedNames();
126 }
127 return mappedNames;
128 }
129
130 private static synchronized DiscoverNamesInAlternateManagedProperties getAlternatePropertyNameDiscoverer() {
131 if (altNameDiscoverer == null) {
132 altNameDiscoverer = new DiscoverNamesInAlternateManagedProperties();
133 }
134
135 return altNameDiscoverer;
136 }
137
138 /**
139 * Create a new instance of a service provider class.
140 *
141 * !WARNING!
142 * SECURITY issue.
143 *
144 * See bug 11874
145 *
146 * The solution to both is to move doPrivilege UP within AXIS to a
147 * class that is either private (cannot be reached by code outside
148 * AXIS) or that represents a secure public interface...
149 *
150 * This is going to require analysis and (probably) rearchitecting.
151 * So, I'm taking taking the easy way out until we are at a point
152 * where we can reasonably rearchitect for security.
153 *
154 * @param spiClass the service provider class to instantiate
155 * @return a new instance of this class
156 */
157
158 public static Object newInstance(Class spiClass)
159 {
160 return newInstance(spiClass, null, null);
161 }
162
163 public static Object newInstance(final Class spiClass,
164 final Class constructorParamTypes[],
165 final Object constructorParams[]) {
166 return AccessController.doPrivileged(
167 new PrivilegedAction() {
168 public Object run() {
169 ResourceClassIterator services = getResourceClassIterator(spiClass);
170
171 Object obj = null;
172 while (obj == null && services.hasNext()) {
173 Class service = services.nextResourceClass().loadClass();
174
175 /* service == null
176 * if class resource wasn't loadable
177 */
178 if (service != null) {
179 /* OK, class loaded.. attempt to instantiate it.
180 */
181 try {
182 ClassUtils.verifyAncestory(spiClass, service);
183 obj = ClassUtils.newInstance(service, constructorParamTypes, constructorParams);
184 } catch (InvocationTargetException e) {
185 if (e.getTargetException() instanceof java.lang.NoClassDefFoundError) {
186 log.debug(Messages.getMessage("exception00"), e);
187 } else {
188 log.warn(Messages.getMessage("exception00"), e);
189 }
190 } catch (Exception e) {
191 log.warn(Messages.getMessage("exception00"), e);
192 }
193 }
194 }
195
196 return obj;
197 }
198 });
199 }
200
201
202 /**
203 * Get value for property bound to the current thread context class loader.
204 *
205 * @param propertyName property name.
206 * @return property value if found, otherwise default.
207 */
208 public static String getProperty(String propertyName) {
209 return ManagedProperties.getProperty(propertyName);
210 }
211
212 /**
213 * Get value for property bound to the current thread context class loader.
214 * If not found, then return default.
215 *
216 * @param propertyName property name.
217 * @param dephault default value.
218 * @return property value if found, otherwise default.
219 */
220 public static String getProperty(String propertyName, String dephault) {
221 return ManagedProperties.getProperty(propertyName, dephault);
222 }
223
224 /**
225 * Set value for property bound to the current thread context class loader.
226 * @param propertyName property name
227 * @param value property value (non-default) If null, remove the property.
228 */
229 public static void setProperty(String propertyName, String value) {
230 ManagedProperties.setProperty(propertyName, value);
231 }
232
233 /**
234 * Set value for property bound to the current thread context class loader.
235 * @param propertyName property name
236 * @param value property value. If null, remove the property.
237 * @param isDefault determines if property is default or not.
238 * A non-default property cannot be overriden.
239 * A default property can be overriden by a property
240 * (default or non-default) of the same name bound to
241 * a decendent class loader.
242 */
243 public static void setProperty(String propertyName, String value, boolean isDefault) {
244 ManagedProperties.setProperty(propertyName, value, isDefault);
245 }
246
247 /**
248 * Set property values for <code>Properties</code> bound to the
249 * current thread context class loader.
250 *
251 * @param newProperties name/value pairs to be bound
252 */
253 public static void setProperties(Map newProperties) {
254 ManagedProperties.setProperties(newProperties);
255 }
256
257
258 /**
259 * Set property values for <code>Properties</code> bound to the
260 * current thread context class loader.
261 *
262 * @param newProperties name/value pairs to be bound
263 * @param isDefault determines if properties are default or not.
264 * A non-default property cannot be overriden.
265 * A default property can be overriden by a property
266 * (default or non-default) of the same name bound to
267 * a decendent class loader.
268 */
269 public static void setProperties(Map newProperties, boolean isDefault) {
270 ManagedProperties.setProperties(newProperties, isDefault);
271 }
272
273
274 public static Enumeration propertyNames() {
275 return ManagedProperties.propertyNames();
276 }
277
278 /**
279 * This is an expensive operation.
280 *
281 * @return Returns a <code>java.util.Properties</code> instance
282 * that is equivalent to the current state of the scoped
283 * properties, in that getProperty() will return the same value.
284 * However, this is a copy, so setProperty on the
285 * returned value will not effect the scoped properties.
286 */
287 public static Properties getProperties() {
288 return ManagedProperties.getProperties();
289 }
290
291
292 public static Object newInstance(Class spiClass, Class defaultClass)
293 {
294 return newInstance(new SPInterface(spiClass), new DefaultClassHolder(defaultClass));
295 }
296
297 /**
298 * !WARNING!
299 * SECURITY issue.
300 *
301 * See bug 11874
302 *
303 * The solution to both is to move doPrivilege UP within AXIS to a
304 * class that is either private (cannot be reached by code outside
305 * AXIS) or that represents a secure public interface...
306 *
307 * This is going to require analysis and (probably) rearchitecting.
308 * So, I'm taking taking the easy way out until we are at a point
309 * where we can reasonably rearchitect for security.
310 */
311 private static Object newInstance(final SPInterface spi,
312 final DefaultClassHolder defaultClass)
313 {
314 return AccessController.doPrivileged(
315 new PrivilegedAction() {
316 public Object run() {
317 try {
318 return DiscoverClass.newInstance(null,
319 spi,
320 (PropertiesHolder)null,
321 defaultClass);
322 } catch (Exception e) {
323 log.error(Messages.getMessage("exception00"), e);
324 }
325 return null;
326 }
327 });
328 }
329 }