001 package railo.runtime.orm.hibernate; 002 003 import java.sql.DatabaseMetaData; 004 import java.sql.ResultSet; 005 import java.util.ArrayList; 006 import java.util.HashSet; 007 import java.util.Iterator; 008 import java.util.Set; 009 010 import org.hibernate.HibernateException; 011 import org.hibernate.metadata.ClassMetadata; 012 import org.hibernate.type.Type; 013 014 import railo.commons.lang.StringUtil; 015 import railo.runtime.Component; 016 import railo.runtime.component.Property; 017 import railo.runtime.component.PropertyImpl; 018 import railo.runtime.db.DatasourceConnection; 019 import railo.runtime.op.Caster; 020 import railo.runtime.orm.ORMException; 021 import railo.runtime.type.Array; 022 import railo.runtime.type.Collection.Key; 023 import railo.runtime.type.Struct; 024 import railo.runtime.type.StructImpl; 025 import railo.runtime.type.util.KeyConstants; 026 import railo.runtime.type.util.ListUtil; 027 028 029 public class HibernateUtil { 030 031 public static final short FIELDTYPE_ID=0; 032 public static final short FIELDTYPE_COLUMN=1; 033 public static final short FIELDTYPE_TIMESTAMP=2; 034 public static final short FIELDTYPE_RELATION=4; 035 public static final short FIELDTYPE_VERSION=8; 036 public static final short FIELDTYPE_COLLECTION=16; 037 038 private static final String KEYWORDS="absolute,access,accessible,action,add,after,alias,all,allocate,allow,alter,analyze,and,any,application,are,array,as,asc,asensitive,assertion,associate,asutime,asymmetric,at,atomic,audit,authorization,aux,auxiliary,avg,backup,before,begin,between,bigint,binary,bit,bit_length,blob,boolean,both,breadth,break,browse,bufferpool,bulk,by,cache,call,called,capture,cardinality,cascade,cascaded,case,cast,catalog,ccsid,change,char,char_length,character,character_length,check,checkpoint,clob,close,cluster,clustered,coalesce,collate,collation,collection,collid,column,comment,commit,compress,compute,concat,condition,connect,connection,constraint,constraints,constructor,contains,containstable,continue,convert,corresponding,count,count_big,create,cross,cube,current,current_date,current_default_transform_group,current_lc_ctype,current_path,current_role,current_server,current_time,current_timestamp,current_timezone,current_transform_group_for_type,current_user,cursor,cycle,data,database,databases,date,day,day_hour,day_microsecond,day_minute,day_second,days,db2general,db2genrl,db2sql,dbcc,dbinfo,deallocate,dec,decimal,declare,default,defaults,deferrable,deferred,delayed,delete,deny,depth,deref,desc,describe,descriptor,deterministic,diagnostics,disallow,disconnect,disk,distinct,distinctrow,distributed,div,do,domain,double,drop,dsnhattr,dssize,dual,dummy,dump,dynamic,each,editproc,else,elseif,enclosed,encoding,end,end-exec,end-exec1,endexec,equals,erase,errlvl,escape,escaped,except,exception,excluding,exclusive,exec,execute,exists,exit,explain,external,extract,false,fenced,fetch,fieldproc,file,fillfactor,filter,final,first,float,float4,float8,for,force,foreign,found,free,freetext,freetexttable,from,full,fulltext,function,general,generated,get,get_current_connection,global,go,goto,grant,graphic,group,grouping,handler,having,high_priority,hold,holdlock,hour,hour_microsecond,hour_minute,hour_second,hours,identified,identity,identity_insert,identitycol,if,ignore,immediate,in,including,increment,index,indicator,infile,inherit,initial,initially,inner,inout,input,insensitive,insert,int,int1,int2,int3,int4,int8,integer,integrity,intersect,interval,into,is,isobid,isolation,iterate,jar,java,join,key,keys,kill,language,large,last,lateral,leading,leave,left,level,like,limit,linear,lineno,lines,linktype,load,local,locale,localtime,localtimestamp,locator,locators,lock,lockmax,locksize,long,longblob,longint,longtext,loop,low_priority,lower,ltrim,map,master_ssl_verify_server_cert,match,max,maxextents,maxvalue,mediumblob,mediumint,mediumtext,method,microsecond,microseconds,middleint,min,minus,minute,minute_microsecond,minute_second,minutes,minvalue,mlslabel,mod,mode,modifies,modify,module,month,months,names,national,natural,nchar,nclob,new,new_table,next,no,no_write_to_binlog,noaudit,nocache,nocheck,nocompress,nocycle,nodename,nodenumber,nomaxvalue,nominvalue,nonclustered,none,noorder,not,nowait,null,nullif,nulls,number,numeric,numparts,nvarchar,obid,object,octet_length,of,off,offline,offsets,old,old_table,on,online,only,open,opendatasource,openquery,openrowset,openxml,optimization,optimize,option,optionally,or,order,ordinality,out,outer,outfile,output,over,overlaps,overriding,package,pad,parameter,part,partial,partition,path,pctfree,percent,piecesize,plan,position,precision,prepare,preserve,primary,print,prior,priqty,privileges,proc,procedure,program,psid,public,purge,queryno,raiserror,range,raw,read,read_write,reads,readtext,real,reconfigure,recovery,recursive,ref,references,referencing,regexp,relative,release,rename,repeat,replace,replication,require,resignal,resource,restart,restore,restrict,result,result_set_locator,return,returns,revoke,right,rlike,role,rollback,rollup,routine,row,rowcount,rowguidcol,rowid,rownum,rows,rrn,rtrim,rule,run,runtimestatistics,save,savepoint,schema,schemas,scope,scratchpad,scroll,search,second,second_microsecond,seconds,secqty,section,security,select,sensitive,separator,session,session_user,set,sets,setuser,share,show,shutdown,signal,similar,simple,size,smallint,some,source,space,spatial,specific,specifictype,sql,sql_big_result,sql_calc_found_rows,sql_small_result,sqlcode,sqlerror,sqlexception,sqlid,sqlstate,sqlwarning,ssl,standard,start,starting,state,static,statistics,stay,stogroup,stores,straight_join,style,subpages,substr,substring,successful,sum,symmetric,synonym,sysdate,sysfun,sysibm,sysproc,system,system_user,table,tablespace,temporary,terminated,textsize,then,time,timestamp,timezone_hour,timezone_minute,tinyblob,tinyint,tinytext,to,top,trailing,tran,transaction,translate,translation,treat,trigger,trim,true,truncate,tsequal,type,uid,under,undo,union,unique,unknown,unlock,unnest,unsigned,until,update,updatetext,upper,usage,use,user,using,utc_date,utc_time,utc_timestamp,validate,validproc,value,values,varbinary,varchar,varchar2,varcharacter,variable,variant,varying,vcat,view,volumes,waitfor,when,whenever,where,while,window,with,within,without,wlm,work,write,writetext,xor,year,year_month,zerofill,zone"; 039 private static final Set<String> keywords=new HashSet<String>(); 040 private static final Key FIELDTYPE = KeyConstants._fieldtype; 041 static { 042 Array arr = ListUtil.listToArray(KEYWORDS, ','); 043 Iterator<Object> it = arr.valueIterator(); 044 while(it.hasNext()){ 045 keywords.add(Caster.toString(it.next(),null)); 046 } 047 } 048 049 050 public static boolean isKeyword(String word){ 051 if(word==null) return false; 052 return keywords.contains(word.trim().toLowerCase()); 053 } 054 055 056 public static Type getPropertyType(ClassMetadata metaData, String name) throws HibernateException { 057 try{ 058 return metaData.getPropertyType(name); 059 } 060 catch(HibernateException he){ 061 if(name.equalsIgnoreCase(metaData.getIdentifierPropertyName())) 062 return metaData.getIdentifierType(); 063 064 String[] names = metaData.getPropertyNames(); 065 for(int i=0;i<names.length;i++){ 066 if(names[i].equalsIgnoreCase(name)) 067 return metaData.getPropertyType(names[i]); 068 } 069 throw he; 070 } 071 } 072 public static Type getPropertyType(ClassMetadata metaData, String name, Type defaultValue) { 073 try{ 074 return metaData.getPropertyType(name); 075 } 076 catch(HibernateException he){ 077 if(name.equalsIgnoreCase(metaData.getIdentifierPropertyName())) 078 return metaData.getIdentifierType(); 079 080 String[] names = metaData.getPropertyNames(); 081 for(int i=0;i<names.length;i++){ 082 if(names[i].equalsIgnoreCase(name)) 083 return metaData.getPropertyType(names[i]); 084 } 085 return defaultValue; 086 } 087 } 088 089 public static String validateColumnName(ClassMetadata metaData, String name) throws ORMException { 090 String res = validateColumnName(metaData, name,null); 091 if(res!=null) return res; 092 throw new ORMException("invalid name, there is no property with name ["+name+"] in the entity ["+metaData.getEntityName()+"]", 093 "valid properties names are ["+railo.runtime.type.util.ListUtil.arrayToList(metaData.getPropertyNames(), ", ")+"]"); 094 095 } 096 097 098 public static String validateColumnName(ClassMetadata metaData, String name, String defaultValue) { 099 if(name.equalsIgnoreCase(metaData.getIdentifierPropertyName())) 100 return metaData.getIdentifierPropertyName(); 101 102 String[] names = metaData.getPropertyNames(); 103 for(int i=0;i<names.length;i++){ 104 if(names[i].equalsIgnoreCase(name)) 105 return names[i]; 106 } 107 return defaultValue; 108 } 109 110 // 111 112 public static Property[] createPropertiesFromTable(DatasourceConnection dc, String tableName) { 113 Struct properties = new StructImpl(); 114 try { 115 DatabaseMetaData md = dc.getConnection().getMetaData(); 116 String dbName=dc.getDatasource().getDatabase(); 117 String name; 118 119 120 // get all columns 121 ResultSet res = md.getColumns(dbName, null, tableName, null); 122 Property p; 123 while(res.next()) { 124 name=res.getString("COLUMN_NAME"); 125 PropertyImpl pi=new PropertyImpl(); 126 p=pi; 127 pi.setName(name); 128 pi.setType(res.getString("TYPE_NAME")); 129 properties.setEL(name, p); 130 } 131 132 // ids 133 res = md.getPrimaryKeys(null, null, tableName); 134 while(res.next()) { 135 name=res.getString("COLUMN_NAME"); 136 p=(Property) properties.get(name,null); 137 if(p!=null) p.getDynamicAttributes().setEL("fieldtype", "id"); 138 } 139 140 // MUST foreign-key relation 141 142 } 143 catch(Throwable t){ 144 return new Property[0]; 145 } 146 147 Iterator it = properties.valueIterator(); 148 Property[] rtn=new Property[properties.size()]; 149 for(int i=0;i<rtn.length;i++){ 150 rtn[i]=(Property) it.next(); 151 } 152 153 return rtn; 154 } 155 156 157 public static Property[] getProperties(Component component,int fieldType, Property[] defaultValue) { 158 Property[] props = component.getProperties(true); 159 java.util.List<Property> rtn=new ArrayList<Property>(); 160 161 if(props!=null) { 162 for(int i=0;i<props.length;i++){ 163 if(fieldType==getFieldType(props[i],FIELDTYPE_COLUMN)) 164 rtn.add(props[i]); 165 } 166 } 167 return rtn.toArray(new Property[rtn.size()]); 168 } 169 170 171 private static int getFieldType(Property property, int defaultValue) { 172 return getFieldType(Caster.toString(property.getDynamicAttributes().get(FIELDTYPE, null),null),defaultValue); 173 174 } 175 176 private static int getFieldType(String fieldType, int defaultValue) { 177 if(StringUtil.isEmpty(fieldType,true)) return defaultValue; 178 fieldType=fieldType.trim().toLowerCase(); 179 180 181 if("id".equals(fieldType)) return FIELDTYPE_ID; 182 if("column".equals(fieldType)) return FIELDTYPE_COLUMN; 183 if("timestamp".equals(fieldType)) return FIELDTYPE_TIMESTAMP; 184 if("relation".equals(fieldType)) return FIELDTYPE_RELATION; 185 if("version".equals(fieldType)) return FIELDTYPE_VERSION; 186 if("collection".equals(fieldType)) return FIELDTYPE_COLLECTION; 187 return defaultValue; 188 } 189 190 }