1 /*
2 * Copyright 2004-2005 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 package org.apache.catalina.storeconfig;
17
18 import java.io.File;
19 import java.io.FileInputStream;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.net.URL;
23
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.apache.tomcat.util.digester.Digester;
27 import org.xml.sax.SAXException;
28
29 /**
30 *
31 * @author Peter Rossbach
32 *
33 * <b>XML Format </b>
34 *
35 * <pre>
36 *
37 * <Registry name="" encoding="UTF8" >
38 * <Description tag="Server" standard="true" default="true"/>
39 * tagClass="org.apache.catalina.core.StandardServer"
40 * storeFactory="org.apache.catalina.storeconfig.StandardServerSF">
41 * <TransientAttributes>
42 * <Attribute></Attribute>
43 * </TransientAttributes>
44 * <TransientChilds>
45 * <Child></Child>
46 * </TransientChilds>
47 * </Description>
48 * ...
49 * </Tegistry>
50 *
51 * </pre>
52 *
53 *
54 * Convention:
55 * <ul>
56 * <li>Factories at subpackage <i>org.apache.catalina.core.storeconfig.xxxSF
57 * </i>.</li>
58 * <li>Element name are the unique Class name</li>
59 * <li>SF for StoreFactory</li>
60 * <li>standard implementation is false</li>
61 * </ul>
62 * other things:
63 * <ul>
64 * <li>Registry XML format is a very good option</li>
65 * <li>Store format is not fix</li>
66 * <li>We hope with the parent declaration we can build recursive child store
67 * operation //dream</li>
68 * <li>Problem is to access child data from array,collections or normal detail
69 * object</li>
70 * <li>Default definitions for Listener, Valve Resource? - Based on interface
71 * type!</li>
72 * </ul>
73 */
74 public class StoreLoader {
75 private static Log log = LogFactory.getLog(StoreLoader.class);
76
77 /**
78 * The <code>Digester</code> instance used to parse registry descriptors.
79 */
80 protected static Digester digester = createDigester();
81
82 private StoreRegistry registry;
83
84 private URL registryResource ;
85
86 /**
87 * @return Returns the registry.
88 */
89 public StoreRegistry getRegistry() {
90 return registry;
91 }
92
93 /**
94 * @param registry
95 * The registry to set.
96 */
97 public void setRegistry(StoreRegistry registry) {
98 this.registry = registry;
99 }
100
101 /**
102 * Create and configure the Digester we will be using for setup store
103 * registry.
104 */
105 protected static Digester createDigester() {
106 long t1 = System.currentTimeMillis();
107 // Initialize the digester
108 Digester digester = new Digester();
109 digester.setValidating(false);
110 digester.setClassLoader(StoreRegistry.class.getClassLoader());
111
112 // Configure the actions we will be using
113 digester.addObjectCreate("Registry",
114 "org.apache.catalina.storeconfig.StoreRegistry", "className");
115 digester.addSetProperties("Registry");
116 digester
117 .addObjectCreate("Registry/Description",
118 "org.apache.catalina.storeconfig.StoreDescription",
119 "className");
120 digester.addSetProperties("Registry/Description");
121 digester.addRule("Registry/Description", new StoreFactoryRule(
122 "org.apache.catalina.storeconfig.StoreFactoryBase",
123 "storeFactoryClass",
124 "org.apache.catalina.storeconfig.StoreAppender",
125 "storeAppenderClass"));
126 digester.addSetNext("Registry/Description", "registerDescription",
127 "org.apache.catalina.storeconfig.StoreDescription");
128 digester.addCallMethod("Registry/Description/TransientAttribute",
129 "addTransientAttribute", 0);
130 digester.addCallMethod("Registry/Description/TransientChild",
131 "addTransientChild", 0);
132
133 long t2 = System.currentTimeMillis();
134 if (log.isDebugEnabled())
135 log.debug("Digester for server-registry.xml created " + (t2 - t1));
136 return (digester);
137
138 }
139
140 /**
141 *
142 * @param aFile
143 * @return The server file
144 */
145 protected File serverFile(String aFile) {
146
147 if (aFile == null || (aFile != null && aFile.length() < 1))
148 aFile = "server-registry.xml";
149 File file = new File(aFile);
150 if (!file.isAbsolute())
151 file = new File(System.getProperty("catalina.base") + "/conf",
152 aFile);
153 try {
154 file = file.getCanonicalFile();
155 } catch (IOException e) {
156 log.error(e);
157 }
158 return (file);
159 }
160
161 /**
162 * Load Description from external source
163 *
164 * @param aURL
165 */
166 public void load(String aURL) {
167 synchronized (digester) {
168 File aRegistryFile = serverFile(aURL);
169 try {
170 registry = (StoreRegistry) digester.parse(aRegistryFile);
171 registryResource = aRegistryFile.toURL();
172 } catch (IOException e) {
173 log.error(e);
174 } catch (SAXException e) {
175 log.error(e);
176 }
177 }
178
179 }
180
181 /**
182 * Load from defaults
183 * <ul>
184 * <li>System Property URL catalina.storeregistry</li>
185 * <li>File $catalina.base/conf/server-registry.xml</li>
186 * <li>class resource org/apache/catalina/storeconfig/server-registry.xml
187 * </li>
188 * </ul>
189 */
190 public void load() {
191
192 InputStream is = null;
193 Throwable error = null;
194 registryResource = null ;
195 try {
196 String configUrl = getConfigUrl();
197 if (configUrl != null) {
198 is = (new URL(configUrl)).openStream();
199 if (log.isInfoEnabled())
200 log
201 .info("Find registry server-registry.xml from system property at url "
202 + configUrl);
203 ;
204 registryResource = new URL(configUrl);
205 }
206 } catch (Throwable t) {
207 // Ignore
208 }
209 if (is == null) {
210 try {
211 File home = new File(getCatalinaBase());
212 File conf = new File(home, "conf");
213 File reg = new File(conf, "server-registry.xml");
214 is = new FileInputStream(reg);
215 if (log.isInfoEnabled())
216 log.info("Find registry server-registry.xml at file "
217 + reg.getCanonicalPath());
218 ;
219 registryResource = reg.toURL() ;
220 } catch (Throwable t) {
221 // Ignore
222 }
223 }
224 if (is == null) {
225 try {
226 is = StoreLoader.class
227 .getResourceAsStream("/org/apache/catalina/storeconfig/server-registry.xml");
228 if (log.isInfoEnabled())
229 log
230 .info("Find registry server-registry.xml at classpath resource");
231 registryResource = StoreLoader.class
232 .getResource("/org/apache/catalina/storeconfig/server-registry.xml");
233
234 } catch (Throwable t) {
235 // Ignore
236 }
237 }
238 if (is != null) {
239 try {
240 synchronized (digester) {
241 registry = (StoreRegistry) digester.parse(is);
242 }
243 } catch (Throwable t) {
244 error = t;
245 } finally {
246 try {
247 is.close();
248 } catch (IOException e) {
249 }
250 }
251 }
252 if ((is == null) || (error != null)) {
253 log.error(error);
254 }
255 }
256
257 /**
258 * Get the value of the catalina.home environment variable.
259 */
260 private static String getCatalinaHome() {
261 return System.getProperty("catalina.home", System
262 .getProperty("user.dir"));
263 }
264
265 /**
266 * Get the value of the catalina.base environment variable.
267 */
268 private static String getCatalinaBase() {
269 return System.getProperty("catalina.base", getCatalinaHome());
270 }
271
272 /**
273 * Get the value of the configuration URL.
274 */
275 private static String getConfigUrl() {
276 return System.getProperty("catalina.storeconfig");
277 }
278
279
280
281 /**
282 * @return Returns the registryResource.
283 */
284 public URL getRegistryResource() {
285 return registryResource;
286 }
287 }