/* * Copyright 2008 Alberto Gimeno <gimenete at gmail.com> * * 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 siena; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.math.BigDecimal; import java.security.MessageDigest; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Collection; import java.util.Date; import java.util.Iterator; import java.util.TimeZone; import java.util.UUID; import siena.embed.Embedded; import siena.embed.JavaSerializer; import siena.embed.JsonSerializer; import siena.jdbc.JdbcPersistenceManager.JdbcClassInfo; /** * Util class for general proposals. * @author gimenete 1.0 * @author jsanca 1.0.1 * */ public class Util { public static String join(Collection<String> s, String delimiter) { if (s.isEmpty()) return ""; Iterator<String> iter = s.iterator(); StringBuilder buffer = new StringBuilder(iter.next()); while (iter.hasNext()) buffer.append(delimiter).append(iter.next()); return buffer.toString(); } public static String sha1(String message) { try { byte[] buffer = message.getBytes("UTF-8"); MessageDigest md = MessageDigest.getInstance("SHA1"); md.update(buffer); byte[] digest = md.digest(); char[] hash = new char[40]; for(int i=0, n=0; i<digest.length; i++) { byte aux = digest[i]; int b = aux & 0xff; String hex = Integer.toHexString(b); if (hex.length() == 1) { hash[n++] = '0'; hash[n++] = hex.charAt(0); } else { hash[n++] = hex.charAt(0); hash[n++] = hex.charAt(1); } } return new String(hash); } catch(Exception e) { // should never happen. UTF-8 and SHA1 are constants throw new RuntimeException(e); } } public static Object fromString(Class<?> type, String value) { if(value == null) return null; if(type.isPrimitive()) { if(type == Boolean.TYPE) return Boolean.parseBoolean(value); if(type == Byte.TYPE) return Byte.parseByte(value); if(type == Short.TYPE) return Short.parseShort(value); if(type == Integer.TYPE) return Integer.parseInt(value); if(type == Long.TYPE) return Long.parseLong(value); if(type == Float.TYPE) return Float.parseFloat(value); if(type == Double.TYPE) return Double.parseDouble(value); } if(type == String.class) return value; if(type == Boolean.class) return Boolean.valueOf(value); if(type == Byte.class) return Byte.valueOf(value); if(type == Short.class) return Short.valueOf(value); if(type == Integer.class) return Integer.valueOf(value); if(type == Long.class) return Long.valueOf(value); if(type == Float.class) return Float.valueOf(value); if(type == Double.class) return Double.valueOf(value); if(type == Date.class) return timestamp(value); if(type == Json.class) return Json.loads(value); if(type == BigDecimal.class) return new BigDecimal(value); if(Enum.class.isAssignableFrom(type)) return Enum.valueOf((Class<Enum>) type, (String)value); throw new IllegalArgumentException("Unsupported type: "+type.getName()); } public static Object fromString(Class<?> type, String value, boolean retValueIfNotSupported) { if(value == null) return null; if(type.isPrimitive()) { if(type == Boolean.TYPE) return Boolean.parseBoolean(value); if(type == Byte.TYPE) return Byte.parseByte(value); if(type == Short.TYPE) return Short.parseShort(value); if(type == Integer.TYPE) return Integer.parseInt(value); if(type == Long.TYPE) return Long.parseLong(value); if(type == Float.TYPE) return Float.parseFloat(value); if(type == Double.TYPE) return Double.parseDouble(value); } if(type == String.class) return value; if(type == Boolean.class) return Boolean.valueOf(value); if(type == Byte.class) return Byte.valueOf(value); if(type == Short.class) return Short.valueOf(value); if(type == Integer.class) return Integer.valueOf(value); if(type == Long.class) return Long.valueOf(value); if(type == Float.class) return Float.valueOf(value); if(type == Double.class) return Double.valueOf(value); if(type == Date.class) return timestamp(value); if(type == Json.class) return Json.loads(value); if(type == BigDecimal.class) return new BigDecimal(value); if(Enum.class.isAssignableFrom(type)) return Enum.valueOf((Class<Enum>) type, (String)value); if(!retValueIfNotSupported){ throw new IllegalArgumentException("Unsupported type: "+type.getName()); } return value; } private static final SimpleDateFormat TIMESTAMP_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS") { private static final long serialVersionUID = 1L; { setTimeZone(TimeZone.getTimeZone("UTC")); } }; private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd") { private static final long serialVersionUID = 1L; { setTimeZone(TimeZone.getTimeZone("UTC")); } }; private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss") { private static final long serialVersionUID = 1L; { setTimeZone(TimeZone.getTimeZone("UTC")); } }; public static Date timestamp(String s) { try { return TIMESTAMP_FORMAT.parse(s); } catch (ParseException e) { throw new SienaException(e); } } public static String timestamp(Date d) { return TIMESTAMP_FORMAT.format(d); } public static Date time(String s) { try { return TIME_FORMAT.parse(s); } catch (ParseException e) { throw new SienaException(e); } } public static String time(Date d) { return TIME_FORMAT.format(d); } public static Date date(String s) { try { return DATE_FORMAT.parse(s); } catch (ParseException e) { throw new SienaException(e); } } public static String date(Date d) { return DATE_FORMAT.format(d); } public static String toString(Field field, Object value) { if(value instanceof Date) { if(field.getAnnotation(DateTime.class) != null) return timestamp((Date) value); else if(field.getAnnotation(Time.class) != null) return time((Date) value); else if(field.getAnnotation(SimpleDate.class) != null) return date((Date) value); else return timestamp((Date) value); } return value.toString(); } public static Object fromObject(Field field, Object value) { Class<?> type = field.getType(); if(value == null) { if(type.isPrimitive()){ if(byte.class==type) return (byte)0; else if(Character.TYPE==type) return (char)0; else if(Short.TYPE==type) return (short)0; else if(Integer.TYPE==type) return (int)0; else if(Long.TYPE==type) return (long)0; else if(Float.TYPE==type) return (float)0; else if(Double.TYPE==type) return (double)0; else if(Boolean.TYPE==type) return false; } return null; } if(Number.class.isAssignableFrom(value.getClass())) { Number number = (Number) value; if(byte.class==type || Byte.class==type) return number.byteValue(); else if(Short.TYPE==type || Short.class==type) return number.shortValue(); else if(Integer.TYPE==type || Integer.class==type) return number.intValue(); else if(Long.TYPE==type || Long.class==type) return number.longValue(); else if(Float.TYPE==type || Float.class==type) return number.floatValue(); else if(Double.TYPE==type || Double.class==type) return number.doubleValue(); else if(Boolean.TYPE==type || Boolean.class==type) return number.byteValue() != 0; else if(BigDecimal.class==type) return (BigDecimal)value; } if(String.class.isAssignableFrom(value.getClass())) { if(Json.class.isAssignableFrom(type)) { return Json.loads((String) value); } if(UUID.class == type) { return UUID.fromString((String)value); } } Embedded embed = field.getAnnotation(Embedded.class); if(embed != null) { switch(embed.mode()){ case SERIALIZE_JSON: if(String.class.isAssignableFrom(value.getClass())) { Json data = Json.loads((String) value); return JsonSerializer.deserialize(field, data); } break; case SERIALIZE_JAVA: try { return JavaSerializer.deserialize((byte[])value); } catch (IOException e) { throw new SienaException(e); } catch (ClassNotFoundException e) { throw new SienaException(e); } case NATIVE: break; } } if(String.class.isAssignableFrom(value.getClass())&& type.isEnum()) { return Enum.valueOf((Class<Enum>) type, (String)value); } if(String.class.isAssignableFrom(value.getClass())&& type != String.class) { return fromString(field.getType(), (String)value, true); } return value; } public static void setField(Object object, Field f, Object value) { try { f.set(object, value); } catch (Exception e) { try { f.setAccessible(true); f.set(object, value); } catch (Exception e2) { throw new SienaException(e2); } } } public static void setFromObject(Object object, Field f, Object value) { setField(object, f, fromObject(f, value)); } public static void setFromString(Object object, Field f, String value) { setField(object, f, fromString(f.getType(), value)); } public static Object readField(Object object, Field field) { boolean wasAccess = true; if(!field.isAccessible()){ field.setAccessible(true); wasAccess = false; } try { return field.get(object); } catch (Exception e) { throw new SienaException(e); } finally { if(!wasAccess){ field.setAccessible(false); } } } public static Field getField(Class<?> clazz, String fieldName) { Class<?> cl = clazz; while (cl!=null) { try { return cl.getDeclaredField(fieldName); } catch(NoSuchFieldException e){ cl = cl.getSuperclass(); } catch (Exception e) { throw new SienaException(e); } } return null; } public static Object translateDate(Field f, Date value) { long t = value.getTime(); SimpleDate simpleDate = f.getAnnotation(SimpleDate.class); if(simpleDate != null) { return new java.sql.Date(t); } DateTime dateTime = f.getAnnotation(DateTime.class); if(dateTime != null) { return new java.sql.Timestamp(t); } Time time = f.getAnnotation(Time.class); if(time != null) { return new java.sql.Time(t); } return new java.sql.Timestamp(t); } /** * Creates an instance of a model from its class. * It tries to find a default constructor and if not found, it uses class.newInstance() * * @param clazz the class of the model * @return the instance of the model */ public static <T> T createObjectInstance(Class<T> clazz){ try { Constructor<T> c = clazz.getDeclaredConstructor(); c.setAccessible(true); return c.newInstance(); }catch(NoSuchMethodException ex){ try { return clazz.newInstance(); }catch (Exception e) { throw new SienaException(e); } }catch(Exception e){ throw new SienaException(e); } } public static void copyObject(Object objFrom, Object objTo) { Class<?> clazz = objFrom.getClass(); for (Field field : JdbcClassInfo.getClassInfo(clazz).allFields) { Util.setField(objTo, field, Util.readField(objFrom, field)); } } public static Class<?> getGenericClass(Field f, int n) { Type genericFieldType = f.getGenericType(); if(genericFieldType instanceof ParameterizedType){ ParameterizedType aType = (ParameterizedType) genericFieldType; Type[] fieldArgTypes = aType.getActualTypeArguments(); return (Class<?>) fieldArgTypes[n]; } return null; } }