/*
jBilling - The Enterprise Open Source Billing System
Copyright (C) 2003-2011 Enterprise jBilling Software Ltd. and Emiliano Conde
This file is part of jbilling.
jbilling is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
jbilling 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with jbilling. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sapienter.jbilling.common;
import org.apache.log4j.Logger;
import java.util.Date;
import java.util.GregorianCalendar;
/**
* Client miscelaneous utility functions
*/
public class Util {
private static final Logger LOG = Logger.getLogger(Util.class);
/**
* Creates a date object with the given parameters only if they belong to a
* valid day, so February 30th would be returning null.
* @param year
* @param month
* @param day
* @return null if the parameters are invalid, otherwise the date object
*/
static public Date getDate(Integer year, Integer month,
Integer day) {
Date retValue = null;
try {
GregorianCalendar cal = new GregorianCalendar();
cal.setLenient(false);
cal.clear();
cal.set(year.intValue(), month.intValue()-1, day.intValue());
retValue = cal.getTime();
} catch (Exception e) {
}
return retValue;
}
/**
* Converts a string in the format yyyy-mm-dd to a Date.
* If the string can't be converted, it returns null
* @param str
* @return
*/
static public Date parseDate(String str) {
if (str == null || str.length() < 8 || str.length() > 10) {
return null;
}
if (str.charAt(4) != '-' || str.lastIndexOf('-') < 6 ||
str.lastIndexOf('-') > 7) {
return null;
}
try {
int year = getYear(str);
int month = getMonth(str);
int day = getDay(str);
return getDate(new Integer(year), new Integer(month),
new Integer(day));
} catch (Exception e) {
return null;
}
}
/**
* Recives date in sql format yyyy-mm-dd and extracts the day
* @param day
* @return
*/
static public int getDay(String str)
throws SessionInternalError {
// from the last '-' to the end
try {
return Integer.valueOf(str.substring(str.lastIndexOf('-') + 1)).
intValue();
} catch (NumberFormatException e) {
throw new SessionInternalError("Cant get the day from " + str);
}
}
static public int getMonth(String str)
throws SessionInternalError {
// from the first '-' to the second '-'
try {
return Integer.valueOf(str.substring(str.indexOf('-') + 1,
str.lastIndexOf('-'))).intValue();
} catch (NumberFormatException e) {
throw new SessionInternalError("Cant get the month from " + str);
}
}
static public int getYear(String str)
throws SessionInternalError {
// from the begining to the first '-'
try {
return Integer.valueOf(str.substring(0, str.indexOf('-'))).intValue();
} catch (NumberFormatException e) {
throw new SessionInternalError("Cant get the year from " + str);
}
}
/**
* Compares to dates, contemplating the posibility of null values.
* If both are null, they are consider equal.
* @param date1
* @param date2
* @return true if equal, otherwise false.
*/
static public boolean equal(Date date1, Date date2) {
boolean retValue;
if (date1 == null && date2 == null) {
retValue = true;
} else if ((date1 == null && date2 != null) ||
(date1 != null && date2 == null)) {
retValue = false;
} else {
retValue = (date1.compareTo(date2) == 0);
}
return retValue;
}
static public Date truncateDate(Date arg) {
if (arg == null) return null;
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(arg);
cal.set(GregorianCalendar.HOUR_OF_DAY, 0);
cal.set(GregorianCalendar.MINUTE, 0);
cal.set(GregorianCalendar.SECOND, 0);
cal.set(GregorianCalendar.MILLISECOND, 0);
return cal.getTime();
}
/**
* Takes a date and returns it as String with the format 'yyyy-mm-dd'
* @param date
* @return
*/
static public String parseDate(Date date) {
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(date);
return cal.get(GregorianCalendar.YEAR) + "-" +
(cal.get(GregorianCalendar.MONTH) + 1) + "-" +
cal.get(GregorianCalendar.DATE);
}
/**
* Returns the payment method for the given credit card. If this credit card
* has been obscured (by the {@link com.sapienter.jbilling.server.payment.tasks.SaveCreditCardExternallyTask} plug-in)
* then the payment type cannot detected and this method will return PAYMENT_METHOD_GATEWAY_KEY.
*
* @param creditCardNumber credit card number to parse
* @return payment method
*/
static public Integer getPaymentMethod(String creditCardNumber) {
Integer type = null;
switch (creditCardNumber.charAt(0)) {
case '4':
type = Constants.PAYMENT_METHOD_VISA;
break;
case '5':
type = Constants.PAYMENT_METHOD_MASTERCARD;
break;
case '3':
// both diners and american express start with a 3
if (creditCardNumber.charAt(1) == '7') {
type = Constants.PAYMENT_METHOD_AMEX;
} else if (creditCardNumber.charAt(1) == '8') {
type = Constants.PAYMENT_METHOD_DINERS;
}
break;
case '6':
type = Constants.PAYMENT_METHOD_DISCOVERY;
break;
}
/*
This isn't 100% accurate as obscured credit card numbers may not always mean that a gateway key
is present. We should be checking CreditCardDTO to ensure that gatewayKey is not null when an
obscured credit card number is encountered.
*/
if (creditCardNumber.contains("*"))
type = Constants.PAYMENT_METHOD_GATEWAY_KEY;
return type;
}
static public String truncateString(String str, int length) {
if (str == null) return null;
String retValue;
if (str.length() <= length) {
retValue = str;
} else {
retValue = str.substring(0, length);
}
return retValue;
}
public static String getSysProp(String key) {
try {
return SystemProperties.getSystemProperties().get(key);
} catch (Exception e) {
LOG.error("Cannot read property '" + key + "' from " + SystemProperties.getPropertiesFile().getPath(), e);
return null;
}
}
/**
* Gets a boolean system property. It returns true by default, and on any error.
*
* @param key boolean system property
* @return boolean property value
*/
public static boolean getSysPropBooleanTrue(String key) {
try {
return Boolean.parseBoolean(SystemProperties.getSystemProperties().get(key, "true"));
} catch (Exception e) {
LOG.error("Cannot read property '" + key + "' from " + SystemProperties.getPropertiesFile().getPath());
}
return true; // default if not found
}
/**
* Credit Card Validate
* Reference: http://www.ling.nwu.edu/~sburke/pub/luhn_lib.pl
*/
public static boolean luhnCheck(String cardNumber) throws SessionInternalError {
//just in case the card number is formated and may contain spaces
cardNumber=getDigitsOnly(cardNumber);
//mod 10 validation
if (isLuhnNum(cardNumber)) {
int no_digit = cardNumber.length();
int oddoeven = no_digit & 1;
int sum = 0;
int digit = 0;
int addend = 0;
boolean timesTwo = false;
for (int i = cardNumber.length() - 1; i >= 0; i--) {
digit = Integer.parseInt(cardNumber.substring(i, i + 1));
if (timesTwo) {
addend = digit * 2;
if (addend > 9) {
addend -= 9;
}
} else {
addend = digit;
}
sum += addend;
timesTwo = !timesTwo;
}
if (sum == 0) return false;
if (sum % 10 == 0) return true;
};
return false;
}
private static String getDigitsOnly(String s) {
StringBuffer digitsOnly = new StringBuffer();
char c;
for (int i = 0; i < s.length(); i++) {
c = s.charAt(i);
if (Character.isDigit(c)) {
digitsOnly.append(c);
}
}
return digitsOnly.toString();
}
private static boolean isLuhnNum(String argvalue) {
if (argvalue.length() == 0) {
return false;
}
for (int n = 0; n < argvalue.length(); n++) {
char c = argvalue.charAt(n);
if (!Character.isDigit(c)) {
return false;
}
}
return true;
}
}