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.jk.config;
018:
019: import java.io.File;
020: import java.io.FileWriter;
021: import java.io.IOException;
022: import java.io.PrintWriter;
023: import java.util.Date;
024:
025: import org.apache.catalina.Context;
026:
027: /**
028: Generates automatic IIS isapi_redirect configurations based on
029: the Tomcat server.xml settings and the war contexts
030: initialized during startup.
031: <p>
032: This config interceptor is enabled by inserting an IISConfig
033: element in the <b><ContextManager></b> tag body inside
034: the server.xml file like so:
035: <pre>
036: * < ContextManager ... >
037: * ...
038: * <<b>IISConfig</b> <i>options</i> />
039: * ...
040: * < /ContextManager >
041: </pre>
042: where <i>options</i> can include any of the following attributes:
043: <ul>
044: <li><b>configHome</b> - default parent directory for the following paths.
045: If not set, this defaults to TOMCAT_HOME. Ignored
046: whenever any of the following paths is absolute.
047: </li>
048: <li><b>regConfig</b> - path to use for writing IIS isapi_redirect registry
049: file. If not set, defaults to
050: "conf/auto/iis_redirect.reg".</li>
051: <li><b>workersConfig</b> - path to workers.properties file used by
052: isapi_redirect. If not set, defaults to
053: "conf/jk/workers.properties".</li>
054: <li><b>uriConfig</b> - path to use for writing IIS isapi_redirect uriworkermap
055: file. If not set, defaults to
056: "conf/auto/uriworkermap.properties".</li>
057: <li><b>jkLog</b> - path to log file to be used by isapi_redirect.</li>
058: <li><b>jkDebug</b> - Loglevel setting. May be debug, info, error, or emerg.
059: If not set, defaults to emerg.</li>
060: <li><b>jkWorker</b> The desired worker. Must be set to one of the workers
061: defined in the workers.properties file. "ajp12", "ajp13"
062: or "inprocess" are the workers found in the default
063: workers.properties file. If not specified, defaults
064: to "ajp13" if an Ajp13Interceptor is in use, otherwise
065: it defaults to "ajp12".</li>
066: <li><b>forwardAll</b> - If true, forward all requests to Tomcat. This helps
067: insure that all the behavior configured in the web.xml
068: file functions correctly. If false, let IIS serve
069: static resources assuming it has been configured
070: to do so. The default is true.
071: Warning: When false, some configuration in
072: the web.xml may not be duplicated in IIS.
073: Review the uriworkermap file to see what
074: configuration is actually being set in IIS.</li>
075: <li><b>noRoot</b> - If true, the root context is not mapped to
076: Tomcat. If false and forwardAll is true, all requests
077: to the root context are mapped to Tomcat. If false and
078: forwardAll is false, only JSP and servlets requests to
079: the root context are mapped to Tomcat. When false,
080: to correctly serve Tomcat's root context you must also
081: modify the Home Directory setting in IIS
082: to point to Tomcat's root context directory.
083: Otherwise some content, such as the root index.html,
084: will be served by IIS before isapi_redirect gets a chance
085: to claim the request and pass it to Tomcat.
086: The default is true.</li>
087: </ul>
088: <p>
089: @author Costin Manolache
090: @author Larry Isaacs
091: @author Gal Shachor
092: @author Bill Barker
093: */
094: public class IISConfig extends BaseJkConfig {
095:
096: public static final String WORKERS_CONFIG = "/conf/jk/workers.properties";
097: public static final String URI_WORKERS_MAP_CONFIG = "/conf/auto/uriworkermap.properties";
098: public static final String ISAPI_LOG_LOCATION = "/logs/iis_redirect.log";
099: public static final String ISAPI_REG_FILE = "/conf/auto/iis_redirect.reg";
100:
101: private File regConfig = null;
102: private File uriConfig = null;
103:
104: public IISConfig() {
105: }
106:
107: //-------------------- Properties --------------------
108:
109: /**
110: set the path to the output file for the auto-generated
111: isapi_redirect registry file. If this path is relative
112: then getRegConfig() will resolve it absolutely against
113: the getConfigHome() path.
114: <p>
115: @param <b>path</b> String path to a file
116: */
117: public void setRegConfig(String path) {
118: regConfig = (path == null) ? null : new File(path);
119: }
120:
121: /**
122: set a path to the uriworkermap.properties file.
123: @param <b>path</b> String path to uriworkermap.properties file
124: */
125: public void setUriConfig(String path) {
126: uriConfig = (path == null ? null : new File(path));
127: }
128:
129: // -------------------- Initialize/guess defaults --------------------
130:
131: /** Initialize defaults for properties that are not set
132: explicitely
133: */
134: protected void initProperties() {
135: super .initProperties();
136:
137: regConfig = getConfigFile(regConfig, configHome, ISAPI_REG_FILE);
138: workersConfig = getConfigFile(workersConfig, configHome,
139: WORKERS_CONFIG);
140: uriConfig = getConfigFile(uriConfig, configHome,
141: URI_WORKERS_MAP_CONFIG);
142: jkLog = getConfigFile(jkLog, configHome, ISAPI_LOG_LOCATION);
143: }
144:
145: // -------------------- Generate config --------------------
146:
147: protected PrintWriter getWriter() throws IOException {
148: String abUriConfig = uriConfig.getAbsolutePath();
149: return new PrintWriter(new FileWriter(abUriConfig, append));
150: }
151:
152: protected boolean generateJkHead(PrintWriter mod_jk) {
153: try {
154: PrintWriter regfile = new PrintWriter(new FileWriter(
155: regConfig));
156: log("Generating IIS registry file = " + regConfig);
157: generateRegistrySettings(regfile);
158: regfile.close();
159: } catch (IOException iex) {
160: log("Unable to generate registry file " + regConfig);
161: return false;
162: }
163: log("Generating IIS URI worker map file = " + uriConfig);
164: generateUriWorkerHeader(mod_jk);
165: return true;
166: }
167:
168: // -------------------- Config sections --------------------
169:
170: /** Writes the registry settings required by the IIS connector
171: */
172: private void generateRegistrySettings(PrintWriter regfile) {
173: regfile.println("REGEDIT4");
174: regfile.println();
175: regfile
176: .println("[HKEY_LOCAL_MACHINE\\SOFTWARE\\Apache Software Foundation\\Jakarta Isapi Redirector\\1.0]");
177: regfile
178: .println("\"extension_uri\"=\"/jakarta/isapi_redirect.dll\"");
179: regfile.println("\"log_file\"=\""
180: + dubleSlash(jkLog.toString()) + "\"");
181: regfile.println("\"log_level\"=\"" + jkDebug + "\"");
182: regfile.println("\"worker_file\"=\""
183: + dubleSlash(workersConfig.toString()) + "\"");
184: regfile.println("\"worker_mount_file\"=\""
185: + dubleSlash(uriConfig.toString()) + "\"");
186: }
187:
188: /** Writes the header information to the uriworkermap file
189: */
190: private void generateUriWorkerHeader(PrintWriter uri_worker) {
191: uri_worker
192: .println("###################################################################");
193: uri_worker.println("# Auto generated configuration. Dated: "
194: + new Date());
195: uri_worker
196: .println("###################################################################");
197: uri_worker.println();
198:
199: uri_worker.println("#");
200: uri_worker
201: .println("# Default worker to be used through our mappings");
202: uri_worker.println("#");
203: uri_worker.println("default.worker=" + jkWorker);
204: uri_worker.println();
205: }
206:
207: /** Forward all requests for a context to tomcat.
208: The default.
209: */
210: protected void generateStupidMappings(Context context,
211: PrintWriter uri_worker) {
212: String ctxPath = context.getPath();
213: String nPath = ("".equals(ctxPath)) ? "/" : ctxPath;
214:
215: if (noRoot && "".equals(ctxPath)) {
216: log("Ignoring root context in forward-all mode ");
217: return;
218: }
219:
220: // map all requests for this context to Tomcat
221: uri_worker.println(nPath + "=$(default.worker)");
222: if ("".equals(ctxPath)) {
223: uri_worker.println(nPath + "*=$(default.worker)");
224: uri_worker
225: .println("# Note: To correctly serve the Tomcat's root context, IIS's Home Directory must");
226: uri_worker.println("# must be set to: \""
227: + getAbsoluteDocBase(context) + "\"");
228: } else
229: uri_worker.println(nPath + "/*=$(default.worker)");
230: }
231:
232: protected void generateContextMappings(Context context,
233: PrintWriter uri_worker) {
234: String ctxPath = context.getPath();
235: String nPath = ("".equals(ctxPath)) ? "/" : ctxPath;
236:
237: if (noRoot && "".equals(ctxPath)) {
238: log("Ignoring root context in forward-all mode ");
239: return;
240: }
241:
242: // Static files will be served by IIS
243: uri_worker.println();
244: uri_worker
245: .println("#########################################################");
246: uri_worker.println("# Auto configuration for the " + nPath
247: + " context.");
248: uri_worker
249: .println("#########################################################");
250: uri_worker.println();
251:
252: // Static mappings are not set in uriworkermap, but must be set with IIS admin.
253:
254: // InvokerInterceptor - it doesn't have a container,
255: // but it's implemented using a special module.
256:
257: // XXX we need to better collect all mappings
258:
259: if (context.getLoginConfig() != null) {
260: String loginPage = context.getLoginConfig().getLoginPage();
261: if (loginPage != null) {
262: int lpos = loginPage.lastIndexOf("/");
263: String jscurl = loginPage.substring(0, lpos + 1)
264: + "j_security_check";
265: addMapping(ctxPath, jscurl, uri_worker);
266: }
267: }
268: String[] servletMaps = context.findServletMappings();
269: for (int ii = 0; ii < servletMaps.length; ii++) {
270: addMapping(ctxPath, servletMaps[ii], uri_worker);
271: }
272: }
273:
274: /** Add an IIS extension mapping.
275: */
276: protected boolean addMapping(String ctxPath, String ext,
277: PrintWriter uri_worker) {
278: if (debug > 0)
279: log("Adding extension map for " + ctxPath + "/*." + ext);
280: if (!ext.startsWith("/"))
281: ext = "/" + ext;
282: if (ext.length() > 1)
283: uri_worker.println(ctxPath + "/*." + ext
284: + "=$(default.worker)");
285: return true;
286: }
287:
288: /** Add a fulling specified IIS mapping.
289: */
290: protected boolean addMapping(String fullPath, PrintWriter uri_worker) {
291: if (debug > 0)
292: log("Adding map for " + fullPath);
293: uri_worker.println(fullPath + "=$(default.worker)");
294: return true;
295: }
296:
297: // -------------------- Utils --------------------
298:
299: private String dubleSlash(String in) {
300: StringBuffer sb = new StringBuffer();
301:
302: for (int i = 0; i < in.length(); i++) {
303: char ch = in.charAt(i);
304: if ('\\' == ch) {
305: sb.append("\\\\");
306: } else {
307: sb.append(ch);
308: }
309: }
310:
311: return sb.toString();
312: }
313:
314: }
|