Java tutorial
/* Copyright 2007 Creare Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ //package com.rbnb.utility; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; import java.util.Enumeration; import java.util.Hashtable; /****************************************************************************** * Parse a URL into its components. * <p> * Components in the URL include: * * * @author John P. Wilson * * @version 09/28/2006 */ /* * Copyright 2006 Creare Inc. * All Rights Reserved * * Date By Description * MM/DD/YYYY * ---------- -- ----------- * 09/28/2006 JPW RBNB servlet no longer supports special meaning for the * "msg" munge. Therefore, I have removed "msg" as an * RBNB munge. As part of this, I removed the method * getCompleteMessageMunge() and the "message" member * variable. * 09/15/2006 JPW Switch over to using KeyValueHash to parse the munge * 05/10/2006 JPW Created * */ public class ParseURL { // A copy of the original, full URL private String url; // Request protocol, such as "http" or "ftp" private String protocol = null; // The request string, stripped of any protocol and munge options private String request = null; // The original, complete munge string private String munge = null; // RBNB munge options private boolean hasRBNBMunge = false; //EMF 5/12/06 private Double time = null; private Double duration = null; private String reference = null; private String fetch = null; private String byteorder = null; private String datatype = null; private Integer mux = null; private Integer blocksize = null; private String mime = null; // Hashtable of non-RBNB munge options private Hashtable nonRBNBMunge = null; /************************************************************************** * Default constructor. * <p> * * @author John P. Wilson * * @version 05/10/2006 */ /* * * Date By Description * MM/DD/YYYY * ---------- -- ----------- * 05/10/2006 JPW Created * */ public ParseURL() { this(null, false); } /************************************************************************** * Constructor. Call parse() to parse the given URL into its components. * <p> * * @author John P. Wilson * * @param urlStrI The URL to parse. * @param bDebugI Print debug? * * @version 05/10/2006 */ /* * * Date By Description * MM/DD/YYYY * ---------- -- ----------- * 05/10/2006 JPW Created * */ public ParseURL(String urlStrI, boolean bDebugI) { parse(urlStrI, bDebugI); } /************************************************************************** * Parse the given URL into its components. * <p> * This method parses a munged URL such as: * * http://jpw.creare.com:80/RBNB/TestSource?r=newest&t=1.5 * * In this case: * "http" is the protocol * "jpw.creare.com:80/RBNB/TestSource" is the request * "newest" is the reference * "1.5" is the time * * @author John P. Wilson * * @param urlStrI The URL to parse. * @param bDebugI Print debug? * * @version 09/15/2006 */ /* * * Date By Description * MM/DD/YYYY * ---------- -- ----------- * 09/15/2006 JPW Switch over to using KeyValueHash to parse the munge * 05/10/2006 JPW Created * */ public void parse(String urlStrI, boolean bDebugI) { // Reset all member variables resetMemberData(); if ((urlStrI == null) || (urlStrI.trim().equals(""))) { if (bDebugI) { System.err.println("Unable to parse URL: empty string"); } return; } url = new String(urlStrI); if (bDebugI) { System.err.println("URL = \"" + urlStrI + "\""); } //////////////////////////////////////////// // See if a protocol is specified in the URL //////////////////////////////////////////// int colonIndex = urlStrI.indexOf(':'); String requestAndMungeStr = urlStrI; if (colonIndex >= 0) { protocol = urlStrI.substring(0, colonIndex); if ((protocol != null) && (protocol.trim().equals(""))) { protocol = null; } if ((protocol != null) && (bDebugI)) { System.err.println("Protocol = \"" + protocol + "\""); } else if (bDebugI) { System.err.println("Protocol = null"); } requestAndMungeStr = urlStrI.substring(colonIndex + 1); } //////////////////////////////////////////////// // Strip off leading '/' from requestAndMungeStr //////////////////////////////////////////////// while ((requestAndMungeStr != null) && (!requestAndMungeStr.equals("")) && (requestAndMungeStr.charAt(0) == '/')) { requestAndMungeStr = requestAndMungeStr.substring(1); } /////////////////////////////////////////////////////////// // Separate the request from the munge; munge portion could // begin with either '?' or '@' /////////////////////////////////////////////////////////// request = null; munge = null; int mungeStartCharIndex = requestAndMungeStr.indexOf('@'); if (mungeStartCharIndex < 0) { mungeStartCharIndex = requestAndMungeStr.indexOf('?'); } if (mungeStartCharIndex >= 0) { request = requestAndMungeStr.substring(0, mungeStartCharIndex); if ((request != null) && (request.trim().equals(""))) { request = null; } munge = requestAndMungeStr.substring(mungeStartCharIndex + 1); if ((munge != null) && (munge.trim().equals(""))) { munge = null; } } else { //EMF 5/11/06: no munge, all request request = requestAndMungeStr; munge = null; } if (bDebugI) { if (request == null) { System.err.println("Request = null"); } else { System.err.println("Request = \"" + request + "\""); } if (munge == null) { System.err.println("Munge = null"); } else { System.err.println("Munge = \"" + munge + "\""); } } ////////////////////////// // Parse the munge options ////////////////////////// if (munge == null) { // We're all done return; } // JPW 09/15/2006: Use KeyValueHash to parse the munge char[] terminatorChars = { '&' }; KeyValueHash kvh = new KeyValueHash(munge, terminatorChars); Hashtable fullHashtable = kvh.getHash(); if (kvh.get("time") != null) { // Store time as a Double object try { time = new Double(kvh.get("time")); if (bDebugI) { System.err.println("time = " + time); } hasRBNBMunge = true; } catch (NumberFormatException e) { // Nothing to do time = null; } // Remove this entry from the hashtable fullHashtable.remove("time"); } if (kvh.get("t") != null) { // Store time as a Double object try { time = new Double(kvh.get("t")); if (bDebugI) { System.err.println("time = " + time); } hasRBNBMunge = true; } catch (NumberFormatException e) { // Nothing to do time = null; } // Remove this entry from the hashtable fullHashtable.remove("t"); } if (kvh.get("duration") != null) { // Store duration as a Double object try { duration = new Double(kvh.get("duration")); if (bDebugI) { System.err.println("duration = " + duration); } hasRBNBMunge = true; } catch (NumberFormatException e) { // Nothing to do duration = null; } // Remove this entry from the hashtable fullHashtable.remove("duration"); } if (kvh.get("d") != null) { // Store duration as a Double object try { duration = new Double(kvh.get("d")); if (bDebugI) { System.err.println("duration = " + duration); } hasRBNBMunge = true; } catch (NumberFormatException e) { // Nothing to do duration = null; } // Remove this entry from the hashtable fullHashtable.remove("d"); } if (kvh.get("reference") != null) { reference = kvh.get("reference"); if (bDebugI) { System.err.println("reference = " + reference); } hasRBNBMunge = true; // Remove this entry from the hashtable fullHashtable.remove("reference"); } if (kvh.get("r") != null) { reference = kvh.get("r"); if (bDebugI) { System.err.println("reference = " + reference); } hasRBNBMunge = true; // Remove this entry from the hashtable fullHashtable.remove("r"); } if (kvh.get("fetch") != null) { fetch = kvh.get("fetch"); if (bDebugI) { System.err.println("fetch = " + fetch); } hasRBNBMunge = true; // Remove this entry from the hashtable fullHashtable.remove("fetch"); } if (kvh.get("f") != null) { fetch = kvh.get("f"); if (bDebugI) { System.err.println("fetch = " + fetch); } hasRBNBMunge = true; // Remove this entry from the hashtable fullHashtable.remove("f"); } if (kvh.get("byteorder") != null) { byteorder = kvh.get("byteorder"); if (bDebugI) { System.err.println("byteorder = " + byteorder); } hasRBNBMunge = true; // Remove this entry from the hashtable fullHashtable.remove("byteorder"); } if (kvh.get("bo") != null) { byteorder = kvh.get("bo"); if (bDebugI) { System.err.println("byteorder = " + byteorder); } hasRBNBMunge = true; // Remove this entry from the hashtable fullHashtable.remove("bo"); } if (kvh.get("datatype") != null) { datatype = kvh.get("datatype"); if (bDebugI) { System.err.println("datatype = " + datatype); } hasRBNBMunge = true; // Remove this entry from the hashtable fullHashtable.remove("datatype"); } if (kvh.get("dt") != null) { datatype = kvh.get("dt"); if (bDebugI) { System.err.println("datatype = " + datatype); } hasRBNBMunge = true; // Remove this entry from the hashtable fullHashtable.remove("dt"); } if (kvh.get("mux") != null) { // Store mux as an Integer object try { mux = new Integer(kvh.get("mux")); if (bDebugI) { System.err.println("mux = " + mux); } hasRBNBMunge = true; } catch (NumberFormatException e) { // Nothing to do mux = null; } // Remove this entry from the hashtable fullHashtable.remove("mux"); } if (kvh.get("x") != null) { // Store mux as an Integer object try { mux = new Integer(kvh.get("x")); if (bDebugI) { System.err.println("mux = " + mux); } hasRBNBMunge = true; } catch (NumberFormatException e) { // Nothing to do mux = null; } // Remove this entry from the hashtable fullHashtable.remove("x"); } if (kvh.get("blocksize") != null) { // Store blocksize as an Integer object try { blocksize = new Integer(kvh.get("blocksize")); if (bDebugI) { System.err.println("blocksize = " + blocksize); } hasRBNBMunge = true; } catch (NumberFormatException e) { // Nothing to do blocksize = null; } // Remove this entry from the hashtable fullHashtable.remove("blocksize"); } if (kvh.get("bs") != null) { // Store blocksize as an Integer object try { blocksize = new Integer(kvh.get("bs")); if (bDebugI) { System.err.println("blocksize = " + blocksize); } hasRBNBMunge = true; } catch (NumberFormatException e) { // Nothing to do blocksize = null; } // Remove this entry from the hashtable fullHashtable.remove("bs"); } if (kvh.get("mime") != null) { mime = kvh.get("mime"); if (bDebugI) { System.err.println("mime = " + mime); } hasRBNBMunge = true; // Remove this entry from the hashtable fullHashtable.remove("mime"); } if (kvh.get("m") != null) { mime = kvh.get("m"); if (bDebugI) { System.err.println("mime = " + mime); } hasRBNBMunge = true; // Remove this entry from the hashtable fullHashtable.remove("m"); } // What remains in fullHashtable must be the non-RBNB munges if ((fullHashtable != null) && (!fullHashtable.isEmpty())) { nonRBNBMunge = fullHashtable; if (bDebugI) { for (Enumeration e = nonRBNBMunge.keys(); e.hasMoreElements();) { String key = (String) e.nextElement(); String value = (String) nonRBNBMunge.get(key); System.err.println("Non-RBNB munge: key = \"" + key + "\", value = \"" + value + "\""); } } } } /************************************************************************** * Reset member data to default values. * <p> * * @author John P. Wilson * * @version 05/10/2006 */ /* * * Date By Description * MM/DD/YYYY * ---------- -- ----------- * 05/10/2006 JPW Created * */ public void resetMemberData() { url = null; protocol = null; request = null; munge = null; time = null; duration = null; reference = null; fetch = null; byteorder = null; datatype = null; mux = null; blocksize = null; mime = null; nonRBNBMunge = null; } /************************************************************************** * Get the original URL as a String * <p> * * @author John P. Wilson * * @version 05/11/2006 */ /* * * Date By Description * MM/DD/YYYY * ---------- -- ----------- * 05/11/2006 JPW Created * */ public String getURL() { return url; } /************************************************************************** * Get URL protocol as a String * <p> * * @author John P. Wilson * * @version 05/11/2006 */ /* * * Date By Description * MM/DD/YYYY * ---------- -- ----------- * 05/11/2006 JPW Created * */ public String getProtocol() { return protocol; } /************************************************************************** * Get URL request as a String * <p> * * @author John P. Wilson * * @version 05/11/2006 */ /* * * Date By Description * MM/DD/YYYY * ---------- -- ----------- * 05/11/2006 JPW Created * */ public String getRequest() { return request; } /************************************************************************** * Get the URL munge as a String * <p> * * @author John P. Wilson * * @version 05/11/2006 */ /* * * Date By Description * MM/DD/YYYY * ---------- -- ----------- * 05/11/2006 JPW Created * */ public String getMunge() { return munge; } /************************************************************************** * Indicates whether any RBNB munge exists * <p> * * @author Eric M. Friets * * @version 05/12/2006 */ /* * * Date By Description * MM/DD/YYYY * ---------- -- ----------- * 05/12/2006 EMF Created * */ public boolean isRBNBMunge() { return hasRBNBMunge; } /************************************************************************** * Get time munge option as a Double object * <p> * * @author John P. Wilson * * @version 05/11/2006 */ /* * * Date By Description * MM/DD/YYYY * ---------- -- ----------- * 05/11/2006 JPW Created * */ public Double getTime() { return time; } /************************************************************************** * Get duration munge option as a Double object * <p> * * @author John P. Wilson * * @version 05/11/2006 */ /* * * Date By Description * MM/DD/YYYY * ---------- -- ----------- * 05/11/2006 JPW Created * */ public Double getDuration() { return duration; } /************************************************************************** * Set a new duration for the munge. * <p> * * @author John P. Wilson * * @version 06/02/2006 */ /* * * Date By Description * MM/DD/YYYY * ---------- -- ----------- * 06/02/2006 JPW Created * */ public void setDuration(double durationI) { if (durationI >= 0.0) { duration = new Double(durationI); } } /************************************************************************** * Get reference munge option as a String * <p> * * @author John P. Wilson * * @version 05/11/2006 */ /* * * Date By Description * MM/DD/YYYY * ---------- -- ----------- * 05/11/2006 JPW Created * */ public String getReference() { return reference; } /************************************************************************** * Get fetch munge option as a String * <p> * * @author John P. Wilson * * @version 05/11/2006 */ /* * * Date By Description * MM/DD/YYYY * ---------- -- ----------- * 05/11/2006 JPW Created * */ public String getFetch() { return fetch; } /************************************************************************** * Get byteorder munge option as a String * <p> * * @author John P. Wilson * * @version 05/11/2006 */ /* * * Date By Description * MM/DD/YYYY * ---------- -- ----------- * 05/11/2006 JPW Created * */ public String getByteorder() { return byteorder; } /************************************************************************** * Get datatype munge option as a String * <p> * * @author John P. Wilson * * @version 05/11/2006 */ /* * * Date By Description * MM/DD/YYYY * ---------- -- ----------- * 05/11/2006 JPW Created * */ public String getDatatype() { return datatype; } /************************************************************************** * Get mux munge option as an Integer object * <p> * * @author John P. Wilson * * @version 05/11/2006 */ /* * * Date By Description * MM/DD/YYYY * ---------- -- ----------- * 05/11/2006 JPW Created * */ public Integer getMux() { return mux; } /************************************************************************** * Get blocksize munge option as an Integer object * <p> * * @author John P. Wilson * * @version 05/11/2006 */ /* * * Date By Description * MM/DD/YYYY * ---------- -- ----------- * 05/11/2006 JPW Created * */ public Integer getBlocksize() { return blocksize; } /************************************************************************** * Get mime munge option as a String * <p> * * @author John P. Wilson * * @version 05/11/2006 */ /* * * Date By Description * MM/DD/YYYY * ---------- -- ----------- * 05/11/2006 JPW Created * */ public String getMime() { return mime; } /************************************************************************** * Get Hashtable nonRBNBMunge * <p> * * @author John P. Wilson * * @version 05/11/2006 */ /* * * Date By Description * MM/DD/YYYY * ---------- -- ----------- * 05/11/2006 JPW Created * */ public Hashtable getNonRBNBMunge() { return nonRBNBMunge; } /************************************************************************** * Get all non-RBNB munge options concatenated together, using '&' as * the separator character. * <p> * * @author John P. Wilson * * @version 05/11/2006 */ /* * * Date By Description * MM/DD/YYYY * ---------- -- ----------- * 05/11/2006 JPW Created * */ public String getNonRBNBMungeStr() { if (nonRBNBMunge == null) { return null; } StringBuffer mungeStrBuf = null; for (Enumeration e = nonRBNBMunge.keys(); e.hasMoreElements();) { String nextKey = (String) e.nextElement(); String nextValue = (String) nonRBNBMunge.get(nextKey); if (mungeStrBuf == null) { mungeStrBuf = new StringBuffer(nextKey + "=" + nextValue); } else { mungeStrBuf.append("&" + nextKey + "=" + nextValue); } } return mungeStrBuf.toString(); } /************************************************************************** * Default version of this method; include all munge components. * <p> * * @author John P. Wilson * * @version 06/02/2006 */ /* * * Date By Description * MM/DD/YYYY * ---------- -- ----------- * 06/02/2006 JPW Created * */ public String createNewRBNBMunge() { return createNewRBNBMunge(false, false, false, false, false, false, false, false, false, false); } /************************************************************************** * Create a new munge string containing the desired RBNB munge components. * <p> * The user can selectively remove munge components as specified by the * boolean arguments. If the user has not chosen to remove any munge * component, then the original, complete munge string is returned. * * @author John P. Wilson * * @param bRemoveTimeI Remove time from returned munge? * @param bRemoveDurationI Remove duration from returned munge? * @param bRemoveReferenceI Remove reference from returned munge? * @param bRemoveFetchI Remove fetch from returned munge? * @param bRemoveByteorderI Remove byteorder from returned munge? * @param bRemoveDatatypeI Remove datatype from returned munge? * @param bRemoveMuxI Remove mux from returned munge? * @param bRemoveBlocksizeI Remove blocksize from returned munge? * @param bRemoveMimeI Remove mime from returned munge? * @param bRemoveNonRBNBMungeI Remove non RBNB munges from returned munge? * * @version 09/28/2006 */ /* * * Date By Description * MM/DD/YYYY * ---------- -- ----------- * 09/28/2006 JPW Change "bRemoveMessageI" to "bRemoveNonRBNBMungeI" * 06/02/2006 JPW Created * */ public String createNewRBNBMunge(boolean bRemoveTimeI, boolean bRemoveDurationI, boolean bRemoveReferenceI, boolean bRemoveFetchI, boolean bRemoveByteorderI, boolean bRemoveDatatypeI, boolean bRemoveMuxI, boolean bRemoveBlocksizeI, boolean bRemoveMimeI, boolean bRemoveNonRBNBMungeI) { // JPW 09/28/2006: If user has not chosen to remove anything, then // simply return the original, complete munge string. if ((!bRemoveTimeI) && (!bRemoveDurationI) && (!bRemoveReferenceI) && (!bRemoveFetchI) && (!bRemoveByteorderI) && (!bRemoveDatatypeI) && (!bRemoveMuxI) && (!bRemoveBlocksizeI) && (!bRemoveMimeI) && (!bRemoveNonRBNBMungeI)) { return munge; } StringBuffer newMunge = new StringBuffer(); if ((getTime() != null) && (!bRemoveTimeI)) { newMunge.append("&t=" + getTime().toString()); } if ((getDuration() != null) && (!bRemoveDurationI)) { newMunge.append("&d=" + getDuration().toString()); } if ((getReference() != null) && (!bRemoveReferenceI)) { newMunge.append("&r=" + getReference()); } if ((getFetch() != null) && (!bRemoveFetchI)) { newMunge.append("&f=" + getFetch()); } if ((getByteorder() != null) && (!bRemoveByteorderI)) { newMunge.append("&bo=" + getByteorder()); } if ((getDatatype() != null) && (!bRemoveDatatypeI)) { newMunge.append("&dt=" + getDatatype()); } if ((getMux() != null) && (!bRemoveMuxI)) { newMunge.append("&x=" + getMux().toString()); } if ((getBlocksize() != null) && (!bRemoveBlocksizeI)) { newMunge.append("&bs=" + getBlocksize().toString()); } if ((getMime() != null) && (!bRemoveMimeI)) { newMunge.append("&m=" + getMime()); } // JPW 09/28/2006: Return the non RBNB munges as a series of key/value // pairs; don't return them encoded in the "msg" // munge (RBNB servlet doesn't do anything special // with the "msg" munge now). if ((getNonRBNBMungeStr() != null) && (!bRemoveNonRBNBMungeI)) { newMunge.append("&" + getNonRBNBMungeStr()); } if (newMunge.length() == 0) { return null; } // If there is a leading '&', remove it if (newMunge.charAt(0) == '&') { newMunge = newMunge.deleteCharAt(0); } return newMunge.toString(); } } class KeyValueHash { Hashtable hash = new Hashtable(); public KeyValueHash(byte[] userData) { // JPW 09/15/2006: These aren't used //ByteArrayInputStream byteArray = new ByteArrayInputStream(userData); //DataInputStream inStream = new DataInputStream(byteArray); // JPW 09/15/2006: Add new constructor this(new String(userData), null); } public KeyValueHash(String inString) { this(inString, null); } // JPW 09/15/2006: Add new constructor that takes a String and an optional // set of terminating characters public KeyValueHash(String inString, char[] terminatorCharsI) { // The default terminating characters char[] terminatorChars = { ',', '\n', '\r' }; if ((terminatorCharsI != null) && (terminatorCharsI.length > 0)) { terminatorChars = terminatorCharsI; } int lt = -1; // location of the terminator from the previous iteration int nt = nextTerminator(inString, lt, terminatorChars); while (nt != -1) { int ne = inString.indexOf('=', lt + 1); // next equals sign if (ne > lt + 1 && ne < nt - 1) { //have key,value isolated hash.put(inString.substring(lt + 1, ne), inString.substring(ne + 1, nt)); //System.out.println(inString.substring(lt+1,ne)+" "+inString.substring(ne+1,nt)); } lt = nt; while ((nt = nextTerminator(inString, lt, terminatorChars)) == lt + 1) //ignore multiple adjacent separators lt = nt; } } //end KeyValueHash constructor public String get(String key) { // JPW 09/15/2006: Add some checks for null if (key == null) { return null; } Object value = hash.get(key); if (value == null) { return null; } return (String) value; } public Hashtable getHash() { return hash; } private int nextTerminator(String s, int n, char[] t) { // JPW 09/15/2006: The terminator characters are provided as a parameter // char[] t = {',','\n','\r'}; //terminator characters int min = -1; boolean foundOne = false; if (n >= s.length()) return -1; //at end of string for (int i = 0; i < t.length; i++) { int j = s.indexOf(t[i], n + 1); if (j >= 0) { if (foundOne) { if (j < min) min = j; } else { foundOne = true; min = j; } } } if (foundOne) return min; else return s.length(); } } //end class KeyValueHash