001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.jk.config;
019:
020: import java.io.File;
021: import java.io.FileWriter;
022: import java.io.IOException;
023: import java.io.PrintWriter;
024: import java.util.Date;
025:
026: import org.apache.catalina.Context;
027:
028: /**
029: Generates automatic Netscape nsapi_redirect configurations based on
030: the Tomcat server.xml settings and the war contexts
031: initialized during startup.
032: <p>
033: This config interceptor is enabled by inserting an NSConfig
034: element in the <b><ContextManager></b> tag body inside
035: the server.xml file like so:
036: <pre>
037: * < ContextManager ... >
038: * ...
039: * <<b>NSConfig</b> <i>options</i> />
040: * ...
041: * < /ContextManager >
042: </pre>
043: where <i>options</i> can include any of the following attributes:
044: <ul>
045: <li><b>configHome</b> - default parent directory for the following paths.
046: If not set, this defaults to TOMCAT_HOME. Ignored
047: whenever any of the following paths is absolute.
048: </li>
049: <li><b>objConfig</b> - path to use for writing Netscape obj.conf
050: file. If not set, defaults to
051: "conf/auto/obj.conf".</li>
052: <li><b>objectName</b> - Name of the Object to execute the requests.
053: Defaults to "servlet".</li>
054: <li><b>workersConfig</b> - path to workers.properties file used by
055: nsapi_redirect. If not set, defaults to
056: "conf/jk/workers.properties".</li>
057: <li><b>nsapiJk</b> - path to Netscape mod_jk plugin file. If not set,
058: defaults to "bin/nsapi_redirect.dll" on windows,
059: "bin/nsapi_rd.nlm" on netware, and
060: "bin/nsapi_redirector.so" everywhere else.</li>
061: <li><b>jkLog</b> - path to log file to be used by nsapi_redirect.</li>
062: <li><b>jkDebug</b> - Loglevel setting. May be debug, info, error, or emerg.
063: If not set, defaults to emerg.</li>
064: <li><b>jkWorker</b> The desired worker. Must be set to one of the workers
065: defined in the workers.properties file. "ajp12", "ajp13"
066: or "inprocess" are the workers found in the default
067: workers.properties file. If not specified, defaults
068: to "ajp13" if an Ajp13Interceptor is in use, otherwise
069: it defaults to "ajp12".</li>
070: <li><b>forwardAll</b> - If true, forward all requests to Tomcat. This helps
071: insure that all the behavior configured in the web.xml
072: file functions correctly. If false, let Netscape serve
073: static resources assuming it has been configured
074: to do so. The default is true.
075: Warning: When false, some configuration in
076: the web.xml may not be duplicated in Netscape.
077: Review the uriworkermap file to see what
078: configuration is actually being set in Netscape.</li>
079: <li><b>noRoot</b> - If true, the root context is not mapped to
080: Tomcat. If false and forwardAll is true, all requests
081: to the root context are mapped to Tomcat. If false and
082: forwardAll is false, only JSP and servlets requests to
083: the root context are mapped to Tomcat. When false,
084: to correctly serve Tomcat's root context you must also
085: modify the Home Directory setting in Netscape
086: to point to Tomcat's root context directory.
087: Otherwise some content, such as the root index.html,
088: will be served by Netscape before nsapi_redirect gets a chance
089: to claim the request and pass it to Tomcat.
090: The default is true.</li>
091: </ul>
092: <p>
093: @author Costin Manolache
094: @author Larry Isaacs
095: @author Gal Shachor
096: @author Bill Barker
097: */
098: public class NSConfig extends BaseJkConfig {
099: private static org.apache.juli.logging.Log log = org.apache.juli.logging.LogFactory
100: .getLog(NSConfig.class);
101:
102: public static final String WORKERS_CONFIG = "/conf/jk/workers.properties";
103: public static final String NS_CONFIG = "/conf/auto/obj.conf";
104: public static final String NSAPI_LOG_LOCATION = "/logs/nsapi_redirect.log";
105: /** default location of nsapi plug-in. */
106: public static final String NSAPI_REDIRECTOR;
107:
108: //set up some defaults based on OS type
109: static {
110: String os = System.getProperty("os.name").toLowerCase();
111: if (os.indexOf("windows") >= 0) {
112: NSAPI_REDIRECTOR = "bin/nsapi_redirect.dll";
113: } else if (os.indexOf("netware") >= 0) {
114: NSAPI_REDIRECTOR = "bin/nsapi_rd.nlm";
115: } else {
116: NSAPI_REDIRECTOR = "bin/nsapi_redirector.so";
117: }
118: }
119:
120: private File objConfig = null;
121: private File nsapiJk = null;
122: private String objectName = "servlet";
123:
124: public NSConfig() {
125: }
126:
127: //-------------------- Properties --------------------
128:
129: /**
130: set the path to the output file for the auto-generated
131: isapi_redirect registry file. If this path is relative
132: then getRegConfig() will resolve it absolutely against
133: the getConfigHome() path.
134: <p>
135: @param path String path to a file
136: */
137: public void setObjConfig(String path) {
138: objConfig = (path == null) ? null : new File(path);
139: }
140:
141: /**
142: set the path to the nsapi plugin module
143: @param path String path to a file
144: */
145: public void setNsapiJk(String path) {
146: nsapiJk = (path == null ? null : new File(path));
147: }
148:
149: /**
150: Set the name for the Object that implements the
151: jk_service call.
152: @param name Name of the obj.conf Object
153: */
154: public void setObjectName(String name) {
155: objectName = name;
156: }
157:
158: // -------------------- Initialize/guess defaults --------------------
159:
160: /** Initialize defaults for properties that are not set
161: explicitely
162: */
163: protected void initProperties() {
164: super .initProperties();
165:
166: objConfig = getConfigFile(objConfig, configHome, NS_CONFIG);
167: workersConfig = getConfigFile(workersConfig, configHome,
168: WORKERS_CONFIG);
169:
170: if (nsapiJk == null)
171: nsapiJk = new File(NSAPI_REDIRECTOR);
172: else
173: nsapiJk = getConfigFile(nsapiJk, configHome,
174: NSAPI_REDIRECTOR);
175: jkLog = getConfigFile(jkLog, configHome, NSAPI_LOG_LOCATION);
176: }
177:
178: // -------------------- Generate config --------------------
179: protected PrintWriter getWriter() throws IOException {
180: String abObjConfig = objConfig.getAbsolutePath();
181: return new PrintWriter(new FileWriter(abObjConfig, append));
182: }
183:
184: protected boolean generateJkHead(PrintWriter mod_jk) {
185: log
186: .info("Generating netscape web server config = "
187: + objConfig);
188:
189: generateNsapiHead(mod_jk);
190:
191: mod_jk.println("<Object name=default>");
192: return true;
193: }
194:
195: private void generateNsapiHead(PrintWriter objfile) {
196: objfile
197: .println("###################################################################");
198: objfile.println("# Auto generated configuration. Dated: "
199: + new Date());
200: objfile
201: .println("###################################################################");
202: objfile.println();
203:
204: objfile.println("#");
205: objfile
206: .println("# You will need to merge the content of this file with your ");
207: objfile
208: .println("# regular obj.conf and then restart (=stop + start) your Netscape server. ");
209: objfile.println("#");
210: objfile.println();
211:
212: objfile.println("#");
213: objfile.println("# Loading the redirector into your server");
214: objfile.println("#");
215: objfile.println();
216: objfile
217: .println("Init fn=\"load-modules\" funcs=\"jk_init,jk_service\" shlib=\"<put full path to the redirector here>\"");
218: objfile.println("Init fn=\"jk_init\" worker_file=\""
219: + workersConfig.toString().replace('\\', '/')
220: + "\" log_level=\"" + jkDebug + "\" log_file=\""
221: + jkLog.toString().replace('\\', '/') + "\"");
222: objfile.println();
223: }
224:
225: protected void generateJkTail(PrintWriter objfile) {
226: objfile.println();
227: objfile
228: .println("#######################################################");
229: objfile
230: .println("# Protecting the WEB-INF and META-INF directories.");
231: objfile
232: .println("#######################################################");
233: objfile
234: .println("PathCheck fn=\"deny-existence\" path=\"*/WEB-INF/*\"");
235: objfile
236: .println("PathCheck fn=\"deny-existence\" path=\"*/META-INF/*\"");
237: objfile.println();
238:
239: objfile.println("</Object>");
240: objfile.println();
241:
242: objfile
243: .println("#######################################################");
244: objfile
245: .println("# New object to execute your servlet requests.");
246: objfile
247: .println("#######################################################");
248: objfile.println("<Object name=" + objectName + ">");
249: objfile.println("ObjectType fn=force-type type=text/html");
250: objfile.println("Service fn=\"jk_service\" worker=\""
251: + jkWorker + "\" path=\"/*\"");
252: objfile.println("</Object>");
253: objfile.println();
254: }
255:
256: // -------------------- Forward all mode --------------------
257:
258: /** Forward all requests for a context to tomcat.
259: The default.
260: */
261: protected void generateStupidMappings(Context context,
262: PrintWriter objfile) {
263: String ctxPath = context.getPath();
264: String nPath = ("".equals(ctxPath)) ? "/" : ctxPath;
265:
266: if (noRoot && "".equals(ctxPath)) {
267: log.debug("Ignoring root context in forward-all mode ");
268: return;
269: }
270: objfile.println("<Object name=" + context.getName() + ">");
271:
272: objfile.println("NameTrans fn=\"assign-name\" from=\""
273: + ctxPath + "\" name=\"" + objectName + "\"");
274: objfile.println("NameTrans fn=\"assign-name\" from=\""
275: + ctxPath + "/*\" name=\"" + objectName + "\"");
276: objfile.println("</Object>");
277: }
278:
279: // -------------------- Netscape serves static mode --------------------
280: // This is not going to work for all apps. We fall back to stupid mode.
281:
282: protected void generateContextMappings(Context context,
283: PrintWriter objfile) {
284: String ctxPath = context.getPath();
285: String nPath = ("".equals(ctxPath)) ? "/" : ctxPath;
286:
287: if (noRoot && "".equals(ctxPath)) {
288: log
289: .debug("Ignoring root context in non-forward-all mode ");
290: return;
291: }
292: objfile.println("<Object name=" + context.getName() + ">");
293: // Static files will be served by Netscape
294: objfile
295: .println("#########################################################");
296: objfile.println("# Auto configuration for the " + nPath
297: + " context starts.");
298: objfile
299: .println("#########################################################");
300: objfile.println();
301:
302: // XXX Need to determine what if/how static mappings are done
303:
304: // InvokerInterceptor - it doesn't have a container,
305: // but it's implemented using a special module.
306:
307: // XXX we need to better collect all mappings
308: if (context.getLoginConfig() != null) {
309: String loginPage = context.getLoginConfig().getLoginPage();
310: if (loginPage != null) {
311: int lpos = loginPage.lastIndexOf("/");
312: String jscurl = loginPage.substring(0, lpos + 1)
313: + "j_security_check";
314: addMapping(ctxPath, jscurl, objfile);
315: }
316: }
317:
318: String[] servletMaps = context.findServletMappings();
319: for (int ii = 0; ii < servletMaps.length; ii++) {
320: addMapping(ctxPath, servletMaps[ii], objfile);
321: }
322: objfile.println("</Object>");
323: }
324:
325: /** Add a Netscape extension mapping.
326: */
327: protected boolean addMapping(String ctxPath, String ext,
328: PrintWriter objfile) {
329: if (log.isDebugEnabled())
330: log.debug("Adding extension map for " + ctxPath + "/*."
331: + ext);
332: if (!ext.startsWith("/"))
333: ext = "/" + ext;
334: if (ext.length() > 1)
335: objfile.println("NameTrans fn=\"assign-name\" from=\""
336: + ctxPath + ext + "\" name=\"" + objectName + "\"");
337: return true;
338: }
339:
340: /** Add a fulling specified Netscape mapping.
341: */
342: protected boolean addMapping(String fullPath, PrintWriter objfile) {
343: if (log.isDebugEnabled())
344: log.debug("Adding map for " + fullPath);
345: objfile.println("NameTrans fn=\"assign-name\" from=\""
346: + fullPath + "\" name=\"" + objectName + "\"");
347: return true;
348: }
349:
350: }
|