PageRenderTime 94ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/java/org/jongo/JongoUtils.java

https://code.google.com/p/jongo/
Java | 357 lines | 211 code | 33 blank | 113 comment | 37 complexity | 767ff791c9099af6bade31973cb17a29 MD5 | raw file
  1. /**
  2. * Copyright (C) 2011, 2012 Alejandro Ayuso
  3. *
  4. * This file is part of Jongo.
  5. * Jongo is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * any later version.
  9. *
  10. * Jongo is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with Jongo. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. package org.jongo;
  19. import java.io.UnsupportedEncodingException;
  20. import java.math.BigDecimal;
  21. import java.security.MessageDigest;
  22. import java.util.ArrayList;
  23. import java.util.HashMap;
  24. import java.util.List;
  25. import java.util.Map;
  26. import javax.ws.rs.core.MultivaluedMap;
  27. import org.apache.commons.lang.StringUtils;
  28. import org.codehaus.jackson.map.ObjectMapper;
  29. import org.codehaus.jackson.type.TypeReference;
  30. import org.joda.time.DateTime;
  31. import org.joda.time.format.DateTimeFormatter;
  32. import org.joda.time.format.ISODateTimeFormat;
  33. import org.jongo.config.JongoConfiguration;
  34. import org.jongo.exceptions.JongoBadRequestException;
  35. import org.jongo.exceptions.StartupException;
  36. import org.jongo.jdbc.StoredProcedureParam;
  37. import org.slf4j.Logger;
  38. import org.slf4j.LoggerFactory;
  39. import sun.misc.BASE64Encoder;
  40. /**
  41. * Collection of commonly used methods and constants.
  42. * @author Alejandro Ayuso
  43. */
  44. public class JongoUtils {
  45. private static final Logger l = LoggerFactory.getLogger(JongoUtils.class);
  46. /**
  47. * Check if a string has the ISO date time format. Uses the ISODateTimeFormat.dateTime() from JodaTime
  48. * and returns a DateTime instance. The correct format is yyyy-MM-ddTHH:mm:ss.SSSZ
  49. * @param arg the string to check
  50. * @return a DateTime instance if the string is in the correct ISO format.
  51. */
  52. public static DateTime isDateTime(final String arg){
  53. if(arg == null) return null;
  54. DateTimeFormatter f = ISODateTimeFormat.dateTime();
  55. DateTime ret = null;
  56. try{
  57. ret = f.parseDateTime(arg);
  58. }catch(IllegalArgumentException e){
  59. l.debug(arg + " is not a valid ISO DateTime");
  60. }
  61. return ret;
  62. }
  63. /**
  64. * Check if a string has the ISO date format. Uses the ISODateTimeFormat.date() from JodaTime
  65. * and returns a DateTime instance. The correct format is yyyy-MM-dd or yyyyMMdd
  66. * @param arg the string to check
  67. * @return a DateTime instance if the string is in the correct ISO format.
  68. */
  69. public static DateTime isDate(final String arg){
  70. if(arg == null) return null;
  71. DateTime ret = null;
  72. DateTimeFormatter df;
  73. if(arg.contains("-")){
  74. df = ISODateTimeFormat.date();
  75. }else{
  76. df = ISODateTimeFormat.basicDate();
  77. }
  78. try{
  79. ret = df.parseDateTime(arg);
  80. }catch(IllegalArgumentException e){
  81. l.debug(arg + " is not a valid ISO date");
  82. }
  83. return ret;
  84. }
  85. /**
  86. * Check if a string has the ISO time format. Uses the ISODateTimeFormat.time() from JodaTime
  87. * and returns a DateTime instance. The correct format is HH:mm:ss.SSSZZ or HHmmss.SSSZ
  88. * @param arg the string to check
  89. * @return a DateTime instance if the string is in the correct ISO format.
  90. */
  91. public static DateTime isTime(final String arg){
  92. if(arg == null) return null;
  93. DateTime ret = null;
  94. DateTimeFormatter df;
  95. if(arg.contains(":")){
  96. df = ISODateTimeFormat.time();
  97. }else{
  98. df = ISODateTimeFormat.basicTime();
  99. }
  100. try{
  101. ret = df.parseDateTime(arg);
  102. }catch(IllegalArgumentException e){
  103. l.debug(arg + " is not a valid ISO time");
  104. }
  105. return ret;
  106. }
  107. /**
  108. * Convert a String in camelCase to a String separated by white spaces.
  109. * I.E. "thisStringInCamelCase" to "this String In Camel Case"
  110. * @param s String in camelCase
  111. * @return same string with white spaces.
  112. */
  113. public static String splitCamelCase(String s) {
  114. return s.replaceAll(String.format("%s|%s|%s", "(?<=[A-Z])(?=[A-Z][a-z])", "(?<=[^A-Z])(?=[A-Z])", "(?<=[A-Za-z])(?=[^A-Za-z0-9_])"), " ");
  115. }
  116. /**
  117. * Convert a List of String to a vararg of Objects. The values are deduced from their format
  118. * and converted to the corresponding java.sql.Types so they are correctly saved in the databases.
  119. * @param values a List of String with the values to be converted
  120. * @return a vararg of java.sql Objects
  121. */
  122. public static Object[] parseValues(List<String> values){
  123. List<Object> res = new ArrayList<Object>();
  124. for(String val : values){
  125. res.add(parseValue(val));
  126. }
  127. return res.toArray();
  128. }
  129. /**
  130. * Infers the java.sql.Types of the given String and returns the JDBC mappable Object corresponding to it.
  131. * The conversions are like this:
  132. * String -> String
  133. * Numeric -> Integer
  134. * Date or Time -> Date
  135. * Decimal -> BigDecimal
  136. * ??? -> TimeStamp
  137. * @param val a String with the value to be mapped
  138. * @return a JDBC mappable object instance with the value
  139. */
  140. public static Object parseValue(String val){
  141. Object ret = null;
  142. if(!StringUtils.isWhitespace(val) && StringUtils.isNumeric(val)){
  143. try{
  144. ret = Integer.valueOf(val);
  145. }catch(Exception e){
  146. l.debug(e.getMessage());
  147. }
  148. }else{
  149. DateTime date = JongoUtils.isDateTime(val);
  150. if(date != null){
  151. l.debug("Got a DateTime " + date.toString(ISODateTimeFormat.dateTime()));
  152. ret = new java.sql.Timestamp(date.getMillis());
  153. }else{
  154. date = JongoUtils.isDate(val);
  155. if(date != null){
  156. l.debug("Got a Date " + date.toString(ISODateTimeFormat.date()));
  157. ret = new java.sql.Date(date.getMillis());
  158. }else{
  159. date = JongoUtils.isTime(val);
  160. if(date != null){
  161. l.debug("Got a Time " + date.toString(ISODateTimeFormat.time()));
  162. ret = new java.sql.Time(date.getMillis());
  163. }
  164. }
  165. }
  166. if(ret == null && val != null){
  167. l.debug("Not a datetime. Try someting else. ");
  168. try{
  169. ret = new BigDecimal(val);
  170. }catch(NumberFormatException e){
  171. l.debug(e.getMessage());
  172. ret = val;
  173. }
  174. }
  175. }
  176. return ret;
  177. }
  178. /**
  179. * Converts a vararg of Object to a String representation of its content
  180. * @param params a vararg of objects
  181. * @return a String like "[1,2,3,5,hello,0.1]"
  182. */
  183. public static String varargToString(Object... params){
  184. StringBuilder b = new StringBuilder("[");
  185. b.append(StringUtils.join(params, ","));
  186. b.append("]");
  187. return b.toString();
  188. }
  189. /**
  190. * Reads a String in JSON format and returns a MultivaluedMap representation of it.
  191. * @return a MultivaluedMap with the keys/values as represented by the incoming JSON string.
  192. * @throws JongoBadRequestException if the JSON string is not readable.
  193. */
  194. public static Map<String, String> getParamsFromJSON(final String json) throws JongoBadRequestException{
  195. if(StringUtils.isBlank(json))
  196. throw new JongoBadRequestException("Invalid number of arguments for request " + json);
  197. try {
  198. Map<String, String> ret = new ObjectMapper().readValue(json, new TypeReference<Map<String, String>>(){});
  199. return ret;
  200. } catch (Exception ex) {
  201. throw new JongoBadRequestException(ex.getMessage());
  202. }
  203. }
  204. /**
  205. * From a JSON string generated a list of {@link org.jongo.jdbc.StoredProcedureParam}. The format of this JSON is:
  206. * [
  207. * {"value":2010, "name":"year", "outParameter":false, "type":"INTEGER", "index":1},
  208. * {"name":"out_total", "outParameter":true, "type":"INTEGER", "index":2}
  209. * ]
  210. * @param json a string with the JSON representation of a {@link org.jongo.jdbc.StoredProcedureParam}
  211. * @return a list of {@link org.jongo.jdbc.StoredProcedureParam}.
  212. * @throws JongoBadRequestException if we fail to parse the JSON for any reason.
  213. */
  214. public static List<StoredProcedureParam> getStoredProcedureParamsFromJSON(final String json) throws JongoBadRequestException{
  215. if(StringUtils.isBlank(json))
  216. throw new JongoBadRequestException("Invalid number of arguments for request " + json);
  217. try {
  218. List<StoredProcedureParam> ret = new ObjectMapper().readValue(json, new TypeReference<List<StoredProcedureParam>>(){});
  219. return ret;
  220. } catch (Exception ex) {
  221. throw new JongoBadRequestException(ex.getMessage());
  222. }
  223. }
  224. /**
  225. * Calls the JongoConfiguration.instanceOf() method and returns the given instance of {@link org.jongo.config.JongoConfiguration}
  226. * @return an instance of {@link org.jongo.config.JongoConfiguration}
  227. * @throws StartupException if {@link org.jongo.config.JongoConfiguration} fails to instantiate.
  228. */
  229. public static JongoConfiguration loadConfiguration() throws StartupException{
  230. JongoConfiguration configuration = null;
  231. try{
  232. configuration = JongoConfiguration.instanceOf();
  233. }catch(IllegalArgumentException e){
  234. l.error(e.getMessage());
  235. }
  236. if(configuration == null){
  237. throw new StartupException("Failed to load configuration", true);
  238. }
  239. return configuration;
  240. }
  241. /**
  242. * Generates a HashMap with the first value of a MultivaluedMap because working with this "maps" is a PITA.
  243. * @param mv the MultivaluedMap with the keys and values
  244. * @return a Map (Hash) with the first value corresponding to the key.
  245. */
  246. public static Map<String, String> hashMapOf(final MultivaluedMap<String, String> mv){
  247. if(mv == null)
  248. throw new IllegalArgumentException("Invalid null argument");
  249. Map<String, String> map = new HashMap<String, String>();
  250. for(String k : mv.keySet()){
  251. String v = mv.getFirst(k);
  252. if(StringUtils.isNotEmpty(v))
  253. map.put(k, v);
  254. }
  255. return map;
  256. }
  257. /**
  258. * Generates a Base64-encoded binary MD5 sum of the content of the response as described by rfc1864
  259. * @param input the string
  260. * @return Base64-encoded binary MD5 sum of the string
  261. */
  262. public static String getMD5Base64(String input) {
  263. if(input == null)
  264. throw new IllegalArgumentException("Invalid null argument");
  265. String ret = "";
  266. try {
  267. MessageDigest digest = MessageDigest.getInstance("MD5");
  268. digest.update(input.getBytes("UTF-8"));
  269. byte[] rawData = digest.digest();
  270. BASE64Encoder bencoder = new BASE64Encoder();
  271. ret = bencoder.encode(rawData);
  272. } catch (Exception ex) {
  273. l.error(ex.getMessage());
  274. }
  275. return ret;
  276. }
  277. /**
  278. * The length of the request body in octets (8-bit bytes)
  279. * @param input the string
  280. * @return an Integer with the length of the request body in octets.
  281. */
  282. public static Integer getOctetLength(String input){
  283. if(input == null)
  284. throw new IllegalArgumentException("Invalid null argument");
  285. byte[] responseBytes;
  286. int result = 0;
  287. try {
  288. responseBytes = input.getBytes("UTF-8");
  289. result = responseBytes.length;
  290. } catch ( UnsupportedEncodingException ex ) {
  291. l.error(ex.getMessage());
  292. }
  293. return result;
  294. }
  295. /**
  296. * The date and time that the message was sent
  297. * @return The date and time that the message was sent
  298. */
  299. public static String getDateHeader(){
  300. return new DateTime().toString(ISODateTimeFormat.dateTime());
  301. }
  302. /**
  303. * Generates a string like {call stmt(?,?,?)} to be used by a CallableStatement to execute a function
  304. * or a procedure.
  305. * @param queryName the name of the function or procedure
  306. * @param paramsSize the amount of parameters to be passed to the function/procedure
  307. * @return a string ready to be fed to a CallableStatement
  308. */
  309. public static String getCallableStatementCallString(final String queryName, final Integer paramsSize){
  310. if(StringUtils.isBlank(queryName))
  311. throw new IllegalArgumentException("The name can't be null, empty or blank" );
  312. StringBuilder b = new StringBuilder("{CALL ");
  313. b.append(queryName);
  314. b.append("(");
  315. for(int i = 0; i < paramsSize; i++){
  316. b.append("?,");
  317. }
  318. if(b.charAt(b.length() - 1) == ','){
  319. b.deleteCharAt(b.length() - 1);
  320. }
  321. b.append(")}");
  322. return b.toString();
  323. }
  324. }