home *** CD-ROM | disk | FTP | other *** search
Java Source | 1998-11-05 | 19.1 KB | 545 lines |
- // Copyright (c) 1997, 1998 Symantec, Inc. All Rights Reserved.
-
- // Static utility routines for the web log analyzer
-
- import java.awt.Rectangle;
- import java.awt.Component;
- import java.awt.Window;
- import java.awt.Frame;
- import java.awt.Dialog;
- import java.awt.TextField;
- import java.util.Date;
- import java.text.DateFormat;
- import java.text.SimpleDateFormat;
- /*
- This class encapsulates miscellaneous static utility routines used by the
- web log analyzer.
- */
- final class WLAUtil {
- // Time conversion constants
- static final long MILLISECS_PER_SECOND = 1000;
- static final long MILLISECS_PER_MINUTE = 1000L*60L;
- static final long MILLISECS_PER_HOUR = 1000L*60L*60L;
- static final long MILLISECS_PER_DAY = 1000L*60L*60L*24L;
- static final long MILLISECS_PER_WEEK = 1000L*60L*60L*24L*7L;
- static final long MILLISECS_PER_YEAR = 1000L*60L*60L*24L*7L*52L;
- static final long DAYS_AGO[] = {
- MILLISECS_PER_DAY,
- MILLISECS_PER_DAY * 6L,
- MILLISECS_PER_DAY * 14L,
- MILLISECS_PER_DAY * 29L,
- MILLISECS_PER_DAY * 59L,
- MILLISECS_PER_DAY * 89L
- };
- static final String TIME_INTERVAL_CP_NAMES[] = {
- "Minutes", "Hours", "Days", "Weeks", "Years"
- };
- static final String TIME_INTERVAL_LS_NAMES[] = {
- "minute", "hour", "day", "week", "year"
- };
- // Time formaters
- static DateFormat dateFormat = makeGoodFor2000(DateFormat.getDateInstance(DateFormat.SHORT));
- static DateFormat dateTimeFormat = makeGoodFor2000(DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM));
- static DateFormat dateTimeLongFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.MEDIUM);
- static DateFormat timeFormat = DateFormat.getTimeInstance(DateFormat.SHORT);
- // for recursion protection of the fatalProgramError method
- static boolean bFatalProgramError = false;
-
- /*
- This is an all-static class.
- Make the constructor private to no one accidentally tries to instantiate it.
- */
- private WLAUtil() {
- //{{INIT_CONTROLS
- //}}
- }
-
- /*
- Called when an unexpected error occurs (due to programming bug, etc).
- Prints a stack trace to stderr, displays an alert, then exits the program.
- */
- public static void fatalProgramError() {
- fatalProgramError(null);
- }
-
- /*
- Called when an unexpected error occurs (due to programming bug, etc).
- Prints a stack trace to stderr, displays an alert, then exits the program.
- If an exception is provided, uses that for its message and stack trace.
- */
- public static void fatalProgramError(Throwable x) {
- // Send error info to std err
- System.err.println("Fatal program error:");
- if(x == null) {
- x = new Throwable();
- } else {
- System.err.println(x.toString());
- }
- x.printStackTrace();
- System.err.flush();
- // Try to display err message before stopping program
- if(!bFatalProgramError && WebLogAnalyzer.theWLA != null) {
- // protect against recursion
- bFatalProgramError = true;
- new AlertDialog(WebLogAnalyzer.theWLA,
- false,
- "Fatal progam error (software bug!)."
- );
- bFatalProgramError = false;
- }
- // Exit program
- System.exit(-1);
- }
-
- /*
- Parses date & time text (in local timezone), returning Date.
- Throws a ParseException if a problem occurs.
- */
- static Date string2DateTime(String dateTimeString) throws java.text.ParseException {
- Date d;
- // first assume time is included
- try {
- d = dateTimeFormat.parse(dateTimeString);
- return d;
- } catch(java.text.ParseException x) {
- }
- // try without time
- d = dateFormat.parse(dateTimeString);
- return d;
- }
-
- /*
- Parses date text (in local timezone), returning Date.
- Throws a ParseException if a problem occurs.
- */
- static Date string2Date(String dateString) throws java.text.ParseException {
- return dateFormat.parse(dateString);
- }
-
- /*
- Parses time text (in local timezone), returning Date.
- Throws a ParseException if a problem occurs.
- */
- static Date string2Time(String timeString) throws java.text.ParseException {
- return timeFormat.parse(timeString);
- }
-
- /*
- Converts a Date to a String.
- Returns a date-only string (without time) in the local timezone.
- */
- static String date2String(Date date) {
- return dateFormat.format(date);
- }
-
- /*
- Converts a Date to a String.
- Returns a date & time string in the local timezone.
- */
- static String dateTime2String(Date date) {
- return dateTimeFormat.format(date);
- }
-
- /*
- Converts a date millisecond value (in GMT) to a String.
- Returns a date & time string in the local timezone.
- */
- static String millisecondsTime2String(long ms) {
- return dateTime2String(new Date(ms));
- }
-
- /*
- Converts a Date to a String.
- Returns a verbose date & time string in the local timezone.
- */
- static String dateTime2StringLong(Date date) {
- return dateTimeLongFormat.format(date);
- }
-
- /*
- Converts a time delta in milliseconds to a String.
- Returns an HH:MM:SS formatted string.
- */
- static String timeDelta2String(long millisecs) {
- long hours = millisecs / MILLISECS_PER_HOUR;
- long milliLeft = millisecs - (hours*MILLISECS_PER_HOUR);
- long minutes = milliLeft / MILLISECS_PER_MINUTE;
- milliLeft = milliLeft - (minutes*MILLISECS_PER_MINUTE);
- long seconds = (milliLeft+500) / MILLISECS_PER_SECOND;
- return hours + ":" + minutes + ":" + seconds;
- }
-
- /*
- Converts a H:M:S formatted string into millisecs.
- */
- static long string2TimeDelta(String str) throws java.text.ParseException {
- int idx = 0;
- try {
- int idxEnd = str.indexOf(':');
- long ms = 0;
- ms += MILLISECS_PER_HOUR * Long.parseLong(str.substring(0, idxEnd));
- idx = idxEnd+1;
- idxEnd = str.indexOf(':', idx);
- ms += MILLISECS_PER_MINUTE * Long.parseLong(str.substring(idx, idxEnd));
- idx = idxEnd+1;
- idxEnd = str.length();
- ms += MILLISECS_PER_SECOND * Long.parseLong(str.substring(idx, idxEnd));
- return ms;
- } catch(NumberFormatException x) {
- throw new java.text.ParseException("Invalid time delta numeric format in \"" + str + "\"", idx);
- } catch(ArrayIndexOutOfBoundsException x) {
- throw new java.text.ParseException("Invalid time delta format in \"" + str + "\"", idx);
- }
- }
-
- /*
- Validates the date & time entered in the given TextField.
- If OK, returns true.
- If fails, displays an alert then moves focus to offending TextField.
- */
- static boolean validateDateField(Window dialogOrFrame, TextField dateField) {
- try {
- // Parse the date to ensure OK
- string2Date(dateField.getText());
- // Parsed OK. Passes validation
- return true;
- } catch(java.text.ParseException x) {
- // Can't parse the given date. Move focus to offending field
- dateField.requestFocus();
- dateField.selectAll();
- // Alert user
- new AlertDialog(getFrame(dialogOrFrame), false, x.getMessage());
- return false;
- }
- }
-
- /**
- Centers the given component relative to that component's parent.
- */
- public static void centerInParent(Component comp) {
- Rectangle bounds = comp.getParent().getBounds();
- Rectangle abounds = comp.getBounds();
- comp.setLocation( bounds.x + (bounds.width - abounds.width)/ 2,
- bounds.y + (bounds.height - abounds.height)/2
- );
- }
-
- /*
- Determines the parent Frame of the given Dialog or Frame.
- */
- static Frame getFrame(Window dialogOrFrame) {
- Window w = dialogOrFrame;
- while(w instanceof Dialog) {
- w = (Window)w.getParent();
- }
- return (Frame)w;
- }
-
- /*
- Given a timeframe choice (like: Report.TIMEFRAME_PAST_2_DAYS) returns
- either the appropriate start or end date as text.
- */
- static String timeframeChoice2DateString(int TIMEFRAME_, boolean wantStartDate) {
- if(TIMEFRAME_ == Report.TIMEFRAME_ALL) {
- return "(all dates)";
- }
- if(TIMEFRAME_ == Report.TIMEFRAME_SPECIFIC) {
- fatalProgramError(); // unexpected
- return null;
- }
- Date date = new Date();
- if(TIMEFRAME_ == Report.TIMEFRAME_TODAY) {
- return date2String(date);
- }
- long millisecs = date.getTime() - MILLISECS_PER_DAY;
- if(TIMEFRAME_ != Report.TIMEFRAME_YESTERDAY && wantStartDate) {
- millisecs -= DAYS_AGO[TIMEFRAME_ - Report.TIMEFRAME_PAST_2_DAYS];
- }
- date.setTime(millisecs);
- return date2String(date);
- }
-
- /*
- Given a time interval in milliseconds (like: WLAUtil.MILLISECS_PER_HOUR),
- returns an index value:
- 0="Minutes", 1="Hours", 2="Days", 3="Weeks", 4="Years".
- */
- static int timeInterval2Index(long timeInterval) {
- switch((int)timeInterval) {
- case (int)WLAUtil.MILLISECS_PER_MINUTE:
- return 0;
- case (int)WLAUtil.MILLISECS_PER_HOUR:
- return 1;
- case (int)WLAUtil.MILLISECS_PER_DAY:
- return 2;
- case (int)WLAUtil.MILLISECS_PER_WEEK:
- return 3;
- case (int)WLAUtil.MILLISECS_PER_YEAR:
- return 4;
- default:
- WLAUtil.fatalProgramError();
- return 0;
- }
- }
-
- /*
- Given a time interval in milliseconds (like: WLAUtil.MILLISECS_PER_HOUR),
- returns an appropriate plural word starting with a capitalized letter:
- "Minutes", "Hours", "Days", "Weeks", "Years".
- */
- static String timeInterval2CapPluralString(long timeInterval) {
- return TIME_INTERVAL_CP_NAMES[timeInterval2Index(timeInterval)];
- }
-
- /*
- Given a time interval in milliseconds (like: WLAUtil.MILLISECS_PER_HOUR),
- returns an appropriate singular word starting with a non-capitalized letter:
- "minute", "hour", "day", "week", "year"
- */
- static String timeInterval2LowerSingularString(long timeInterval) {
- return TIME_INTERVAL_LS_NAMES[timeInterval2Index(timeInterval)];
- }
-
- /*
- Given a string as entered by a user, automatically clean it up into the
- desired URL string.
- Sample actions:
- "mylog.log" -> "http://mylog.log/"
- "http://mylog.log" -> "http://mylog.log/"
- "\mylog.log" -> "file:///\mylog.log"
- "c:\mylog.log" -> "file:///c:\mylog.log"
- */
- static String cleanupURLName(String messyURLText) {
- // Infer starting "file://", etc as needed
- try {
- char ch;
- StringBuffer buf;
- // Colon?
- int idx = messyURLText.indexOf(':');
- if(idx < 0) {
- // No colon.
- buf = new StringBuffer(messyURLText.length() + 9);
- ch = messyURLText.charAt(0);
- if(ch == java.io.File.separatorChar) {
- // Presume file entry
- buf.append("file:///");
- buf.append(messyURLText);
- } else {
- //Prepend http:// by default
- buf.append("http://");
- buf.append(messyURLText);
- // if no slashes in messyURL, presume only domain given and end with one
- if(-1 == messyURLText.indexOf('/')) {
- buf.append('/');
- }
- }
- return buf.toString();
- }
- // Have a colon in the messyURLText, look at char after the colon
- ch = messyURLText.charAt(++idx);
- if(ch == '/') {
- ch = messyURLText.charAt(++idx);
- if(ch == '/') {
- idx = messyURLText.indexOf(':', ++idx);
- if(idx < 0) {
- // only initial "//" provided. Add ending one.
- buf = new StringBuffer(messyURLText.length() + 2);
- buf.append(messyURLText);
- buf.append('/');
- return buf.toString();
- }
- }
- // protocol specified. Nothing to do.
- return messyURLText;
- }
- if(ch == '\\') {
- // MSDOS file path. Prefix file: protocol
- return "file:///" + messyURLText;
- }
- //colon, but no slash...do nothing
- } catch(StringIndexOutOfBoundsException x) {
- // if get this, no cleanup
- }
- return messyURLText;
- }
-
- /*
- Allows the user to browse locally for a log file.
- Shows the standard open dialog, then, if the user chooses a file,
- it "cleans up" the filename into a URL using the cleanupURLName()
- method.
- Template is the inititial filename in the open dialog.
- If the user cancels the dialog, null is returned.
- */
- public static String browseForURL(String template) {
- // Access main frame which has the open dialog off it
- WebLogAnalyzer wla = WebLogAnalyzer.theWLA;
-
- // set the default suffix
- wla.openFileURLDialog.setFile(template);
-
- // Show the OpenFileDialog
- wla.openFileURLDialog.show();
-
- // get the results
- String results = wla.openFileURLDialog.getFile();
- if(results != null) {
- results = wla.openFileURLDialog.getDirectory() + results;
- results = WLAUtil.cleanupURLName(results);
- }
- return results;
- }
-
- /*
- This sort routine was modified from Sun's SortDemo, and thus the long copyright, etc.
- The original sorted an array of integers.
- The modified version sorts an array of Objects the implement the Sortable interface.
- */
-
- /*
- * @(#)QSortAlgorithm.java 1.6 96/12/06
- *
- * Copyright (c) 1994-1996 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
- * modify and redistribute this software in source and binary code form,
- * provided that i) this copyright notice and license appear on all copies of
- * the software; and ii) Licensee does not utilize the software in a manner
- * which is disparaging to Sun.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
- * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
- * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
- * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
- * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
- * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
- * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
- * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
- * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGES.
- *
- * This software is not designed or intended for use in on-line control of
- * aircraft, air traffic, aircraft navigation or aircraft communications; or in
- * the design, construction, operation or maintenance of any nuclear
- * facility. Licensee represents and warrants that it will not use or
- * redistribute the Software for such purposes.
- */
-
- public static void quickSort(Sortable a[])
- {
- doQuickSort(a, 0, a.length - 1);
- }
-
- /** This is a generic version of C.A.R Hoare's Quick Sort
- * algorithm. This will handle arrays that are already
- * sorted, and arrays with duplicate keys.<BR>
- *
- * If you think of a one dimensional array as going from
- * the lowest index on the left to the highest index on the right
- * then the parameters to this function are lowest index or
- * left and highest index or right. The first time you call
- * this function it will be with the parameters 0, a.length - 1.
- *
- * @param a an Sortable array
- * @param lo0 left boundary of array partition
- * @param hi0 right boundary of array partition
- */
- private static void doQuickSort(Sortable a[], int lo0, int hi0)
- {
- int lo = lo0;
- int hi = hi0;
- Sortable midObj;
-
- if ( hi0 > lo0)
- {
-
- /* Arbitrarily establishing partition element as the midpoint of
- * the array.
- */
- midObj = a[ ( lo0 + hi0 ) / 2 ];
-
- // loop through the array until indices cross
- while( lo <= hi )
- {
- /* find the first element that is greater than or equal to
- * the partition element starting from the left Index.
- */
- while( ( lo < hi0 ) && midObj.isLessThan(a[lo]))
- ++lo;
-
- /* find an element that is smaller than or equal to
- * the partition element starting from the right Index.
- */
- while( ( hi > lo0 ) && !midObj.isLessThanOrEqual(a[hi]))
- --hi;
-
- // if the indexes have not crossed, swap
- if( lo <= hi )
- {
- // swap
- Sortable T;
- T = a[lo];
- a[lo] = a[hi];
- a[hi] = T;
- //
- ++lo;
- --hi;
- }
- }
-
- /* If the right index has not reached the left side of array
- * must now sort the left partition.
- */
- if( lo0 < hi )
- doQuickSort( a, lo0, hi );
-
- /* If the left index has not reached the right side of array
- * must now sort the right partition.
- */
- if( lo < hi0 )
- doQuickSort( a, lo, hi0 );
-
- }
- }
-
- /*
- Ensures the given DateFormat has 4 year digits so that it may
- handle the year 2000.
- */
- private static DateFormat makeGoodFor2000(DateFormat dateFormat) {
- SimpleDateFormat sdf;
- try {
- sdf = (SimpleDateFormat)dateFormat;
- } catch(ClassCastException x) {
- // can't handle this uncommon dateFormat
- return dateFormat;
- }
- // ensure year displayed as 4 digits
- String pattern = sdf.toLocalizedPattern();
- int i = pattern.indexOf("yyyy");
- if(i != -1) {
- // pattern is already as a 4 digit year
- return dateFormat;
- }
- // modify the pattern so that it has a 4 digit year
- i = pattern.indexOf("yy");
- if(i != -1) {
- pattern = pattern.substring(0,i) + "yyyy" + pattern.substring(i+2, pattern.length());
- sdf = new SimpleDateFormat(pattern);
- }
- return sdf;
- }
- //{{DECLARE_CONTROLS
- //}}
- }
-
-
-
-
-
-
-
-
-
-