001 package railo.runtime.db; 002 003 import java.util.Map; 004 import java.util.TimeZone; 005 006 import org.apache.commons.collections.map.ReferenceMap; 007 008 import railo.commons.lang.ClassException; 009 import railo.commons.lang.ClassUtil; 010 import railo.commons.lang.StringUtil; 011 import railo.runtime.config.Config; 012 import railo.runtime.engine.ThreadLocalPageContext; 013 import railo.runtime.op.Caster; 014 import railo.runtime.type.Collection; 015 import railo.runtime.type.Struct; 016 017 018 /** 019 * 020 */ 021 public final class DataSourceImpl implements Cloneable, DataSource { 022 023 private String dsn; 024 private String username; 025 private String password; 026 private boolean readOnly; 027 private Class clazz; 028 private String host; 029 private String database; 030 private int port; 031 private String dsnTranslated; 032 private int connectionLimit; 033 private int connectionTimeout; 034 private boolean blob; 035 private boolean clob; 036 private int allow; 037 private Struct custom; 038 private String name; 039 private long metaCacheTimeout; 040 private Map<String,ProcMetaCollection> procedureColumnCache; 041 private boolean validate; 042 private boolean storage; 043 private TimeZone timezone; 044 045 /** 046 * constructor of the class 047 * @param name 048 * @param clazz 049 * @param host 050 * @param dsn 051 * @param database 052 * @param port 053 * @param username 054 * @param password 055 * @param connectionLimit 056 * @param connectionTimeout 057 * @param blob 058 * @param clob 059 * @param allow 060 * @param custom 061 * @param readOnly 062 * @throws ClassException 063 */ 064 public DataSourceImpl(String name,String className, String host, String dsn, String database, int port, String username, String password, 065 int connectionLimit, int connectionTimeout,long metaCacheTimeout, boolean blob, boolean clob, int allow, Struct custom, boolean readOnly, 066 boolean validate,boolean storage, TimeZone timezone) throws ClassException { 067 this(name, toClass(className), host, dsn, database, port, username, password, connectionLimit, connectionTimeout,metaCacheTimeout, blob, clob, allow, custom, readOnly,validate,storage,timezone); 068 069 } 070 071 private static Class toClass(String className) throws ClassException { 072 try { 073 return Class.forName(className); 074 } 075 catch (ClassNotFoundException e) { 076 Config config = ThreadLocalPageContext.getConfig(); 077 if(config!=null) return ClassUtil.loadClass(config.getClassLoader(),className); 078 return ClassUtil.loadClass(className); 079 } 080 } 081 082 private DataSourceImpl(String name,Class clazz, String host, String dsn, String database, int port, String username, String password, 083 int connectionLimit, int connectionTimeout,long metaCacheTimeout, boolean blob, boolean clob, int allow, Struct custom, boolean readOnly, 084 boolean validate,boolean storage,TimeZone timezone) { 085 if(allow<0) allow=ALLOW_ALL; 086 this.name=name; 087 this.clazz=clazz; 088 this.host=host; 089 this.database=database; 090 this.dsn=dsn; 091 this.port=port; 092 this.username=username; 093 this.password=password; 094 095 this.connectionLimit=connectionLimit; 096 this.connectionTimeout=connectionTimeout; 097 this.blob=blob; 098 this.clob=clob; 099 this.allow=allow; 100 this.readOnly=readOnly; 101 this.custom=custom; 102 this.validate=validate; 103 this.storage=storage; 104 105 this.dsnTranslated=dsn; 106 this.metaCacheTimeout= metaCacheTimeout; 107 this.timezone=timezone; 108 translateDsn(); 109 110 // throw new DatabaseException("can't find class ["+classname+"] for jdbc driver, check if driver (jar file) is inside lib folder",e.getMessage(),null,null,null); 111 112 } 113 private void translateDsn() { 114 dsnTranslated=replace(dsnTranslated,"host",host,false); 115 dsnTranslated=replace(dsnTranslated,"database",database,false); 116 dsnTranslated=replace(dsnTranslated,"port",Caster.toString(port),false); 117 dsnTranslated=replace(dsnTranslated,"username",username,false); 118 dsnTranslated=replace(dsnTranslated,"password",password,false); 119 120 Collection.Key[] keys = custom==null?new Collection.Key[0]:custom.keys(); 121 for(int i=0;i<keys.length;i++) { 122 dsnTranslated=replace(dsnTranslated,keys[i].getString(),Caster.toString(custom.get(keys[i],null),""),true); 123 } 124 } 125 126 private String replace(String src, String name, String value,boolean doQueryString) { 127 if(StringUtil.indexOfIgnoreCase(src,"{"+name+"}")!=-1) { 128 return StringUtil.replace(dsnTranslated,"{"+name+"}",value,false); 129 } 130 if(!doQueryString) return src; 131 if(clazz.getName().indexOf("microsoft")!=-1 || clazz.getName().indexOf("jtds")!=-1) 132 return src+=';'+name+'='+value; 133 return src+=((src.indexOf('?')!=-1)?'&':'?')+name+'='+value; 134 } 135 136 /** 137 * @see railo.runtime.db.DataSource#getDsnOriginal() 138 */ 139 public String getDsnOriginal() { 140 return dsn; 141 } 142 143 /** 144 * @see railo.runtime.db.DataSource#getDsnTranslated() 145 */ 146 public String getDsnTranslated() { 147 return dsnTranslated; 148 } 149 150 /** 151 * @see railo.runtime.db.DataSource#getPassword() 152 */ 153 public String getPassword() { 154 return password; 155 } 156 /** 157 * @see railo.runtime.db.DataSource#getUsername() 158 */ 159 public String getUsername() { 160 return username; 161 } 162 163 /** 164 * @see railo.runtime.db.DataSource#isReadOnly() 165 */ 166 public boolean isReadOnly() { 167 return readOnly; 168 } 169 170 /** 171 * @see railo.runtime.db.DataSource#hasAllow(int) 172 */ 173 public boolean hasAllow(int allow) { 174 return (this.allow&allow)>0; 175 } 176 177 /** 178 * @see railo.runtime.db.DataSource#getClazz() 179 */ 180 public Class getClazz() { 181 return clazz; 182 } 183 184 /** 185 * @see railo.runtime.db.DataSource#getDatabase() 186 */ 187 public String getDatabase() { 188 return database; 189 } 190 191 /** 192 * @see railo.runtime.db.DataSource#getPort() 193 */ 194 public int getPort() { 195 return port; 196 } 197 198 /** 199 * @see railo.runtime.db.DataSource#getHost() 200 */ 201 public String getHost() { 202 return host; 203 } 204 205 /** 206 * @see railo.runtime.db.DataSource#clone() 207 */ 208 public Object clone() { 209 return new DataSourceImpl(name,clazz, host, dsn, database, port, username, password, connectionLimit, connectionTimeout,metaCacheTimeout, blob, clob, allow, custom, readOnly,validate,storage,timezone); 210 } 211 212 /** 213 * @see railo.runtime.db.DataSource#cloneReadOnly() 214 */ 215 public DataSource cloneReadOnly() { 216 return new DataSourceImpl(name,clazz, host, dsn, database, port, username, password, connectionLimit, connectionTimeout,metaCacheTimeout, blob, clob, allow,custom, true,validate,storage,timezone); 217 } 218 219 /** 220 * @see railo.runtime.db.DataSource#isBlob() 221 */ 222 public boolean isBlob() { 223 return blob; 224 } 225 226 /** 227 * @see railo.runtime.db.DataSource#isClob() 228 */ 229 public boolean isClob() { 230 return clob; 231 } 232 233 /** 234 * @see railo.runtime.db.DataSource#getConnectionLimit() 235 */ 236 public int getConnectionLimit() { 237 return connectionLimit; 238 } 239 240 /** 241 * @see railo.runtime.db.DataSource#getConnectionTimeout() 242 */ 243 public int getConnectionTimeout() { 244 return connectionTimeout; 245 } 246 247 248 //FUTURE add to interface 249 public long getMetaCacheTimeout() { 250 return metaCacheTimeout; 251 } 252 253 // FUTURE add to interface 254 public TimeZone getTimeZone() { 255 return timezone; 256 } 257 258 /** 259 * @see railo.runtime.db.DataSource#getCustomValue(java.lang.String) 260 */ 261 public String getCustomValue(String key) { 262 return Caster.toString(custom.get(key,null),""); 263 } 264 265 /** 266 * @see railo.runtime.db.DataSource#getCustomNames() 267 */ 268 public String[] getCustomNames() { 269 return custom.keysAsString(); 270 } 271 272 /** 273 * @see railo.runtime.db.DataSource#getCustoms() 274 */ 275 public Struct getCustoms() { 276 return (Struct)custom.clone(); 277 } 278 279 /** 280 * @see railo.runtime.db.DataSource#hasSQLRestriction() 281 */ 282 public boolean hasSQLRestriction() { 283 return this.allow!=DataSource.ALLOW_ALL; 284 } 285 286 /** 287 * @see railo.runtime.db.DataSource#getName() 288 */ 289 public String getName() { 290 return name; 291 } 292 293 /** 294 * @see railo.runtime.db.DataSource#setClazz(java.lang.Class) 295 */ 296 public void setClazz(Class clazz) { 297 this.clazz = clazz; 298 } 299 300 /** 301 * 302 * @see java.lang.Object#toString() 303 */ 304 public String toString() { 305 return this.dsnTranslated; 306 } 307 308 /** 309 * 310 * @see java.lang.Object#equals(java.lang.Object) 311 */ 312 public boolean equals(Object obj) { 313 if(this==obj)return true; 314 if(!(obj instanceof DataSourceImpl)) return false; 315 DataSourceImpl ds = (DataSourceImpl)obj; 316 return this.getDsnTranslated().equals(ds.getDsnTranslated()); 317 } 318 319 public Map<String,ProcMetaCollection> getProcedureColumnCache() { 320 if(procedureColumnCache==null) 321 procedureColumnCache=new ReferenceMap(); 322 return procedureColumnCache; 323 } 324 /* * 325 * 326 * @see railo.runtime.db.DataSource#getMaxConnection() 327 * / 328 public int getMaxConnection() { 329 return maxConnection; 330 }*/ 331 332 public boolean validate() { 333 return validate; 334 } 335 336 public boolean isStorage() { 337 return storage; 338 } 339 340 /* * 341 * @param maxConnection the maxConnection to set 342 * / 343 protected void setMaxConnection(int maxConnection) { 344 this.maxConnection = maxConnection; 345 }*/ 346 347 }