1 /*
2 * $Id$
3 *
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21 package org.apache.struts.config;
22
23 import java.io.Serializable;
24
25 import java.util.Enumeration;
26 import java.util.Properties;
27
28 /**
29 * <p> A abstract base class for all config classes. Provide basic support
30 * for arbitrary properties </p>
31 *
32 * @since Struts 1.3
33 */
34 public abstract class BaseConfig implements Serializable {
35 private static final long serialVersionUID = 7059240587081363820L;
36
37 /**
38 * Indicates if configuration of this component been completed. TODO
39 * change protected to private and use methods provided by extenders?
40 */
41 protected boolean configured = false;
42
43 /**
44 * A map of arbitrary properties configured for this component.
45 *
46 * @since Struts 1.3
47 */
48 private Properties properties = new Properties();
49
50 /**
51 * Freeze the configuration of this action.
52 */
53 public void freeze() {
54 configured = true;
55 }
56
57 /**
58 * Throw <code>IllegalStateException</code> if configuration is frozen.
59 *
60 * @throws IllegalStateException if configuration is frozen
61 */
62 public void throwIfConfigured() {
63 if (configured) {
64 throw new IllegalStateException("Configuration is frozen");
65 }
66 }
67
68 /**
69 * <p> Set an arbitary key/value pair which can be retrieved by this
70 * config class. This facility should eliminate many use cases for
71 * subclassing <code>*Config</code> classes by providing a mechanism to
72 * pass any amount of arbitrary configuration information into an config
73 * class. <p /> This method must not be called after configuration is
74 * complete, or an <code>IllegalStateException</code> will be thrown.</p>
75 *
76 * <p><b>Example</b>
77 * <code><pre>
78 * <action path="/example" type="com.example.MyAction">
79 * <set-property key="foo" property="bar" />
80 * </action>
81 * </pre></code>
82 * </p>
83 *
84 * @param key the key by which this value will be retrieved
85 * @param value the value to store with the supplied key
86 * @throws IllegalStateException if this module configuration has been
87 * frozen
88 * @since Struts 1.3
89 */
90 public void setProperty(String key, String value) {
91 throwIfConfigured();
92 properties.setProperty(key, value);
93 }
94
95 /**
96 * Return the property-value for the specified key, if any; otherwise
97 * return <code>null</code>.
98 *
99 * @param key a key specified in the <code>struts-config</code> file
100 * @return the value stored with the supplied key
101 * @since Struts 1.3
102 */
103 public String getProperty(String key) {
104 return properties.getProperty(key);
105 }
106
107 /**
108 * <p> Return the entire set of properties configured for this object. At
109 * this time, this only needs to be exposed to support inheritance, so
110 * choosing a conservative access modifier ("protected"). </p>
111 *
112 * @return set of properties configured for this object
113 */
114 protected Properties getProperties() {
115 return this.properties;
116 }
117
118 /**
119 * Set the entire set of properties configured for this object. At this
120 * time, this only needs to be exposed to support inheritance, so choosing
121 * a conservative access modifier ("protected").
122 */
123 protected void setProperties(Properties properties) {
124 this.properties = properties;
125 }
126
127 /**
128 * <p>Compare the properties of this config with that of the given and
129 * copy those that are not present. This method is used by subclasses
130 * that support configuration inheritance.</p>
131 *
132 * @param baseConfig The config object to copy properties from.
133 */
134 protected void inheritProperties(BaseConfig baseConfig) {
135 throwIfConfigured();
136
137 // Inherit forward properties
138 Properties baseProperties = baseConfig.getProperties();
139 Enumeration<?> keys = baseProperties.propertyNames();
140
141 while (keys.hasMoreElements()) {
142 String key = (String) keys.nextElement();
143
144 // Check if we have this property before copying it
145 String value = this.getProperty(key);
146
147 if (value == null) {
148 value = baseProperties.getProperty(key);
149 setProperty(key, value);
150 }
151 }
152 }
153
154 /**
155 * <p>Return a copy of the properties held by this object.</p>
156 */
157 protected Properties copyProperties() {
158 Properties copy = new Properties();
159
160 Enumeration<?> keys = properties.propertyNames();
161
162 while (keys.hasMoreElements()) {
163 String key = (String) keys.nextElement();
164
165 copy.setProperty(key, properties.getProperty(key));
166 }
167
168 return copy;
169 }
170 }