package org.vegbank.common.utility; import java.io.*; import java.net.URL; import java.sql.*; import java.text.DateFormat; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.servlet.http.*; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.vegbank.common.dbAdapter.AbstractDatabase; import org.vegbank.common.model.Aux_role; import org.vegbank.common.model.Place; import org.vegbank.common.model.Plantconcept; import org.vegbank.common.model.Plantstatus; import org.vegbank.common.model.VBModelBean; import org.vegbank.common.utility.mail.*; import org.vegbank.common.Constants; /* * '$RCSfile: Utility.java,v $' * * Purpose: An utility class for Vegbank project. * * '$Author: anderson $' * '$Date: 2005/07/27 22:24:35 $' * '$Revision: 1.52 $' * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ public class Utility implements Constants { /** * Handle for logging */ private static Log log = LogFactory.getLog(Utility.class); public static AbstractDatabase dbAdapter; // FIXME: Read from properties public static String DB_ADAPTER_NAME = "org.vegbank.common.dbAdapter.PostgresqlAdapter"; // Bundle: database public static String DATABASE_NAME; // Bundle: general public static boolean AUTO_APPEND_WILDCARD = false; // Bundle: vegbank public static ResourceBundle vegbankPropFile; public static ResourceBundle dbPropFile; public static String SMTP_SERVER; public static String SMTP_PORT; public static String VEGBANK_SCHEMA_LOCATION; public static String VEGBANK_SCHEMA_NAME; public static String VEGBANK_XML_SCHEMA; public static String VEGBANK_VERSION; public static String VEGBANK_XML_SCHEM; public static String VB_HOME_DIR; public static String VB_DATA_DIR; public static String VB_EXPORT_DIR; public static String VB_EXPORT_DIRNAME; public static String SERVER_ADDRESS; public static String WEBAPP_DIR; public static String WEB_DIR; public static String MODELBEAN_CACHING; public static String VB_EMAIL_FROM; public static String VB_EMAIL_ADMIN_TO; public static String VB_EMAIL_ADMIN_FROM; public static String DATABASE_ACCESSION_KEY_PREASSIGN; public static List DS_CANDIDATES; public static String PARAM_DELIM = "__"; public static String DATACART_KEY = "datacart"; // found in session public static String DATACART_COUNT_KEY = "datacart-count"; // found in session static { try { // Bundle: database; used elsewhere (e.g. dataload) dbPropFile = ResourceBundle.getBundle("database"); DATABASE_NAME = dbPropFile.getString("databaseName"); // Bundle: general AUTO_APPEND_WILDCARD = false; String tmp = ResourceBundle.getBundle("general").getString("queries.auto_append_wildcard"); if (!isStringNullOrEmpty(tmp) && !tmp.equals("false") && !tmp.equals("0")) { AUTO_APPEND_WILDCARD = true; } // Bundle: vegbank vegbankPropFile = ResourceBundle.getBundle("vegbank"); VEGBANK_SCHEMA_LOCATION = vegbankPropFile.getString("schemaLocation"); if (!VEGBANK_SCHEMA_LOCATION.endsWith("/")) { VEGBANK_SCHEMA_LOCATION += "/"; } VEGBANK_SCHEMA_NAME = vegbankPropFile.getString("vegbankSchemaName"); VEGBANK_VERSION = vegbankPropFile.getString("vegbankVersion"); VEGBANK_XML_SCHEMA = VEGBANK_SCHEMA_LOCATION + VEGBANK_SCHEMA_NAME; SERVER_ADDRESS = vegbankPropFile.getString("serverAddress"); WEBAPP_DIR = vegbankPropFile.getString("vegbank.webapp.dir"); WEB_DIR = vegbankPropFile.getString("vegbank.web.dir"); VB_HOME_DIR = vegbankPropFile.getString("vegbank.home.dir"); VB_DATA_DIR = vegbankPropFile.getString("vegbank.data.dir"); VB_EXPORT_DIRNAME = vegbankPropFile.getString("vegbank.export.dirname"); VB_EXPORT_DIR = WEB_DIR + VB_EXPORT_DIRNAME; MODELBEAN_CACHING = vegbankPropFile.getString("modelbean.caching"); SMTP_SERVER = vegbankPropFile.getString("mailHost"); SMTP_PORT = vegbankPropFile.getString("mailPort"); VB_EMAIL_FROM = vegbankPropFile.getString("systemEmail"); VB_EMAIL_ADMIN_TO = vegbankPropFile.getString("admin.email.to"); VB_EMAIL_ADMIN_FROM = vegbankPropFile.getString("admin.email.from"); // accessionCode properties for this database: DATABASE_ACCESSION_KEY_PREASSIGN = vegbankPropFile.getString("database.accession.key.preassign"); } catch (Exception ex) { log.error("There was a problem loading Utility properties", ex); } } /** * Determine our db adapter class and create an instance of that class */ static { try { dbAdapter = (AbstractDatabase) createObject(DB_ADAPTER_NAME); } catch (Exception e) { log.error("Error in Vegbank Util static block:" + e.getMessage()); } } /** * There are some characters that need to be escaped before they are being * written to the database, this escaping needs to be removed before usage. * * @param s -- String to escape chars on * @return ready for db write */ public static String decodeFromDB(String s) { // Handle nulls if ( s == null) return null; //String origString = s; // TODO: Implement this method // '' -> ', '$ -> $, '^ -> ^ ( perhaps removing all ' will work?) // needs experimentation //System.out.println("---->" + origString + " VS. " + s ); return s; } /** * There are some characters that need to be escaped before they are being * written to the database * * @param s -- String to escape chars on * @return String -- ready for db write */ public static String encodeForDB(String s) { // Handle nulls if ( s == null) return null; // List of characters to escape char[] specialChar = {'\'', '$', '^'}; for (int i = 0; i < specialChar.length ; i++) { char currentChar = specialChar[i]; //System.out.println("----->" + currentChar); if ( s.indexOf ( currentChar) != -1 ) { StringBuffer hold = new StringBuffer(); char c; for ( int ii = 0; ii < s.length(); ii++ ) { if ( (c=s.charAt(ii)) == currentChar ) hold.append ("\\" + currentChar ); else hold.append(c); } s = hold.toString(); } } //System.out.println("---->" + origString + " VS. " + s ); return s; } /** * Convert a string to a boolean. * Vegbank sometimes stores booleans in Strings for ease of use ( laziness ) * This attemps to right that wrong by converting certain String patterns into * boolean values * * @param string String to test for true/t equality * @return is this a Stringified true? */ public static boolean isTrue( String string) { boolean result = false; // Check for braindead stuff first if ( string == null || string.equals("") ) return false; if ( string.equals("true") ) return true; if ( string.equals("t") ) return true; return result; } /** * Thin wrapper around setting a date field in a PreparedStatement to handle * adding nulls when needed, e.g. empty string. * * @param date * @param psmnt * @param i * @throws SQLException */ public static void insertDateField ( String date, PreparedStatement psmnt, int i) throws SQLException { int sqlDateType = java.sql.Types.DATE; if ( date == null || date.equals("") ) { psmnt.setNull(i, sqlDateType); } else { // this maybe should be setDate psmnt.setString(i, date); } } /** * Thin wrapper around setting a double field in a PreparedStatement to handle * adding nulls when needed, e.g. empty string. * * @param number * @param psmnt * @param i * @throws SQLException */ public static void insertDoubleField ( String number, PreparedStatement psmnt, int i) throws SQLException { int sqlDoubleType = java.sql.Types.DOUBLE; if ( number == null || number.equals("") ) { psmnt.setNull(i, sqlDoubleType); } else { // this maybe should be setDate psmnt.setString(i, number); } } /** * Retrieves the content of a URL as a string * * @param u - the URL * @return String - the content of the URL * @throws java.io.IOException */ public static String getURLContent(URL u) throws java.io.IOException { //System.out.println("url: " + u.toString()); char istreamChar; int istreamInt; InputStreamReader istream = new InputStreamReader(u.openStream()); StringBuffer serverResponse = new StringBuffer(); while((istreamInt = istream.read()) != -1) { istreamChar = (char)istreamInt; serverResponse.append(istreamChar); } return serverResponse.toString(); } /** *
* Instantiate a class using the name of the class at runtime *
* * @param className * the fully qualified name of the class to instantiate * @return Instance of the requested class * @throws Exception * the class finding/creation exceptions */ public static Object createObject(String className) throws Exception { Object object = null; try { Class classDefinition = Class.forName(className); object = classDefinition.newInstance(); } catch (InstantiationException e) { throw e; } catch (IllegalAccessException e) { throw e; } catch (ClassNotFoundException e) { throw e; } return object; } /** * Generates a VBModelBean from the field names in a ResultSet. */ public static VBModelBean buildBean(ResultSetMetaData meta, ResultSet rs, String beanName) { Object bean = null; try { if (rs == null || !rs.first()) { return null; } int colCount = meta.getColumnCount(); bean = Utility.createObject(VBObjectUtils.DATA_MODEL_PACKAGE + beanName); // use DB column names to set properties for (int i=1; i<=colCount; i++) { String propName = meta.getColumnName(i); Object value = rs.getObject(i); //String value = rs.getString(i); try { if (value != null) { BeanUtils.copyProperty(bean, propName, value); } } catch (Exception ex) { log.debug("unable to set " + propName + " in bean " + beanName); } } } catch (Exception ex) { log.error("Problem building bean from DB results.", ex); } return (VBModelBean)bean; } /** ** Utility Method to check for nulls and empty String *
* * @param stringToCheck * @return Is this Empty or null? */ public static boolean isStringNullOrEmpty(String stringToCheck) { return ( stringToCheck == null || stringToCheck.equals("") ); } /** * Return true if string is not "false", "no", "O", empty or null. */ public static boolean isStringTrue(String stringToCheck) { return !(Utility.isStringNullOrEmpty(stringToCheck) || stringToCheck.equalsIgnoreCase("false") || stringToCheck.equalsIgnoreCase("no") || stringToCheck.equalsIgnoreCase("0")); } /** ** Utility Method to check for nulls and empty array. *
* * @param arrayToCheck * @return Is this Empty or null? */ public static boolean isArrayNullOrEmpty(Object[] arrayToCheck) { return arrayToCheck == null || arrayToCheck.length == 0; } /** ** Convience method to check several string for nullness or emtyness *
* * @param stringsToCheck -- Array of Strings to check * @return Are any of these Strings empty or null? */ public static boolean isAnyStringNullorEmpty( String[] stringsToCheck) { boolean result = false; for (int i = 0; i < stringsToCheck.length; i++) { if ( isStringNullOrEmpty(stringsToCheck[i]) ) { result = true; return result; } } return result; } /** ** Convience method to check several string for non nullness or non emtyness *
* * @param stringsToCheck Array ofString
s to check
* @return Are any of these Strings
NOT empty or null?
*/
public static boolean isAnyStringNotNullorEmpty( String[] stringsToCheck)
{
boolean result = false;
for (int i = 0; i < stringsToCheck.length; i++)
{
if ( ! isStringNullOrEmpty(stringsToCheck[i]) )
{
result = true;
return result;
}
}
return result;
}
/**
*
* Convience method to create a simple comma separted string from an Object[]
.
*
Object
s to convert to comma separate String
* @return String
*/
public static String arrayToCommaSeparatedString(Object[] objects)
{
return joinArray(objects, ",");
}
/**
*
* Convience method to create a simple delimetted String
from
* an Object[]
.
*
String
* @return The delimited List as String
*/
public static String joinArray(Object[] objects, String delimiter)
{
StringBuffer sb = new StringBuffer();
for (int i=0; i < objects.length; i++)
{
sb.append(objects[i]);
if( (i +1) < objects.length )
{
sb.append(delimiter);
}
}
return sb.toString();
}
/**
* Capitalizes the first letter of a string. Leaves the rest of the Sting alone
* @param text
* @return String
*/
public static String upperCaseFirstLetter(String text)
{
String result = text.substring(0, 1).toUpperCase() + text.substring(1);
//System.out.println("Utiltiy > " +result);
return result;
}
/**
* Prints out a hashtable in an easy to read fashion
*
* @param hash -- hashtable to pretty print
*/
public static void prettyPrintHash( Hashtable hash )
{
if (hash == null) {
return;
}
log.debug(prettyPrintHash(hash, 0));
}
private static String prettyPrintHash( Hashtable hash, int indent)
{
//log.debug(indent +" -- "+hash.hashCode());
StringBuffer sb = new StringBuffer(256);
Iterator keys = hash.keySet().iterator();
while ( keys.hasNext() )
{
Object key = keys.next();
sb.append(getIdent( indent ) + key + ":");
Object value = hash.get( key );
if ( value instanceof java.util.Hashtable )
{
sb.append("\n");
sb.append( prettyPrintHash( (Hashtable) value, indent + 1));
}
else if ( value instanceof java.util.Vector )
{
Iterator it = ((Vector) value).iterator();
while ( it.hasNext())
{
Object element = it.next();
if ( element instanceof java.util.Hashtable )
{
sb.append( "--->" +((Hashtable) element).get("TableName") );
sb.append("\n");
sb.append( prettyPrintHash( (Hashtable) element, indent + 1));
}
}
}
else
{
sb.append( "\t" + value + "\n");
}
}
return sb.toString();
}
/**
* Gets current date and time using UTC Timezone.
*
* @return Date-- current Date
*/
public static java.util.Date getNow( )
{
// TODO: not tested yet
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
return cal.getTime();
}
/**
* Gets current date in a format that can be accepted
* by the RDBMS and that is like: Aug 9, 2002
*
* @return the date in a RDBMS format
*/
public static String getCurrentDate()
{
// TODO: use getNow() when it has been tested
java.util.Date now = new java.util.Date(); //Set Date variable now to the current date and time
DateFormat med = DateFormat.getDateInstance (DateFormat.MEDIUM);
return med.format(now);
}
/**
* Convience method for get a string of tabs
*
* @param indent
* @return
*/
private static String getIdent(int indent)
{
StringBuffer sb = new StringBuffer();
for ( int i=0; i* Foreign Key don't always have the same name as the primary key of the * the the primary table, this is a utility to allow this lookup to happen. * * * Not a comprehensive lookup! *
* * @param FKName The Foriegn Key name * @return The Primary Key name that corresponds to the inputed FK name. */ public static String getPKNameFromFKName(String FKName) { // TODO: this is not comprehesive as this is only a problem // for some lookups, should be comprehensive to avoid misuse String PKname = ""; if ( FKName.equalsIgnoreCase(Plantstatus.PLANTPARENT_ID)) { PKname = Plantconcept.PKNAME; } else { PKname = FKName; } return PKname; } /** * Only certain database names need to have accessionCodes loaded * * @return boolean */ public static boolean isLoadAccessionCodeOn() { // I'm not sure what we were thinking when this code was written, // but I'm disabling it. 2/1/2005 PMA return true; /* boolean genAC = false; log.debug("Utility: databaseName = " + DATABASE_NAME); if (DATABASE_NAME.equalsIgnoreCase("vegbank") || DATABASE_NAME.equalsIgnoreCase("vegtest")) { genAC = true; } else { genAC = false; } return genAC; */ } /** * @return */ public static String getAccessionPrefix() { String accessionPrefix = ""; // This is a function of database name and host machine if ( DATABASE_NAME.equalsIgnoreCase("vegbank")) { accessionPrefix = vegbankPropFile.getString("vegbank.accession.prefix"); if (Utility.isStringNullOrEmpty(accessionPrefix)) { accessionPrefix = "VB"; } else { accessionPrefix = accessionPrefix.toUpperCase(); } } else if ( DATABASE_NAME.equalsIgnoreCase("vegtest")) { accessionPrefix = "VT"; } else { accessionPrefix = "NOTVALID"; } return accessionPrefix; } /** * Convert an inputstream to a String. Not sure how the handle encoding * so using System default for now. * * @param is * @return * @throws IOException */ public static String getStringFromInputStream(InputStream is) throws IOException { InputStreamReader reader = new InputStreamReader(is); char[] buffer = new char[4096]; StringWriter writer = new StringWriter(); int bytes_read; while ((bytes_read = reader.read(buffer)) != -1) { writer.write(buffer, 0, bytes_read); } String result = writer.toString(); return result; } /** * Convience method to Uppercase first char of a String and lower case * the rest * @param stringToCapitalize * @return */ public static String upperCaseFirstChar(String stringToCapitalize ) { StringBuffer result = new StringBuffer(); result.append( stringToCapitalize.substring(0,1).toUpperCase() ); result.append( stringToCapitalize.substring(1).toLowerCase() ); return result.toString(); } /** * Parse up an Accessioncode into its parts * * @param accessionCode Vegbank AC to be parsed. * @return code, entityname, key in aString[]
*/
public static HashMap parseAccessionCode(String accessionCode)
{
String DBCODE = "DBCODE";
String ENTITYCODE = "ENTITYCODE";
String KEYVALUE = "KEYVALUE";
String CONFIMATIONCODE = "CONFIMATIONCODE";
HashMap parsedAC = new HashMap();
// method
log.debug("Utility: accessionCode = " + accessionCode);
Pattern pattern = Pattern.compile("([^\\.]*)\\.([^\\.]*)\\.([^\\.]*)\\.{0,1}([^\\.]*)");
Matcher m = pattern.matcher(accessionCode);
if ( m.find() )
{
parsedAC.put("DBCODE", m.group(1) );
parsedAC.put("ENTITYCODE", m.group(2) );
parsedAC.put("KEYVALUE", m.group(3) );
parsedAC.put("CONFIMATIONCODE", m.group(4) );
}
log.debug("Parsed an AccessionCode: DBCode > '" + parsedAC.get(DBCODE) + "' ENTITYCODE > '" + parsedAC.get(ENTITYCODE) + "' KEYVALUE > '" + parsedAC.get(KEYVALUE) + "' CONFIMATIONCODE > '" + parsedAC.get(CONFIMATIONCODE) + "'" );
return parsedAC;
}
/**
* Ugly hack to test if an entityCode is a root entity or not.
*
* @param entityCode
* @return Is root entity?
*/
public static boolean isRootEntity(String entityCode)
{
boolean result = false;
if (entityCode.equalsIgnoreCase("OB") || entityCode.equalsIgnoreCase("PC")
|| entityCode.equalsIgnoreCase("CC"))
{
result = true;
}
return result;
}
/**
* Create and write a temp file in the system tmp dir (/tmp).
*
* @param in
* Reader to write out to filesystem
* @throws IOException
* @return path to temp file
*/
public static String writeTempFile(Reader in) throws IOException
{
File outputFile = File.createTempFile(Integer.toString(in.hashCode()), null);
FileWriter out = new FileWriter(outputFile);
int c;
while ((c = in.read()) != -1)
out.write(c);
out.close();
in.close();
return outputFile.getAbsolutePath();
}
/**
* Tool to save a file to the filesystem.
*
* @param in
* Reader to write out to filesystem
* @param filename
* The name of the file to write to
* @throws IOException
*/
public static void saveFile( Reader in, String filename) throws IOException
{
File outputFile = new File(filename);
if (!outputFile.exists()) {
// create the file
outputFile.createNewFile();
}
FileWriter out = new FileWriter(outputFile);
int c;
while ((c = in.read()) != -1)
out.write(c);
out.close();
in.close();
}
/**
* Tool to delete a file from the filesystem.
*
* @param filename
* The name of the file to write to
* @throws IOException
*/
public static void deleteFile(String filename) throws IOException
{
(new File(filename)).delete();
}
/**
* Serialize a file.
*
* @param fileName
* @param the Object
* @throws IOException
*/
public static void saveBinaryFile(String fileName, Object o) throws IOException {
FileOutputStream fileOut = new FileOutputStream(new File(fileName));
ObjectOutputStream objectOut = new ObjectOutputStream (fileOut);
objectOut.writeObject(o);
}
/**
* Deserialize a file.
*
* @param fileName
* @param the Object
* @throws IOException
*/
public static Object loadBinaryFile(String fileName) throws IOException {
FileInputStream fileIn = new FileInputStream(new File(fileName));
ObjectInputStream objectIn = new ObjectInputStream(fileIn);
try {
return objectIn.readObject();
} catch (Exception ex) {
log.error("couldn't load binary file " + fileName, ex);
}
return null;
}
/**
*
*/
public static String capitalize(String str) {
if (isStringNullOrEmpty(str)) {
return "";
}
return Character.toUpperCase(str.charAt(0)) +
str.toLowerCase().substring(1);
}
/**
* @return true if the value of the given string is a number
*/
public static boolean isNumeric(String s) {
if (Utility.isStringNullOrEmpty(s)) {
return false;
}
try { Long.parseLong(s); }
catch (NumberFormatException nfex) { return false; }
return true;
}
/**
* @return true if the first/only value of the given
* comma-separated list is a number
*/
public static boolean isNumericList(String csv) {
if (Utility.isStringNullOrEmpty(csv)) {
return false;
}
String value = csv;
if (csv.indexOf(',') != -1 || csv.indexOf('|') != -1) {
// a list
StringTokenizer st = new StringTokenizer(csv, ",|");
if (st.hasMoreTokens()) { value = st.nextToken(); }
}
return isNumeric(value);
}
/**
*
*/
public static void notifyAdmin(String subject, String body) {
String adminFromEmail = vegbankPropFile.getString("admin.email.from");
String adminToEmail = vegbankPropFile.getString("admin.email.to");
String server = vegbankPropFile.getString("machine_url");
if (isStringNullOrEmpty(adminFromEmail)) { adminFromEmail = "site@vegbank.org"; }
if (isStringNullOrEmpty(adminToEmail)) { adminToEmail = "dba@vegbank.org"; }
if (isStringNullOrEmpty(server)) { server = "unknown vegbank host"; }
try {
Mailer m = new Mailer();
m.sendPlain("ADMIN NOTIFICATION FROM " + server,
"SUBJECT: " + subject + "\n\n" + body, adminToEmail,
null, null, adminFromEmail);
log.info("Sent an email notification to admin re: " + subject);
} catch (MailerException mex) {
log.error("Problem notifying admin", mex);
}
}
/**
*
* @return
*/
public static boolean canAddToDatasetOnLoad(String tableName) {
if (Utility.isStringNullOrEmpty(tableName)) {
log.debug("canAddToDatasetOnLoad(): given empty string");
return false;
}
if (DS_CANDIDATES == null) {
String s = vegbankPropFile.getString("dataset.candidates");
StringTokenizer st = new StringTokenizer(s, ",");
DS_CANDIDATES = new ArrayList();
while (st.hasMoreTokens()) {
DS_CANDIDATES.add(st.nextToken().toLowerCase());
}
}
return DS_CANDIDATES.contains(tableName.toLowerCase());
}
/**
* Returns a version of the given string that is no
* longer than len chars and ends in "..." if
* any chars were abbreviated (string was long).
*/
public static String abbreviate(String src, int len) {
if (Utility.isStringNullOrEmpty(src)) {
return "";
}
if (src.length() > len) {
return src.substring(0, len-3) + "...";
} else {
return src;
}
}
/**
* Returns usr_id of authenticated user, or null if not logged in.
*/
public static Long getAuthenticatedUsrId(HttpSession session) {
return (Long)session.getAttribute(USER_KEY);
}
/**
* Returns path and parameters for last search.
*/
public static String getLastSearchURL(HttpSession session) {
String url = (String)session.getAttribute(LAST_SEARCH_URL);
if (url == null) {
url = "";
}
log.debug("GOT " + LAST_SEARCH_URL + ": " + url);
return url;
}
/**
* Saves path and parameters for last search.
*/
public static void setLastSearchURL(HttpServletRequest request) {
StringBuffer url = request.getRequestURL();
String qs = request.getQueryString();
if (qs != null) {
url.append("?").append(qs);
}
log.debug("setting " + LAST_SEARCH_URL + " to " + url.toString());
request.getSession().setAttribute(LAST_SEARCH_URL, url.toString());
}
/**
*
*/
public static String getVegBankProperty(String key) {
return vegbankPropFile.getString(key);
}
}