001package bradleyross.library.helpers;
002import java.text.NumberFormat;
003import java.util.regex.Pattern;
004import java.util.regex.Matcher;
005import java.sql.Date;
006import java.sql.ResultSet;
007import java.sql.SQLException;
008import java.sql.PreparedStatement;
009import java.sql.Types;
010import java.util.Enumeration;
011import javax.servlet.http.HttpServletRequest;
012import bradleyross.library.database.DatabaseProperties;
013import bradleyross.library.helpers.StringHelpers;
014/**
015 * General purpose helpers for use in creating servlets.
016 * @author - Bradley Ross
017 */
018public class ServletHelpers
019{
020        protected DatabaseProperties data = null;
021        public ServletHelpers(DatabaseProperties dataValue)
022        {
023                data = dataValue;
024        }
025        /**
026         * This method is intended to help in showing the elapsed time for
027         * generating a page.
028         * <p>By using this method, you avoid the possibility of the
029         *    value for milliseconds displaying with over a dozen
030         *    digits due to round-off error.</p>
031         * @param startTime Date (in milliseconds that was generated using
032         *        a previous java.util.Date object.
033         * @return Formatted string containing the elapsed time in
034         *        milliseconds
035         * @see java.util.Date
036         * @see java.text.NumberFormat
037         */
038        public static String formatElapsedTime (long startTime)
039        {
040                long difference = new java.util.Date().getTime() - startTime;
041                java.text.NumberFormat nf = java.text.NumberFormat.getInstance();
042                nf.setMaximumFractionDigits(3);
043                return nf.format((double) difference / 1000.0d);
044        }
045        /**
046         * Returns a default value if the examined value is null.
047         * <p>Trying to run a number of String methods, such as equals or 
048         *    equalsIgnoreCase, result in exeptions being thrown if the 
049         *    object being examined has a value of null<p>
050         * @param value String value to be examined
051         * @param ifDefault Default value to be used if value is null
052         * @return String containing either examined or default value
053         */
054        public static String valueWithDefault ( String value, String ifDefault)
055        {
056                if ( value == null)
057                { return ifDefault; }
058                else
059                {return value; }
060        }
061        /**
062         * Replace occurrences of double quotes with two
063         * double quote characters.
064         * @param value String to be processed
065         * @return Processed string
066         */
067        public static String doubleDoubleQuotes (String value)
068        {
069                java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("\\\"");
070                java.util.regex.Matcher matcher = pattern.matcher(value);
071                return matcher.replaceAll("\"\"");
072        }
073        /**
074         * 
075         * Replace occurrences of double quotes with a back slash followed by
076         * a double quote.
077         * @param value String to be processed
078         * @return Processed string
079         */
080        public static String escapeDoubleQuotes (String value)
081        {
082                Pattern pattern = Pattern.compile("\\\"");
083                Matcher matcher = pattern.matcher(value);
084                return matcher.replaceAll("\\\\\"");
085        }
086        /**
087         * Return a character value from a result set as a String object.
088         * @param rs Result set to be used
089         * @param columnName Name of column to be read
090         * @param defaultValue Default value if column in result set has a value of null
091         * @return Character data
092         * @throws SQLException if io errors
093         */
094        public static String getStringValue(ResultSet rs, String columnName, String defaultValue)
095        throws SQLException
096        {
097                String working = rs.getString(columnName);
098                if (rs.wasNull())
099                {
100                        working = defaultValue;
101                }
102                
103                return working;
104        }
105        /**
106         * Return a character value from a result set as a String object.
107         * @param rs Result set to be read
108         * @param columnName Name of column to be read
109         * @param defaultValue Default value to be used in value in database is null
110         * @return Character data
111         * @throws SQLException if database errors
112         */
113        public static String getStringValueEscaped(ResultSet rs, String columnName, String defaultValue)
114        throws SQLException
115        {
116                String working = getStringValue(rs, columnName, defaultValue);
117                return StringHelpers.escapeHTML(working);
118        }
119        /**
120         * Return the contents of a character column in a result set as a String object.
121         * @param rs Result set to be read
122         * @param columnName Name of column to be read
123         * @return Character data from database
124         * @throws SQLException if database errors
125         */
126        public static String getStringValue(ResultSet rs, String columnName) throws SQLException
127        {
128                return getStringValue (rs, columnName, (String) null);
129        }
130        /**
131         * Return the contents of a character column in a result set as a String object.
132         * 
133         * <p>This method escapes the character strings using the HTML
134         *    character entity literals before returning the data to the calling program.</p>
135         * @param rs Result set to be read
136         * @param columnName Name of column to be read
137         * @return Character data from database
138         * @throws SQLException if database errors
139         */
140        public static String getStringValueEscaped (ResultSet rs, String columnName) throws SQLException
141        {
142                return getStringValueEscaped (rs, columnName, (String) null);
143        }
144        /**
145         * Return a floating point value from the result set.
146         * @param rs ResultSet object containing information
147         * @param columnName Name of column in result set
148         * @param defaultValue Value to be returned if value of column is null
149         * @return Value from result set
150         * @throws SQLException if dataase errors
151         */
152        public static float getFloatValue(ResultSet rs, String columnName, float defaultValue)
153        throws SQLException
154        {
155                float working = rs.getFloat(columnName);
156                if (rs.wasNull())
157                {
158                        working = defaultValue;
159                }
160                return working;
161        }
162        /**
163         * Return a floating point value from a result set, returning zero if the value
164         * in the result set was null.
165         * @param rs Result set from which data is to be taken
166         * @param columnName Name of column in result set
167         * @return Floating point value from result set
168         * @throws SQLException if database errors
169         */
170        public static float getFloatValue (ResultSet rs, String columnName) throws SQLException
171        {
172                return getFloatValue (rs, columnName, 0.0f );
173        }
174        /**
175         * Set a CHAR column in a prepared statement.
176         * 
177         * @param stmt Prepared statement
178         * @param position Position in prepared statement
179         * @param value Value to be used for parameter
180         * @throws SQLException if database errors
181         */
182        public static void setChar(PreparedStatement stmt, int position, String value) throws SQLException
183        {
184                setChar(stmt, position, value, false);
185        }
186        /**
187         * Set a CHAR column in a prepared statement.
188         * 
189         * @param stmt Prepared statement
190         * @param position Position in prepared statement
191         * @param value Value to be used for parameter
192         * @param toUpperCase True means strings are converted to upper case
193         * @throws SQLException if database errors
194         */
195        public static void setChar(PreparedStatement stmt, int position, String value, boolean toUpperCase) throws SQLException
196        {
197                if (value == null)
198                {
199                        stmt.setNull(position, Types.CHAR);
200                }
201                else if (value.trim().length() == 0)
202                {
203                        stmt.setNull(position, Types.CHAR);
204                }
205                else
206                {
207                        if (toUpperCase)
208                        {
209                                stmt.setString(position, value.toUpperCase());
210                        }
211                        else
212                        {
213                                stmt.setString(position, value);
214                        }
215                }       
216        }
217        /**
218         * Set a CHAR column in a prepared statement.
219         * 
220         * @param stmt Prepared statement
221         * @param position Position in prepared statement
222         * @param rs Result set containing value to be used for parameter
223         * @param name Name of column in result set
224         * @throws SQLException if database errors
225         */
226        public static void setChar (PreparedStatement stmt, int position, ResultSet rs, String name) throws SQLException
227        {
228                setChar(stmt, position, rs, name, false);
229        }
230        /**
231         * Set a CHAR column in a prepared statement.
232         * 
233         * @param stmt Prepared statement
234         * @param position Position in prepared statement
235         * @param rs Result set containing value to be used for parameter
236         * @param name Name of column in result set
237         * @param toUpperCase True means strings are converted to upper case
238         * @throws SQLException if database errors
239         */
240        public static void setChar (PreparedStatement stmt, int position, ResultSet rs, String name, boolean toUpperCase) throws SQLException
241        {
242                String working = rs.getString(name);
243                if (rs.wasNull())
244                {
245                        stmt.setNull(position, Types.CHAR);
246                }
247                else if (working == null)
248                {
249                        stmt.setNull(position, Types.CHAR);
250                }
251                else if (working.trim().length() == 0)
252                {
253                        stmt.setNull(position, Types.CHAR);
254                }
255                else
256                {
257                        if (toUpperCase)
258                        {
259                                working = working.toUpperCase();
260                        }
261                        stmt.setString(position, working);
262                }
263        }
264        /**
265         * Set a VARCHAR column in a prepared statement.
266         * 
267         * @param stmt Prepared statement
268         * @param position Position in prepared statement
269         * @param value Value to be used for parameter
270         * @throws SQLException if database errors
271         */
272        public static void setVarchar(PreparedStatement stmt, int position, String value) throws SQLException
273        {
274                setVarchar(stmt, position, value, false);
275        }
276        /**
277         * Set a VARCHAR column in a prepared statement.
278         * 
279         * @param stmt Prepared statement
280         * @param position Position in prepared statement
281         * @param value Value to be used for parameter
282         * @param toUpperCase True means that strings are converted to upper case
283         * @throws SQLException if database errors
284         */
285        public static void setVarchar(PreparedStatement stmt, int position, String value, boolean toUpperCase) throws SQLException
286        {
287                if (value == null)
288                {
289                        stmt.setNull(position, Types.VARCHAR);
290                }
291                else if (value.trim().length() == 0)
292                {
293                        stmt.setNull(position, Types.VARCHAR);
294                }
295                else
296                {
297                        if (toUpperCase)
298                        {
299                                stmt.setString(position, value.toUpperCase());
300                        }
301                        else
302                        {
303                                stmt.setString(position, value);
304                        }
305                }       
306        }
307        /**
308         * Set a VARCHAR column in a prepared statement.
309         * 
310         * @param stmt Prepared statement
311         * @param position Position in prepared statement
312         * @param rs Result set containing value to be used for parameter
313         * @param name Name of column in result set
314         * @throws SQLException if database errors
315         */
316        public static void setVarchar (PreparedStatement stmt, int position, ResultSet rs, String name) throws SQLException
317        {
318                setVarchar (stmt, position, rs, name, false);
319        }
320        /**
321         * Set a VARCHAR column in a prepared statement.
322         * 
323         * @param stmt Prepared statement
324         * @param position Position in prepared statement
325         * @param rs Result set containing value to be used for parameter
326         * @param name Name of column in result set
327         * @param toUpperCase True means that strings are to be converted to upper case
328         * @throws SQLException if database errors
329         */
330        public static void setVarchar (PreparedStatement stmt, int position, ResultSet rs, String name, boolean toUpperCase) throws SQLException
331        {
332                String working = rs.getString(name);
333                if (rs.wasNull())
334                {
335                        stmt.setNull(position, Types.VARCHAR);
336                }
337                else if (working == null)
338                {
339                        stmt.setNull(position, Types.VARCHAR);
340                }
341                else if (working.trim().length() == 0)
342                {
343                        stmt.setNull(position, Types.VARCHAR);
344                }
345                else
346                {
347                        if (toUpperCase)
348                        {
349                                working = working.toUpperCase();
350                        }
351                        stmt.setString(position, working);
352                }
353        }       
354        /**
355         * Set a FLOAT column in a prepared statement.
356         * 
357         * @param stmt Prepared statement
358         * @param position Position in prepared statement
359         * @param value Value to be used for parameter
360         * @throws SQLException if database errors
361         */
362        public static void setFloat(PreparedStatement stmt, int position, Float value) throws SQLException
363        {
364                if (value == null)
365                {
366                        stmt.setNull(position, Types.FLOAT);
367                }
368                else
369                {
370                        stmt.setFloat(position, value);
371                }       
372        }
373        /**
374         * Set a FLOAT column in a prepared statement.
375         * 
376         * @param stmt Prepared statement
377         * @param position Position in prepared statement
378         * @param rs Result set containing value to be used for parameter
379         * @param name Name of column in result set
380         * @throws SQLException if database errors
381         */
382        public static void setFloat (PreparedStatement stmt, int position, ResultSet rs, String name) throws SQLException
383        {
384                float working = rs.getFloat(name);
385                if (rs.wasNull())
386                {
387                        stmt.setNull(position, Types.FLOAT);
388                }
389                else
390                {
391                        stmt.setFloat(position, working);
392                }
393        }               
394        /**
395         * Set a INTEGER column in a prepared statement.
396         * 
397         * @param stmt Prepared statement
398         * @param position Position in prepared statement
399         * @param value Value to be used for parameter
400         * @throws SQLException if database errors
401         */
402        public static void setInteger(PreparedStatement stmt, int position, Integer value) throws SQLException
403        {
404                if (value == null)
405                {
406                        stmt.setNull(position, Types.INTEGER);
407                }
408                else
409                {
410                        stmt.setInt(position, value);
411                }       
412        }
413        /**
414         * Set a INTEGER column in a prepared statement.
415         * 
416         * @param stmt Prepared statement
417         * @param position Position in prepared statement
418         * @param rs Result set containing value to be used for parameter
419         * @param name Name of column in result set
420         * @throws SQLException  if database errors
421         */
422        public static void setInteger (PreparedStatement stmt, int position, ResultSet rs, Integer name) throws SQLException
423        {
424                int working = rs.getInt(name);
425                if (rs.wasNull())
426                {
427                        stmt.setNull(position, Types.INTEGER);
428                }
429                else
430                {
431                        stmt.setInt(position, working);
432                }
433        }               
434        /**
435         * Construct an SQL date using the year, month, and day
436         * @param yearValue Year (4 digit)
437         * @param monthValue Number of Month (January = 1)
438         * @param dayValue Day of month
439         * @return SQL date
440         */
441        public static Date buildDate(String yearValue, String monthValue, String dayValue) 
442        {
443                int year = -1;
444                int month = -1;
445                int day = -1;
446                try
447                {
448                year = Integer.parseInt(yearValue);
449                month = Integer.parseInt(monthValue);
450                day = Integer.parseInt(dayValue);
451                }
452                catch (NumberFormatException e)
453                {
454                        throw new IllegalArgumentException ("buildDate unable to process " + yearValue + ":" + monthValue + ":" + dayValue);
455                }
456                return buildDate(year, month, day);
457        }
458        /**
459         * Construct an SQL date using the year, month, and day
460         * @param year Year (4 digit)
461         * @param month Number of month (January = 1)
462         * @param day Day of month
463         * @return SQL date
464         */
465        public static Date buildDate(int year, int month, int day) 
466        {
467                NumberFormat format2 =  NumberFormat.getIntegerInstance();
468                NumberFormat format4 =  NumberFormat.getIntegerInstance();
469                format2.setMinimumIntegerDigits(2);
470                format2.setGroupingUsed(false);
471                format4.setMinimumIntegerDigits(4);
472                format4.setGroupingUsed(false);
473                return Date.valueOf(format4.format(year) + "-" + format2.format(month) + "-" + format2.format(day));
474        }
475        /**
476         * Place information on the parameters in the body of the servlet.
477         * 
478         * <p>This is intended for debugging purposes.</p>
479         * 
480         * @param request Request object
481         * @return Text to be included in HTML document
482         */
483        public static String showParameters(HttpServletRequest request)
484        {
485                Enumeration<?> parameterNames = null;
486                String values[] = null;
487                parameterNames = request.getParameterNames();
488                StringBuffer working = new StringBuffer("<ul>");
489                while (parameterNames.hasMoreElements())
490                {
491                        String parameter = (String) parameterNames.nextElement();
492                        working.append("<li>" + StringHelpers.escapeHTML(parameter) + ": ");
493                        values = request.getParameterValues(parameter);
494                        for (int i = 0; i < values.length; i++)
495                        {
496                                working.append(StringHelpers.escapeHTML(values[i]) + " ");
497                        }
498                        working.append("</li>");
499                }
500                working.append("</ul>");
501                return new String(working);
502        }
503        /**
504         * Test driver.
505         * @param args Not used in this program
506         */
507        public static void main(String args[])
508        {
509                System.out.println(doubleDoubleQuotes("\"This is  a test\""));
510                System.out.println(escapeDoubleQuotes("aaa\"\"bbb \""));
511                System.out.println(doubleDoubleQuotes("aaa\"bbb"));
512        }
513}