0001: /**
0002: * Library name : Primrose - A Java Database Connection Pool.
0003: * Published by Ben Keeping, http://primrose.org.uk .
0004: * Copyright (C) 2004 Ben Keeping, primrose.org.uk
0005: * Email: Use "Contact Us Form" on website
0006: *
0007: * This library is free software; you can redistribute it and/or
0008: * modify it under the terms of the GNU Lesser General Public
0009: * License as published by the Free Software Foundation; either
0010: * version 2.1 of the License, or (at your option) any later version.
0011: *
0012: * This library is distributed in the hope that it will be useful,
0013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0015: * Lesser General Public License for more details.
0016: *
0017: * You should have received a copy of the GNU Lesser General Public
0018: * License along with this library; if not, write to the Free Software
0019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0020: */package uk.org.primrose.console;
0021:
0022: import uk.org.primrose.GeneralException;
0023: import uk.org.primrose.Logger;
0024: import uk.org.primrose.Util;
0025: import uk.org.primrose.pool.*;
0026: import uk.org.primrose.pool.core.*;
0027: import java.net.*;
0028: import java.io.*;
0029: import java.util.*;
0030: import java.lang.reflect.*;
0031:
0032: public class WebConsole {
0033:
0034: private static int port = -1;
0035: private static boolean alreadyStarted = false;
0036: private Logger logger = null;
0037: List<Pool> loadedPools = null;
0038: private static boolean bKeepRunning = true;
0039: private static String username = null;
0040: private static String password = null;
0041:
0042: public WebConsole(String username, String password, int port,
0043: Logger logger) {
0044: WebConsole.port = port;
0045: this .logger = logger;
0046: WebConsole.username = username;
0047: WebConsole.password = password;
0048: }
0049:
0050: public WebConsole(int port, Logger logger) {
0051: WebConsole.port = port;
0052: this .logger = logger;
0053: }
0054:
0055: public void start() throws IOException {
0056: if (port > 0 && !alreadyStarted) {
0057: logger.info("Starting WebConsole on port " + port);
0058: new WebConsoleStarter().start();
0059: Runtime.getRuntime().addShutdownHook(
0060: new WebConsoleStopper());
0061: }
0062: }
0063:
0064: class WebConsoleStarter extends Thread {
0065:
0066: public void run() {
0067: if (alreadyStarted)
0068: return;
0069: try {
0070: logger.verbose("About to bind to port " + port);
0071:
0072: ServerSocket ss = new ServerSocket(port);
0073: alreadyStarted = true;
0074: logger.verbose("Listening for connections ...");
0075: while (bKeepRunning) {
0076: new SocketHandler(ss.accept()).start();
0077: }
0078: } catch (IOException ioe) {
0079: logger.error("Cannot start WebConsole on port " + port
0080: + " : " + ioe);
0081: logger.printStackTrace(ioe);
0082: }
0083: }
0084: }
0085:
0086: public static void shutdown() {
0087: try {
0088: bKeepRunning = false;
0089: alreadyStarted = false;
0090:
0091: // This bumps it out of the blocking while loop on accept()
0092: Socket s = new Socket("localhost", port);
0093: s.close();
0094: } catch (Exception e) {
0095: // don't care
0096: }
0097: }
0098:
0099: class WebConsoleStopper extends Thread {
0100: public void run() {
0101: bKeepRunning = false;
0102: logger.info("Stopping WebConsole");
0103: WebConsole.shutdown();
0104: }
0105: }
0106:
0107: public void setUsername(String username) {
0108: WebConsole.username = username;
0109: }
0110:
0111: public void setPassword(String password) {
0112: WebConsole.password = password;
0113: }
0114:
0115: public String getPassword() {
0116: return password;
0117: }
0118:
0119: public String getUsername() {
0120: return username;
0121: }
0122:
0123: class SocketHandler extends Thread {
0124: Socket s = null;
0125: HttpRequest httpRequest = new HttpRequest(logger);
0126: OutputStream out = null;
0127:
0128: SocketHandler(Socket s) {
0129: this .s = s;
0130: }
0131:
0132: public void run() {
0133: try {
0134: ByteArrayOutputStream baos = new ByteArrayOutputStream();
0135: BufferedReader br = new BufferedReader(
0136: new InputStreamReader(s.getInputStream()));
0137: out = s.getOutputStream();
0138:
0139: String line;
0140: int iCountBlankLines = 0;
0141: while ((line = br.readLine()) != null) {
0142: if (line.length() == 0) {
0143: iCountBlankLines++;
0144: }
0145: baos.write((line + "\n").getBytes());
0146: if (iCountBlankLines == 1)
0147: break;
0148:
0149: }
0150:
0151: baos.flush();
0152:
0153: byte[] requestData = baos.toByteArray();
0154: baos.close();
0155:
0156: if (httpRequest.parseRequest(new String(requestData))) {
0157: //httpRequest.printDetails();
0158: handleRequest();
0159: }
0160:
0161: br.close();
0162: out.close();
0163:
0164: } catch (IOException ioe) {
0165: logger.printStackTrace(ioe);
0166: } finally {
0167: try {
0168: s.close();
0169: } catch (IOException ioe) {
0170: logger.printStackTrace(ioe);
0171: }
0172: }
0173:
0174: }
0175:
0176: private boolean userAuthorised() {
0177: if (username == null || password == null)
0178: return true;
0179:
0180: //httpRequest.printDetails();
0181: HashMap<String, String> headers = httpRequest.getHeaders();
0182: String value = headers.get("authorization");
0183: if (value == null) {
0184: value = headers.get("Authorization");
0185: }
0186: if (value != null) {
0187: String b64pass = value.split(" ")[1];
0188: sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
0189:
0190: String userpass = null;
0191: try {
0192: userpass = new String(decoder.decodeBuffer(b64pass));
0193: } catch (IOException ioe) {
0194: }
0195: if (userpass != null) {
0196: if (userpass.indexOf(":") != -1) {
0197:
0198: String s[] = userpass.split(":");
0199:
0200: if (password.equals(s[1])
0201: && username.equals(s[0])) {
0202: return true;
0203: }
0204: }
0205: }
0206: }
0207: return false;
0208: }
0209:
0210: private void handleRequest() throws IOException {
0211: if (!userAuthorised()) {
0212:
0213: writeHeaders("text/html", "", 401, 0);
0214: return;
0215: }
0216:
0217: String resource = httpRequest.getResource();
0218: logger.verbose("Processing resource : '" + resource + "'");
0219: // Home page
0220: loadedPools = PoolLoader.getLoadedPools();
0221:
0222: if (resource == null || resource.length() == 0
0223: || resource.equals("/")
0224: || resource.equals("/index.html")) {
0225: writeHeaders("text/html", "", 200, 0);
0226: writeTop();
0227:
0228: writeData("<br/><h4>Welcome to the Primrose Web Console</h4>");
0229:
0230: for (Pool pool : loadedPools) {
0231: writeData("<p>");
0232: writeData("<a href=\"/showPool?poolName="
0233: + pool.getPoolName() + "\">Show '"
0234: + pool.getPoolName() + "' Pool</a>");
0235: writeData("</p>");
0236:
0237: }
0238: writeBottom();
0239:
0240: } else if (resource.startsWith("/showPoolConfig")) {
0241: writeHeaders("text/html", "", 200, 0);
0242: writeTop();
0243:
0244: String poolName = httpRequest.getParameters().get(
0245: "poolName");
0246: Pool pool = findPoolByName(poolName);
0247:
0248: if (pool != null) {
0249: writeData("<p>");
0250: writeData("<a href=\"/showPool?poolName="
0251: + pool.getPoolName() + "\">Show '"
0252: + pool.getPoolName() + "' Connections</a>");
0253: writeData("</p>");
0254:
0255: writeData("<br/><form method=\"get\" action=\"alterPoolProperties\"><table>");
0256: Method[] publicMethods = PoolConfigImpl.class
0257: .getMethods();
0258: for (int j = 0; j < publicMethods.length; j++) {
0259: //int numOfArgs = publicMethods[j].getParameterTypes().length;
0260: String methodName = publicMethods[j].getName();
0261: if (methodName.startsWith("getClass"))
0262: continue;
0263: if (methodName.startsWith("get")) {
0264: try {
0265: Object ret = publicMethods[j].invoke(
0266: pool, new Object[] {});
0267: if (ret == null) {
0268: ret = "";
0269: }
0270: writeData("<tr><td>"
0271: + methodName.replaceAll("get",
0272: "")
0273: + "</td><td><input type=\"text\" name=\""
0274: + methodName.replaceAll("get",
0275: "")
0276: + "\" size=\"60\" value=\""
0277: + ret + "\"/></td></tr>");
0278: } catch (Exception e) {
0279: }
0280: }
0281:
0282: }
0283: writeData("<tr><td colspan=\"2\"><input type=\"hidden\" value=\""
0284: + poolName + "\"/></td></tr>");
0285: writeData("<tr><td colspan=\"2\"><input type=\"submit\" value=\"Update Pool Now\"/></td></tr>");
0286:
0287: writeData("</table></form>");
0288: writeData("<p>If you update the pool settings, the existing pool will be restarted in order for the settings to take effect. Any running connections/SQL will NOT be affected - their jobs will finish normally, and then those connections will be retired.</p>");
0289: } else {
0290: writeData("<p>Sorry, cannot find pool under name '"
0291: + poolName + "'</p>");
0292: }
0293:
0294: writeBottom();
0295:
0296: } else if (resource.equals("/webconsole.css")) {
0297: writeCSS();
0298: } else if (resource.startsWith("/poolStop")) {
0299: String poolName = httpRequest.getParameters().get(
0300: "poolName");
0301: Pool pool = findPoolByName(poolName);
0302:
0303: try {
0304: pool.stop(false);
0305:
0306: } catch (PoolException pe) {
0307: logger.printStackTrace(pe);
0308: }
0309:
0310: writeHeaders("text/html", "/showPool?poolName="
0311: + pool.getPoolName(), 302, 0);
0312:
0313: } else if (resource.startsWith("/poolStart")) {
0314: String poolName = httpRequest.getParameters().get(
0315: "poolName");
0316: Pool pool = findPoolByName(poolName);
0317: try {
0318: pool.start();
0319:
0320: } catch (PoolException pe) {
0321: logger.printStackTrace(pe);
0322:
0323: }
0324: writeHeaders("text/html", "/showPool?poolName="
0325: + pool.getPoolName(), 302, 0);
0326:
0327: } else if (resource.startsWith("/poolRestart")) {
0328: String poolName = httpRequest.getParameters().get(
0329: "poolName");
0330: Pool pool = findPoolByName(poolName);
0331:
0332: try {
0333: pool.restart(false);
0334:
0335: } catch (PoolException pe) {
0336: logger.printStackTrace(pe);
0337: }
0338: writeHeaders("text/html", "/showPool?poolName="
0339: + pool.getPoolName(), 302, 0);
0340:
0341: } else if (resource.startsWith("/showPool")) {
0342: String poolName = httpRequest.getParameters().get(
0343: "poolName");
0344: Pool pool = findPoolByName(poolName);
0345:
0346: writeHeaders("text/html", "", 200, 0);
0347: writeTop();
0348:
0349: writeData("<table><tr><td><table><tr><td>Server date : "
0350: + new java.util.Date() + "</td></tr>");
0351: int numberOfWaitingThreads = pool
0352: .getNumberOfWaitingThreads();
0353: if (numberOfWaitingThreads > 0) {
0354: writeData("<tr><td><span style='color:red'>Warning ! There are "
0355: + numberOfWaitingThreads
0356: + " threads waiting for a connection.</span> You may want to increase your base pool size.</td></tr>");
0357: }
0358: writeData("<tr><td>Total number of connections handed out : "
0359: + pool.getTotalConnectionsHandedOut()
0360: + "</td></tr>");
0361: writeData("<tr><td><a href=\"/showPoolConfig?poolName="
0362: + poolName
0363: + "\">Edit runtime config properties</a></td></tr></table></td><td> </td>");
0364:
0365: writeData("<td><table><tr><td><a href=\"/poolStop?poolName="
0366: + poolName + "\">Stop Pool</a></td></tr>");
0367: writeData("<tr><td><a href=\"/poolStart?poolName="
0368: + poolName + "\">Start Pool</a></td></tr>");
0369: writeData("<tr><td><a href=\"/poolRestart?poolName="
0370: + poolName
0371: + "\">Restart Pool</a></td></tr></table></td></tr></table>");
0372:
0373: if (pool != null) {
0374: writeData("<p/><h5>Connection Data</h5>");
0375: Vector<ConnectionHolder> connections = pool
0376: .getPoolConnections();
0377: writeData("<table border=\"1\">");
0378: writeData("<tr><td><h5>ID</h5></td>"
0379: + "<td><h5>Status</h5></td>"
0380: + "<td><h5>Opens</h5></td>"
0381: + "<td><h5>Closes</h5></td>"
0382: + "<td><h5>CallableStatement</h5></td>"
0383: + "<td><h5>PreparedStatement</h5></td>"
0384: + "<td><h5>Statement</h5></td>"
0385: + "<td><h5>Active For</h5></td>"
0386: + "<td><h5>Idle For</h5></td>"
0387: + "<td><h5>SQL</h5></td></tr>");
0388:
0389: for (ConnectionHolder ch : connections) {
0390: String status = PoolData
0391: .getStringStatus(Pool.UNKNOWN_STATUS_CODE);
0392: String inusefor = "n/a";
0393: String idlefor = "n/a";
0394: if (ch.status == Pool.CONNECTION_ACTIVE) {
0395: status = "<span style='color:red'>"
0396: + PoolData
0397: .getStringStatus(ch.status)
0398: + "</span>";
0399: inusefor = ((System.currentTimeMillis() - ch.connOpenedDate) / 1000)
0400: + " secs";
0401:
0402: } else if (ch.status == Pool.CONNECTION_INACTIVE) {
0403: status = "<span style='color:green'>"
0404: + PoolData
0405: .getStringStatus(ch.status)
0406: + "</span>";
0407: if (ch.lastUsedTimestamp > 0L) {
0408: idlefor = ((System.currentTimeMillis() - ch.lastUsedTimestamp) / 1000)
0409: + " secs";
0410: }
0411:
0412: }
0413:
0414: writeData("<tr><td>" + ch.conn.hashCode()
0415: + "</td><td>" + status + "</td>"
0416: + "<td>" + ch.numberOfOpens + "</td>"
0417: + "<td>" + ch.numberOfCloses + "</td>"
0418: + "<td>"
0419: + ch.numberOfJDBCCallableStatementsRun
0420: + "</td>" + "<td>"
0421: + ch.numberOfJDBCPreparedStatementsRun
0422: + "</td>" + "<td>"
0423: + ch.numberOfJDBCStatementsRun
0424: + "</td>" + "<td>" + inusefor + "</td>"
0425: + "<td>" + idlefor + "</td>" + "<td>"
0426: + ch.sql + "</td></tr>");
0427: }
0428: writeData("</table>");
0429:
0430: writeData("<br/><p>"
0431: + "ID - The PoolConnection class hashCode()<br/>"
0432: + "Status - The Status of the connection<br/>"
0433: + "Opens - How many times this connection has been extracted from the pool<br/>"
0434: + "Closes - How many times this connection has been returned to the pool<br/>"
0435: + "CallableStatement - How many JDBC CallableStatement objects have been created from this connection<br/>"
0436: + "PreparedStatement - How many JDBC PreparedStatement objects have been created from this connection<br/>"
0437: + "Statement - How many JDBC Statement objects have been created from this connection<br/>"
0438: + "Active For - How many seconds this connection has been in use for(if active)<br/>"
0439: + "Idle For - How many seconds this connection has been idle for (if inactive)<br/>"
0440: + "SQL - The current executing SQL on this connection (if any)</p>");
0441: } else {
0442: writeData("<p>Sorry, cannot find pool under name '"
0443: + poolName + "'</p>");
0444: }
0445:
0446: writeBottom();
0447: } else if (resource.startsWith("/alterPoolProperties")) {
0448: Pool pool = findPoolByName(httpRequest.parameters
0449: .get("PoolName"));
0450: Iterator<String> parametersIter = httpRequest.parameters
0451: .keySet().iterator();
0452: while (parametersIter.hasNext()) {
0453: String key = parametersIter.next();
0454: String value = httpRequest.parameters.get(key);
0455: if (!key.equals("PoolName")) {
0456: try {
0457: logger
0458: .info("[WebConsole] alterPoolProperties() Setting "
0459: + key + "=" + value);
0460: Util
0461: .callClassMethod(Pool.class, pool,
0462: "set" + key,
0463: new Object[] { value });
0464: } catch (GeneralException ge) {
0465: showErrorPage("Error setting property "
0466: + key + " : " + ge);
0467: return;
0468: }
0469: }
0470: }
0471:
0472: try {
0473: pool.restart(false);
0474:
0475: } catch (PoolException pe) {
0476: showErrorPage("Error restarting pool : " + pe);
0477: }
0478:
0479: writeHeaders("text/html", "/showPool?poolName="
0480: + pool.getPoolName(), 302, 0);
0481:
0482: }
0483: }
0484:
0485: private void showErrorPage(String error) throws IOException {
0486: writeHeaders("text/html", "", 200, 0);
0487: writeTop();
0488: writeData(error);
0489: writeBottom();
0490:
0491: }
0492:
0493: private Pool findPoolByName(String poolName) {
0494: for (Pool pool : loadedPools) {
0495: if (pool.getPoolName().equals(poolName)) {
0496: return pool;
0497: }
0498: }
0499: return null;
0500: }
0501:
0502: private void writeHeaders(String contentType,
0503: String szExtraData, int iHttpStatusCode,
0504: int iContentLength) throws IOException {
0505:
0506: if (iHttpStatusCode == 500) {
0507: writeData("HTTP/1.1 500 " + szExtraData + ";");
0508: } else if (iHttpStatusCode == 401) {
0509: writeData("HTTP/1.1 401 Authenitcation Required;");
0510: writeData("WWW-Authenticate: Basic realm=\"Primrose Web Console\"");
0511: } else if (iHttpStatusCode == 302) {
0512: writeData("HTTP/1.1 302 Found;");
0513: writeData("Location: " + szExtraData + "");
0514: } else {
0515: writeData("HTTP/1.1 200 OK;");
0516: }
0517: writeData("Date: " + new Date() + "");
0518: writeData("Server: Primrose Web Console");
0519: writeData("LastModified: " + new Date() + "");
0520: writeData("Content-Type: " + contentType + "");
0521:
0522: if (iContentLength > 0) {
0523: writeData("Content-Length: " + iContentLength + "");
0524: }
0525:
0526: writeData("Connection:close");
0527: writeData(""); // newline
0528: }
0529:
0530: private void writeData(String data) throws IOException {
0531: data += "\n";
0532: out.write(data.getBytes());
0533: out.flush();
0534: }
0535:
0536: private void writeTop() throws IOException {
0537: writeData("<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'");
0538: writeData(" 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>");
0539:
0540: writeData("<!--<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"");
0541: writeData(" \"http://www.w3.org/TR/html4/strict.dtd\">-->");
0542:
0543: writeData("<html lang=\"en\">");
0544: writeData(" <head>");
0545: writeData(" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\"/>");
0546: writeData(" <style type=\"text/css\"><!-- ");
0547: writeData(" @import \"/webconsole.css\"; ");
0548: writeData(" --></style>");
0549: writeData(" <title>Primrose Web Console</title>");
0550: writeData(" </head>");
0551: writeData(" <body>");
0552: writeData(" <div id=\"pageWrapper\">");
0553:
0554: writeData(" ");
0555: writeData(" <!-- masthead content begin -->");
0556: writeData(" ");
0557: writeData("<!--banner -->");
0558: writeData("<div id=\"bannerOuterWrapper\">");
0559: writeData(" <div id=\"bannerWrapper\">");
0560: writeData(" ");
0561: writeData(" ");
0562: writeData(" <h1><a href=\"http://www.primrose.org.uk\"><img style=\"border:0\" src=\"http://www.primrose.org.uk/images/primrose_logo.jpg\" alt=\"Primrose Logo\" /></a></h1>");
0563:
0564: writeData(" </div>");
0565: writeData("</div> ");
0566: writeData(" <!-- masthead content end -->");
0567: writeData(" ");
0568: writeData(" <!-- horizontal nav begin -->");
0569: writeData(" <div class=\"hnav\">");
0570: writeData(" <hr class=\"hide\"/>");
0571: writeData("</div>");
0572:
0573: writeData(" <!-- horizontal nav end -->");
0574:
0575: writeData("<!--- middle (main content) column begin -->");
0576: writeData(" <div id=\"outerColumnContainer\">");
0577: writeData(" <div id=\"innerColumnContainer\">");
0578: writeData(" <div id=\"SOWrap\">");
0579: writeData(" <div id=\"middleColumn\">");
0580: writeData(" <div class=\"inside\">");
0581: }
0582:
0583: private void writeBottom() throws IOException {
0584:
0585: writeData(" <hr class=\"hide\"/>");
0586: writeData(" </div>");
0587: writeData("</div>");
0588:
0589: writeData("<!--- middle (main content) column end -->");
0590:
0591: writeData("<!--- left column begin -->");
0592:
0593: writeData(" <div id=\"leftColumn\">");
0594: writeData(" <div class=\"inside\">");
0595: writeData("<div class=\"vnav\"><p> </p></div>");
0596: writeData("<div class=\"vnav\">");
0597:
0598: writeData(" <h3> </h3>");
0599: writeData(" <h3>Site Navigation</h3>");
0600: writeData(" <p></p>");
0601:
0602: writeData(" <ul");
0603: writeData(" ><li");
0604: writeData(" ><a href=\"/\">Home</a");
0605: writeData(" ></li");
0606:
0607: for (Pool pool : loadedPools) {
0608: writeData(" ><li");
0609: writeData(" ><a href=\"/showPool?poolName="
0610: + pool.getPoolName() + "\">Show '"
0611: + pool.getPoolName() + "' Pool</a");
0612: writeData(" ></li");
0613:
0614: }
0615:
0616: writeData(" ");
0617: writeData(" ></ul>");
0618: writeData("</div>");
0619:
0620: writeData(" <hr class=\"hide\"/>");
0621: writeData(" </div>");
0622: writeData(" </div>");
0623: writeData(" <div class=\"clear\"></div>");
0624: writeData(" </div>");
0625:
0626: writeData("<!--- left column end -->");
0627:
0628: writeData("<!--- right column begin -->");
0629:
0630: writeData(" <div id=\"rightColumn\">");
0631: writeData(" <div class=\"inside\">");
0632:
0633: writeData("<p> </p>");
0634: writeData(" <hr class=\"hide\"/>");
0635: writeData(" </div>");
0636: writeData(" </div>");
0637: writeData(" <div class=\"clear\"></div>");
0638: writeData(" </div>");
0639: writeData(" </div>");
0640:
0641: writeData("<!--- right column end -->");
0642:
0643: writeData("<!-- footer begin -->");
0644: writeData(" <!-- horizontal nav begin -->");
0645: writeData(" <div class=\"hnav\">");
0646: writeData(" <hr class=\"hide\"/>");
0647: writeData("</div>");
0648:
0649: writeData(" <!-- horizontal nav end -->");
0650: writeData("<div id=\"bannerWrapperRepeat\">");
0651: writeData(" ");
0652: writeData(" ");
0653: writeData(" <div id=\"footer\">");
0654:
0655: writeData(" <p style=\"margin:0;\">");
0656: writeData(" © www.primrose.org.uk<br/>");
0657: writeData(" ");
0658: writeData(" <a href=\"http://www.primrose.org.uk\"><img style=\"border:0;\"");
0659: writeData(" src=\"http://www.primrose.org.uk/images/primrose_powered_by_centre_small.jpg\"");
0660: writeData(" alt=\"Powered By Primrose\"/></a> ");
0661: writeData(" </p> ");
0662:
0663: writeData(" </div>");
0664:
0665: writeData("</div> ");
0666:
0667: writeData("<!-- footer end -->");
0668:
0669: writeData(" </div>");
0670: writeData(" </body>");
0671: writeData("</html>");
0672:
0673: }
0674:
0675: private void writeCSS() throws IOException {
0676: writeData("@charset \"iso-8859-1\";");
0677:
0678: writeData("/* begin with generic selectors so that they can be overridden if needed");
0679: writeData(" * by classes deeper in the stylesheet");
0680: writeData(" */");
0681: writeData(".clear");
0682: writeData("{");
0683: writeData(" clear: both;");
0684: writeData(" padding-bottom: 1px; /* for Gecko-based browsers */");
0685: writeData(" margin-bottom: -1px; /* for Gecko-based browsers */");
0686: writeData("}");
0687: writeData(".hide");
0688: writeData("{");
0689: writeData(" display: none !important;");
0690: writeData("}");
0691: writeData(".inside");
0692: writeData("{");
0693: writeData(" /* glitch in IE caused by vertical padding in this class, so 0 padding is");
0694: writeData(" * set here and those blocks that need the vertical padding must be ");
0695: writeData(" * applied to the parent element. the purpose of this class is to provide");
0696: writeData(" * horizontal padding without using hacks to get around IE's broken box ");
0697: writeData(" * model. so it's okay to apply vertical padding to the parent element, ");
0698: writeData(" * just not horizontal padding.");
0699: writeData(" */");
0700: writeData(" padding: 0 1em;");
0701: writeData("}");
0702:
0703: writeData("/* margin values and font sizes for headings, and margins on paragraphs");
0704: writeData(" * and lists are not consistent across browser platforms. to achieve a");
0705: writeData(" * consistent look we need to explicity set these values here. it may");
0706: writeData(" * seem an odd way to declare the margins like this but you never");
0707: writeData(" * know what kind of horizontal padding a browser may be using on an");
0708: writeData(" * element, and I only want to change the vertical padding.");
0709: writeData(" *");
0710: writeData(" * pixels are used here, rather than ems, because I want a consistent");
0711: writeData(" * margin on the different headings. if I use ems, 1em for an h1 element");
0712: writeData(" * is much larger than 1em on an h6 element. I don't wnat this.");
0713: writeData(" *");
0714: writeData(" * salt to taste");
0715: writeData(" */");
0716: writeData("ul, ol, dl, p, h1, h2, h3, h4, h5, h6");
0717: writeData("{");
0718: writeData(" margin-top: 14px;");
0719: writeData(" margin-bottom: 14px;");
0720: writeData(" padding-top: 0;");
0721: writeData(" padding-bottom: 0;");
0722: writeData("}");
0723: writeData("h1");
0724: writeData("{");
0725: writeData(" font-size: 220%;");
0726: writeData("}");
0727: writeData("h2");
0728: writeData("{");
0729: writeData(" font-size: 160%;");
0730: writeData(" color: #4411A1;");
0731: writeData("}");
0732: writeData("h3");
0733: writeData("{");
0734: writeData(" font-size: 160%;");
0735: writeData(" color: #4411A1;");
0736: writeData("}");
0737: writeData("h4");
0738: writeData("{");
0739: writeData(" font-size: 130%;");
0740: writeData(" color: #4411A1;");
0741: writeData("}");
0742: writeData("h5");
0743: writeData("{");
0744: writeData(" margin-top: 0px;");
0745: writeData(" margin-bottom: 0px;");
0746: writeData(" font-size: 100%;");
0747: writeData(" color: #4411A1;");
0748: writeData("}");
0749: writeData("h6");
0750: writeData("{");
0751: writeData(" font-size: 70%;");
0752: writeData(" color: #4411A1;");
0753: writeData("}");
0754:
0755: writeData("/* alter some HTML elements' default style");
0756: writeData(" */");
0757: writeData("a, a:link, a:visited, a:active");
0758: writeData("{");
0759: writeData(" text-decoration: underline;");
0760: writeData(" color: #3388CC;");
0761: writeData("}");
0762: writeData("a:hover");
0763: writeData("{");
0764: writeData(" text-decoration: none;");
0765: writeData("}");
0766: writeData("code");
0767: writeData("{");
0768: writeData(" font-family: \"Courier New\", Courier, monospace;");
0769: writeData("}");
0770: writeData("label");
0771: writeData("{");
0772: writeData(" cursor: pointer;");
0773: writeData("}");
0774: writeData("table");
0775: writeData("{");
0776: writeData(" font-size: 100%;");
0777: writeData("}");
0778: writeData("td, th");
0779: writeData("{");
0780: writeData(" vertical-align: top;");
0781: writeData("}");
0782:
0783: writeData("#pageWrapper");
0784: writeData("{");
0785: writeData(" border: solid 1px #fff;");
0786: writeData(" border-width: 0 0px;");
0787: writeData(" min-width: 0em; /* IE doens't understand this property. EMs are used");
0788: writeData(" so that as the font size increases, the proportional");
0789: writeData(" limitations (min-width) increase with it, rather");
0790: writeData(" than creating a middle column that can only fit");
0791: writeData(" 3 or 4 characters in it. */");
0792: writeData(" width: auto;");
0793: writeData("}");
0794: writeData("* html #pageWrapper");
0795: writeData("{");
0796: writeData(" word-wrap: break-word;");
0797: writeData("}");
0798: writeData("#masthead");
0799: writeData("{");
0800: writeData(" border: solid 1px #fff;");
0801: writeData(" border-width: 1px 0;");
0802: writeData(" padding: 0.5em;");
0803: writeData("}");
0804: writeData("#masthead h1");
0805: writeData("{");
0806: writeData(" padding: 0;");
0807: writeData(" margin: 0;");
0808: writeData("}");
0809: writeData("#outerColumnContainer");
0810: writeData("{");
0811: writeData(" /* reserves space for the left and right columns. you can use either");
0812: writeData(" * padding, margins, or borders, depending on your needs. however you");
0813: writeData(" * can use the border method to create a background color for both left");
0814: writeData(" * and right columns");
0815: writeData(" */");
0816: writeData(" border-left: solid 15em #fff;");
0817: writeData(" border-right: solid 0em #fff;");
0818: writeData("}");
0819: writeData("#innerColumnContainer");
0820: writeData("{");
0821: writeData(" border: solid 1px #fff;");
0822: writeData(" border-width: 0 0px;");
0823: writeData(" margin: 0 -1px; /* compensate for the borders because of");
0824: writeData(" 100% width declaration */");
0825: writeData(" width: 100%;");
0826: writeData(" z-index: 1;");
0827: writeData("}");
0828: writeData("#leftColumn, #middleColumn, #rightColumn, * html #SOWrap");
0829: writeData("{");
0830: writeData(" overflow: visible; /* fix for IE italics bug */");
0831: writeData(" position: relative; /* fix some rendering issues */");
0832: writeData("}");
0833: writeData("#SOWrap");
0834: writeData("{");
0835: writeData(" float: left;");
0836: writeData(" margin: 0 -1px 0 0;");
0837: writeData(" width: 100%;");
0838: writeData(" z-index: 3;");
0839: writeData("}");
0840: writeData("#middleColumn");
0841: writeData("{");
0842: writeData(" float: right;");
0843: writeData(" margin: 0 0 0 -1px;");
0844: writeData(" width: 100%;");
0845: writeData(" z-index: 5;");
0846: writeData("}");
0847: writeData("#leftColumn");
0848: writeData("{");
0849: writeData(" float: left;");
0850: writeData(" margin: 0 1px 0 -15em;");
0851: writeData(" width: 15em;");
0852: writeData(" z-index: 4;");
0853: writeData("}");
0854: writeData("#rightColumn");
0855: writeData("{");
0856: writeData(" float: right;");
0857: writeData(" /*width: 14em;");
0858: writeData(" margin: 0 -14em 0 1px;*/");
0859: writeData(" z-index: 2;");
0860: writeData("}");
0861: writeData("#footer");
0862: writeData("{");
0863: writeData(" border: solid 1px #fff;");
0864: writeData(" border-width: 1px 0;");
0865: writeData(" padding: 0.5em;");
0866: writeData("}");
0867:
0868: writeData("p.fontsize-set");
0869: writeData("{");
0870: writeData(" text-align: center;");
0871: writeData("}");
0872: writeData("p.fontsize-set img");
0873: writeData("{");
0874: writeData(" border-width: 0;");
0875: writeData("}");
0876:
0877: writeData(".vnav");
0878: writeData("{");
0879: writeData(" margin: 1em 0;");
0880: writeData("}");
0881: writeData(".vnav ul, .vnav ul li");
0882: writeData("{");
0883: writeData(" margin: 0;");
0884: writeData(" padding: 0;");
0885: writeData(" list-style-type: none;");
0886: writeData(" display: block;");
0887: writeData("}");
0888: writeData(".vnav ul");
0889: writeData("{");
0890: writeData(" border: solid 1px #fff;");
0891: writeData(" border-bottom-width: 0;");
0892: writeData("}");
0893: writeData(".vnav ul li");
0894: writeData("{");
0895: writeData(" border-bottom: solid 1px #fff;");
0896: writeData("}");
0897: writeData(".vnav ul li, .vnav ul li a");
0898: writeData("{");
0899: writeData(" margin: 0;");
0900: writeData(" display: block;");
0901: writeData(" padding: 0;");
0902: writeData(" line-height: normal;");
0903: writeData("}");
0904: writeData(".vnav ul li a");
0905: writeData("{");
0906: writeData(" display: block;");
0907: writeData(" padding: 2px 5px 3px 5px;");
0908: writeData("}");
0909: writeData(".vnav ul li a, .vnav ul li a:link, .vnav ul li a:visited, .vnav ul li a:active, .vnav ul li a:hover");
0910: writeData("{");
0911: writeData(" text-decoration: none;");
0912: writeData(" cursor: pointer;");
0913: writeData("}");
0914: writeData(".vnav h3");
0915: writeData("{");
0916: writeData(" margin-bottom: 0;");
0917: writeData(" padding-bottom: 0;");
0918: writeData(" font-size: 126%;");
0919: writeData("}");
0920: writeData("* html .vnav ul li a/* hide from IE5.0/Win & IE5/Mac */");
0921: writeData("{");
0922: writeData(" height: 0.01%;");
0923: writeData("}");
0924: writeData("* html .vnav ul");
0925: writeData("{");
0926: writeData(" position: relative; /* IE needs this to fix a rendering problem */");
0927: writeData("}");
0928:
0929: writeData("/* horizontal navigation elements. create a DIV element with the class hnav");
0930: writeData(" * and stick one unordered list inside it to generate a horizontal menu.");
0931: writeData(" */");
0932: writeData(".hnav");
0933: writeData("{");
0934: writeData(" border-bottom: solid 1px #fff;");
0935: writeData(" text-align: center;");
0936: writeData("}");
0937: writeData(".hnav, .hnav ul li a");
0938: writeData("{");
0939: writeData(" padding-top: 3px;");
0940: writeData(" padding-bottom: 4px;");
0941: writeData("}");
0942: writeData(".hnav ul, .hnav ul li");
0943: writeData("{");
0944: writeData(" display: inline;");
0945: writeData(" list-style-type: none;");
0946: writeData(" margin: 0;");
0947: writeData(" padding: 0;");
0948: writeData("}");
0949: writeData(".hnav ul li a");
0950: writeData("{");
0951: writeData(" margin: 0 -1px 0 0;");
0952: writeData(" padding-left: 10px;");
0953: writeData(" padding-right: 10px; /* short-hand padding attribute would overwrite");
0954: writeData(" top/bottom padding set in a previous rule */");
0955: writeData(" border-left: solid 1px #000;");
0956: writeData(" border-right: solid 1px #000;");
0957: writeData(" white-space: nowrap;");
0958: writeData("}");
0959: writeData(".hnav ul li a:link, .hnav ul li a:visited, .hnav ul li a:active, .hnav ul li a:hover");
0960: writeData("{");
0961: writeData(" text-decoration: none;");
0962: writeData("}");
0963: writeData(".hnav ul li span.divider");
0964: writeData("{");
0965: writeData(" display: none;");
0966: writeData("}");
0967: writeData("* html .hnav ul li, * html .hnav ul li a");
0968: writeData("{");
0969: writeData(" width: 1%; /* IE/Mac needs this */");
0970: writeData(" display: inline-block; /* IE/Mac needs this */");
0971: writeData(" width: auto;");
0972: writeData(" display: inline;");
0973: writeData(" /* reset above hack */");
0974: writeData("}");
0975: writeData("* html .hnav, * html .hnav ul a");
0976: writeData("{");
0977: writeData(" height: 0.01%; /* hasLayout hack to fix render bugs in IE/Win. ");
0978: writeData(" IE/Mac will ignore this rule. */");
0979: writeData("}");
0980: writeData("* html .HNAV");
0981: writeData("{");
0982: writeData(" padding: 0; /* IE5/Win will resize #hnav to fit the heights of its");
0983: writeData(" inline children that have vertical padding. So this");
0984: writeData(" incorrect case selector hack will be applied only by");
0985: writeData(" IE 5.x/Win */");
0986: writeData("}");
0987:
0988: writeData("/* everything below this point is related to the page's \"theme\" and could be");
0989: writeData(" * placed in a separate stylesheet to allow for multiple color/font scemes on");
0990: writeData(" * the layout. you should probably leave a default theme within this stylesheet");
0991: writeData(" * just to be on the safe side. ");
0992: writeData(" */");
0993: writeData("#pageWrapper, #masthead, #innerColumnContainer, #footer, .vnav ul, .vnav ul li, .hnav, .hnav ul li a");
0994: writeData("{");
0995: writeData(" border-color: #565;");
0996: writeData("}");
0997: writeData("html, body");
0998: writeData("{");
0999: writeData(" /* note that both html and body elements are in the selector.");
1000: writeData(" * this is because we have margins applied to the body element");
1001: writeData(" * and the HTML's background property will show through if");
1002: writeData(" * it is ever set. _DO_NOT_ apply a font-size value to the");
1003: writeData(" * html or body elements, set it in #pageWrapper.");
1004: writeData(" */");
1005: writeData(" background-color: #eee;");
1006: writeData(" color: #000;");
1007: writeData(" font-family: Verdana, Arial, Tahoma;");
1008: writeData(" font-size: 14px; ");
1009: writeData(" margin:0px;");
1010: writeData(" ");
1011: writeData("}");
1012: writeData("#pageWrapper");
1013: writeData("{");
1014: writeData(" font-size: 80%; /* set your default font size here. */");
1015: writeData("}");
1016: writeData("#masthead");
1017: writeData("{");
1018: writeData(" background-color: #4411A1;");
1019: writeData(" color: #fff;");
1020: writeData("}");
1021:
1022: writeData("#bannerOuterWrapper {");
1023: writeData(" height:100px;");
1024: writeData(" background-color: #fff;");
1025: writeData("}");
1026:
1027: writeData("#bannerWrapper {");
1028: writeData(" height:100px;");
1029:
1030: writeData("}");
1031: writeData("#bannerWrapperRepeat {");
1032: writeData(" height:100px;");
1033:
1034: writeData("}");
1035:
1036: writeData(".logo_text {");
1037: writeData(" font-size: 220%;");
1038: writeData(" font-weight:bold;");
1039: writeData(" color:#CCCCFF;");
1040:
1041: writeData("}");
1042: writeData(".logo_body_text {");
1043: writeData(" font-size: 100%;");
1044: writeData(" font-weight:bold;");
1045: writeData(" color:#4411A1;");
1046:
1047: writeData("}");
1048:
1049: writeData(".hnav");
1050: writeData("{");
1051: writeData(" background-color: #CCCCFF;");
1052: writeData(" color: #fff;");
1053: writeData(" border:0;");
1054: writeData("}");
1055: writeData("#outerColumnContainer");
1056: writeData("{");
1057: writeData(" border-left-color: #CCCCFF; /* left column background color */");
1058: writeData(" border-right-color: #CCCCFF; /* right column background color */");
1059: writeData(" background-color: #fff; /* set the background color for the");
1060: writeData(" middle column here */");
1061: writeData("}");
1062: writeData(".vnav ul li a:link, .vnav ul li a:visited, .vnav ul li a:active");
1063: writeData("{");
1064: writeData(" text-decoration: none;");
1065: writeData(" background-color: #4411A1;");
1066: writeData(" color: #FFF;");
1067: writeData("}");
1068: writeData("#rightColumn .vnav ul li a:link, #rightColumn .vnav ul li a:visited, #rightColumn .vnav ul li a:active");
1069: writeData("{");
1070: writeData(" background-color: #ded;");
1071: writeData("}");
1072: writeData(".vnav ul li a:hover, #rightColumn .vnav ul li a:hover");
1073: writeData("{");
1074: writeData(" text-decoration: none;");
1075: writeData(" background-color: #FFFFFF;");
1076: writeData(" color: #000000;");
1077: writeData("}");
1078: writeData(".hnav ul li a:link, .hnav ul li a:visited");
1079: writeData("{");
1080: writeData(" background-color: #4411A1;");
1081: writeData(" color: #fff;");
1082: writeData("}");
1083: writeData(".hnav ul li a:hover");
1084: writeData("{");
1085: writeData(" background-color: #FFF;");
1086: writeData(" color: #000;");
1087: writeData(" text-decoration: none;");
1088: writeData("}");
1089:
1090: writeData(".login_box");
1091: writeData("{");
1092: writeData(" font-family: Verdana, Arial, Tahoma;");
1093: writeData(" font-size: 10px; ");
1094: writeData(" border-style: solid;");
1095: writeData(" border-width: 3px; ");
1096: writeData(" border-color: #4411A1;");
1097: writeData(" color: #4411A1;");
1098: writeData(" background-color: #FFF;");
1099: writeData(" padding-bottom:5px;");
1100: writeData(" padding-left:3px;");
1101: writeData("}");
1102:
1103: writeData("input ");
1104: writeData("{");
1105: writeData(" font-family: Verdana, Arial, Tahoma;");
1106: writeData(" font-size: 10px; ");
1107: writeData(" border-style: solid;");
1108: writeData(" border-width: 1px; ");
1109: writeData(" border-color: #4411A1;");
1110: writeData(" background-color: #FFFFFF;");
1111: writeData(" color:#4411A1;");
1112: writeData("}");
1113:
1114: writeData("select ");
1115: writeData("{");
1116: writeData(" font-family: Verdana, Arial, Tahoma;");
1117: writeData(" font-size: 10px; ");
1118: writeData(" border-style: solid;");
1119: writeData(" border-width: 1px; ");
1120: writeData(" border-color: #4411A1;");
1121: writeData(" background-color: #FFFFFF;");
1122: writeData(" color:#4411A1;");
1123: writeData("}");
1124:
1125: writeData(".profile_table");
1126: writeData("{");
1127: writeData(" font-family: Verdana, Arial, Tahoma;");
1128: writeData(" font-size: 10px; ");
1129: writeData(" border-style: solid;");
1130: writeData(" border-width: 1px; ");
1131: writeData(" border-color: #4411A1;");
1132: writeData(" background-color: #FFFFFF;");
1133: writeData(" color:#000;");
1134: writeData("}");
1135:
1136: writeData("#rightColumn .inside");
1137: writeData("{");
1138: writeData(" /* if you apply a font size to just #rightColumn, then its width,");
1139: writeData(" * which is specified in EMs, will also be affected. you don't want");
1140: writeData(" * that. so apply font size changes to the .inside element which exists");
1141: writeData(" * inside underneath all three columns");
1142: writeData(" */");
1143: writeData(" font-size: 90%;");
1144: writeData("}");
1145: writeData("#rightColumn .inside .vnav");
1146: writeData("{");
1147: writeData(" font-size: 110%;");
1148: writeData("}");
1149: writeData("#footer");
1150: writeData("{");
1151: writeData(" border:0;");
1152: writeData(" color: #4411A1;");
1153: writeData(" text-align: center;");
1154: writeData("}");
1155:
1156: writeData(".input_plain {");
1157: writeData(" color:#000;");
1158: writeData("}");
1159:
1160: writeData("/******************************************************************************/");
1161:
1162: }
1163: }
1164:
1165: }
|