001: /*
002: * Copyright 1999,2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.catalina.startup;
018:
019: import java.io.File;
020: import java.util.Enumeration;
021:
022: import org.apache.catalina.Context;
023: import org.apache.catalina.Host;
024: import org.apache.catalina.Lifecycle;
025: import org.apache.catalina.LifecycleEvent;
026: import org.apache.catalina.LifecycleListener;
027: import org.apache.catalina.Logger;
028: import org.apache.catalina.util.StringManager;
029:
030: /**
031: * Startup event listener for a <b>Host</b> that configures Contexts (web
032: * applications) for all defined "users" who have a web application in a
033: * directory with the specified name in their home directories. The context
034: * path of each deployed application will be set to <code>~xxxxx</code>, where
035: * xxxxx is the username of the owning user for that web application
036: *
037: * @author Craig R. McClanahan
038: * @version $Revision: 1.3 $ $Date: 2004/02/27 14:58:49 $
039: */
040:
041: public final class UserConfig implements LifecycleListener {
042:
043: // ----------------------------------------------------- Instance Variables
044:
045: /**
046: * The Java class name of the Context configuration class we should use.
047: */
048: private String configClass = "org.apache.catalina.startup.ContextConfig";
049:
050: /**
051: * The Java class name of the Context implementation we should use.
052: */
053: private String contextClass = "org.apache.catalina.core.StandardContext";
054:
055: /**
056: * The debugging detail level for this component.
057: */
058: private int debug = 999;
059:
060: /**
061: * The directory name to be searched for within each user home directory.
062: */
063: private String directoryName = "public_html";
064:
065: /**
066: * The base directory containing user home directories.
067: */
068: private String homeBase = null;
069:
070: /**
071: * The Host we are associated with.
072: */
073: private Host host = null;
074:
075: /**
076: * The string resources for this package.
077: */
078: private static final StringManager sm = StringManager
079: .getManager(Constants.Package);
080:
081: /**
082: * The Java class name of the user database class we should use.
083: */
084: private String userClass = "org.apache.catalina.startup.PasswdUserDatabase";
085:
086: // ------------------------------------------------------------- Properties
087:
088: /**
089: * Return the Context configuration class name.
090: */
091: public String getConfigClass() {
092:
093: return (this .configClass);
094:
095: }
096:
097: /**
098: * Set the Context configuration class name.
099: *
100: * @param configClass The new Context configuration class name.
101: */
102: public void setConfigClass(String configClass) {
103:
104: this .configClass = configClass;
105:
106: }
107:
108: /**
109: * Return the Context implementation class name.
110: */
111: public String getContextClass() {
112:
113: return (this .contextClass);
114:
115: }
116:
117: /**
118: * Set the Context implementation class name.
119: *
120: * @param contextClass The new Context implementation class name.
121: */
122: public void setContextClass(String contextClass) {
123:
124: this .contextClass = contextClass;
125:
126: }
127:
128: /**
129: * Return the debugging detail level for this component.
130: */
131: public int getDebug() {
132:
133: return (this .debug);
134:
135: }
136:
137: /**
138: * Set the debugging detail level for this component.
139: *
140: * @param debug The new debugging detail level
141: */
142: public void setDebug(int debug) {
143:
144: this .debug = debug;
145:
146: }
147:
148: /**
149: * Return the directory name for user web applications.
150: */
151: public String getDirectoryName() {
152:
153: return (this .directoryName);
154:
155: }
156:
157: /**
158: * Set the directory name for user web applications.
159: *
160: * @param directoryName The new directory name
161: */
162: public void setDirectoryName(String directoryName) {
163:
164: this .directoryName = directoryName;
165:
166: }
167:
168: /**
169: * Return the base directory containing user home directories.
170: */
171: public String getHomeBase() {
172:
173: return (this .homeBase);
174:
175: }
176:
177: /**
178: * Set the base directory containing user home directories.
179: *
180: * @param homeBase The new base directory
181: */
182: public void setHomeBase(String homeBase) {
183:
184: this .homeBase = homeBase;
185:
186: }
187:
188: /**
189: * Return the user database class name for this component.
190: */
191: public String getUserClass() {
192:
193: return (this .userClass);
194:
195: }
196:
197: /**
198: * Set the user database class name for this component.
199: */
200: public void setUserClass(String userClass) {
201:
202: this .userClass = userClass;
203:
204: }
205:
206: // --------------------------------------------------------- Public Methods
207:
208: /**
209: * Process the START event for an associated Host.
210: *
211: * @param event The lifecycle event that has occurred
212: */
213: public void lifecycleEvent(LifecycleEvent event) {
214:
215: // Identify the host we are associated with
216: try {
217: host = (Host) event.getLifecycle();
218: } catch (ClassCastException e) {
219: log(sm.getString("hostConfig.cce", event.getLifecycle()), e);
220: return;
221: }
222:
223: // Process the event that has occurred
224: if (event.getType().equals(Lifecycle.START_EVENT))
225: start();
226: else if (event.getType().equals(Lifecycle.STOP_EVENT))
227: stop();
228:
229: }
230:
231: // -------------------------------------------------------- Private Methods
232:
233: /**
234: * Deploy a web application for any user who has a web application present
235: * in a directory with a specified name within their home directory.
236: */
237: private void deploy() {
238:
239: if (debug >= 1)
240: log(sm.getString("userConfig.deploying"));
241:
242: // Load the user database object for this host
243: UserDatabase database = null;
244: try {
245: Class clazz = Class.forName(userClass);
246: database = (UserDatabase) clazz.newInstance();
247: database.setUserConfig(this );
248: } catch (Exception e) {
249: log(sm.getString("userConfig.database"), e);
250: return;
251: }
252:
253: // Deploy the web application (if any) for each defined user
254: Enumeration users = database.getUsers();
255: while (users.hasMoreElements()) {
256: String user = (String) users.nextElement();
257: String home = database.getHome(user);
258: deploy(user, home);
259: }
260:
261: }
262:
263: /**
264: * Deploy a web application for the specified user if they have such an
265: * application in the defined directory within their home directory.
266: *
267: * @param user Username owning the application to be deployed
268: * @param home Home directory of this user
269: */
270: private void deploy(String user, String home) {
271:
272: // Does this user have a web application to be deployed?
273: String contextPath = "/~" + user;
274: if (host.findChild(contextPath) != null)
275: return;
276: File app = new File(home, directoryName);
277: if (!app.exists() || !app.isDirectory())
278: return;
279: /*
280: File dd = new File(app, "/WEB-INF/web.xml");
281: if (!dd.exists() || !dd.isFile() || !dd.canRead())
282: return;
283: */
284: log(sm.getString("userConfig.deploy", user));
285:
286: // Deploy the web application for this user
287: try {
288: Class clazz = Class.forName(contextClass);
289: Context context = (Context) clazz.newInstance();
290: context.setPath(contextPath);
291: context.setDocBase(app.toString());
292: if (context instanceof Lifecycle) {
293: clazz = Class.forName(configClass);
294: LifecycleListener listener = (LifecycleListener) clazz
295: .newInstance();
296: ((Lifecycle) context).addLifecycleListener(listener);
297: }
298: host.addChild(context);
299: } catch (Exception e) {
300: log(sm.getString("userConfig.error", user), e);
301: }
302:
303: }
304:
305: /**
306: * Log a message on the Logger associated with our Host (if any)
307: *
308: * @param message Message to be logged
309: */
310: private void log(String message) {
311:
312: Logger logger = null;
313: if (host != null)
314: logger = host.getLogger();
315: if (logger != null)
316: logger
317: .log("UserConfig[" + host.getName() + "]: "
318: + message);
319: else
320: System.out.println("UserConfig[" + host.getName() + "]: "
321: + message);
322:
323: }
324:
325: /**
326: * Log a message on the Logger associated with our Host (if any)
327: *
328: * @param message Message to be logged
329: * @param throwable Associated exception
330: */
331: private void log(String message, Throwable throwable) {
332:
333: Logger logger = null;
334: if (host != null)
335: logger = host.getLogger();
336: if (logger != null)
337: logger.log("UserConfig[" + host.getName() + "] " + message,
338: throwable);
339: else {
340: System.out.println("UserConfig[" + host.getName() + "]: "
341: + message);
342: System.out.println("" + throwable);
343: throwable.printStackTrace(System.out);
344: }
345:
346: }
347:
348: /**
349: * Process a "start" event for this Host.
350: */
351: private void start() {
352:
353: if (debug > 0)
354: log(sm.getString("userConfig.start"));
355:
356: deploy();
357:
358: }
359:
360: /**
361: * Process a "stop" event for this Host.
362: */
363: private void stop() {
364:
365: if (debug > 0)
366: log(sm.getString("userConfig.stop"));
367:
368: }
369:
370: }
|