001    package railo.runtime.tag;
002    
003    import java.sql.DatabaseMetaData;
004    import java.sql.ResultSet;
005    import java.sql.SQLException;
006    import java.util.HashMap;
007    import java.util.HashSet;
008    import java.util.Map;
009    import java.util.Set;
010    import java.util.regex.Pattern;
011    
012    import railo.commons.lang.StringUtil;
013    import railo.commons.sql.SQLUtil;
014    import railo.runtime.PageContext;
015    import railo.runtime.db.DataSourceManager;
016    import railo.runtime.db.DatasourceConnection;
017    import railo.runtime.exp.ApplicationException;
018    import railo.runtime.exp.DatabaseException;
019    import railo.runtime.exp.PageException;
020    import railo.runtime.ext.tag.TagImpl;
021    import railo.runtime.listener.ApplicationContextPro;
022    import railo.runtime.op.Caster;
023    import railo.runtime.op.Constants;
024    import railo.runtime.timer.Stopwatch;
025    import railo.runtime.type.Array;
026    import railo.runtime.type.ArrayImpl;
027    import railo.runtime.type.Collection;
028    import railo.runtime.type.Collection.Key;
029    import railo.runtime.type.KeyImpl;
030    import railo.runtime.type.QueryColumn;
031    import railo.runtime.type.QueryImpl;
032    import railo.runtime.type.QueryPro;
033    import railo.runtime.type.SVArray;
034    import railo.runtime.type.Struct;
035    import railo.runtime.type.StructImpl;
036    
037    /**
038    * Handles all interactions with files. The attributes you use with cffile depend on the value of the action attribute. 
039    *  For example, if the action = "write", use the attributes associated with writing a text file.
040    *
041    *
042    *
043    **/
044    public final class DBInfo extends TagImpl {
045    
046            private static final Key TABLE_NAME = KeyImpl.intern("TABLE_NAME");
047            private static final Key COLUMN_NAME = KeyImpl.intern("COLUMN_NAME");
048            private static final Key IS_PRIMARYKEY = KeyImpl.intern("IS_PRIMARYKEY");
049            private static final Key IS_FOREIGNKEY = KeyImpl.intern("IS_FOREIGNKEY");
050            private static final Key COLUMN_DEF = KeyImpl.intern("COLUMN_DEF");
051            private static final Key COLUMN_DEFAULT_VALUE = KeyImpl.intern("COLUMN_DEFAULT_VALUE");
052            private static final Key REFERENCED_PRIMARYKEY = KeyImpl.intern("REFERENCED_PRIMARYKEY");
053            private static final Key REFERENCED_PRIMARYKEY_TABLE = KeyImpl.intern("REFERENCED_PRIMARYKEY_TABLE");
054            private static final Key USER = KeyImpl.intern("USER");
055            private static final Key TABLE_SCHEM = KeyImpl.intern("TABLE_SCHEM");
056            private static final Key DECIMAL_DIGITS = KeyImpl.intern("DECIMAL_DIGITS");
057    
058            private static final Key DATABASE_NAME = KeyImpl.intern("database_name");
059            private static final Key TABLE_CAT = KeyImpl.intern("TABLE_CAT");
060            private static final Key PROCEDURE = KeyImpl.intern("procedure");
061            private static final Key CATALOG = KeyImpl.intern("catalog");
062            private static final Key SCHEMA = KeyImpl.intern("schema");
063            private static final Key DATABASE_PRODUCTNAME = KeyImpl.intern("DATABASE_PRODUCTNAME");
064            private static final Key DATABASE_VERSION = KeyImpl.intern("DATABASE_VERSION");
065            private static final Key DRIVER_NAME = KeyImpl.intern("DRIVER_NAME");
066            private static final Key DRIVER_VERSION = KeyImpl.intern("DRIVER_VERSION");
067            private static final Key JDBC_MAJOR_VERSION = KeyImpl.intern("JDBC_MAJOR_VERSION");
068            private static final Key JDBC_MINOR_VERSION = KeyImpl.intern("JDBC_MINOR_VERSION");     
069            
070            private static final int TYPE_NONE=0;
071            private static final int TYPE_DBNAMES=1;
072            private static final int TYPE_TABLES=2;
073            private static final int TYPE_TABLE_COLUMNS = 3;
074            private static final int TYPE_VERSION = 4;
075            private static final int TYPE_PROCEDURES = 5;
076            private static final int TYPE_PROCEDURE_COLUMNS = 6;
077            private static final int TYPE_FOREIGNKEYS = 7;
078            private static final int TYPE_INDEX = 8;
079            private static final int TYPE_USERS = 9;
080            private static final int TYPE_TERMS = 10;
081            private static final Collection.Key CARDINALITY = KeyImpl.init("CARDINALITY");
082    
083            
084            //private static final String[] ALL_TABLE_TYPES = {"TABLE", "VIEW", "SYSTEM TABLE", "SYNONYM"};
085            
086            private String datasource;
087            private String name;
088            private int type;
089            
090            
091            private String dbname;
092            private String password;
093            private String pattern;
094            private String table;
095            private String procedure;
096            private String username;
097            private String strType;
098            
099            
100            /**
101            * @see javax.servlet.jsp.tagext.Tag#release()
102            */
103            public void release()   {
104                    super.release();
105                    datasource=null;
106                    name=null;
107                    type=TYPE_NONE;
108                    dbname=null;
109                    password=null;
110                    pattern=null;
111                    table=null;
112                    procedure=null;
113                    username=null;
114                    
115                    
116                    
117            }
118    
119            /**
120             * @param procedure the procedure to set
121             */
122            public void setProcedure(String procedure) {
123                    this.procedure = procedure;
124            }
125    
126            /**
127             * @param datasource the datasource to set
128             */
129            public void setDatasource(String datasource) {
130                    this.datasource = datasource;
131            }
132    
133            /**
134             * @param name the name to set
135             */
136            public void setName(String name) {
137                    this.name = name;
138            }
139    
140            /**
141             * @param type the type to set
142             * @throws ApplicationException 
143             */
144            public void setType(String strType) throws ApplicationException {
145                    this.strType=strType;
146                    strType=strType.toLowerCase().trim();
147                    
148                    if("dbnames".equals(strType))                   this.type=TYPE_DBNAMES;
149                    else if("dbname".equals(strType))               this.type=TYPE_DBNAMES;
150                    else if("tables".equals(strType))               this.type=TYPE_TABLES;
151                    else if("table".equals(strType))                this.type=TYPE_TABLES;
152                    else if("columns".equals(strType))              this.type=TYPE_TABLE_COLUMNS;
153                    else if("column".equals(strType))               this.type=TYPE_TABLE_COLUMNS;
154                    else if("version".equals(strType))              this.type=TYPE_VERSION;
155                    else if("procedures".equals(strType))   this.type=TYPE_PROCEDURES;
156                    else if("procedure".equals(strType))    this.type=TYPE_PROCEDURES;
157                    
158    
159                    else if("table_columns".equals(strType))        this.type=TYPE_TABLE_COLUMNS;
160                    else if("table_column".equals(strType))         this.type=TYPE_TABLE_COLUMNS;
161                    else if("column_table".equals(strType))         this.type=TYPE_TABLE_COLUMNS;
162                    else if("column_tables".equals(strType))        this.type=TYPE_TABLE_COLUMNS;
163                    
164                    else if("tablecolumns".equals(strType))         this.type=TYPE_TABLE_COLUMNS;
165                    else if("tablecolumn".equals(strType))          this.type=TYPE_TABLE_COLUMNS;
166                    else if("columntable".equals(strType))          this.type=TYPE_TABLE_COLUMNS;
167                    else if("columntables".equals(strType))         this.type=TYPE_TABLE_COLUMNS;
168                    
169                    else if("procedure_columns".equals(strType))    this.type=TYPE_PROCEDURE_COLUMNS;
170                    else if("procedure_column".equals(strType))             this.type=TYPE_PROCEDURE_COLUMNS;
171                    else if("column_procedure".equals(strType))             this.type=TYPE_PROCEDURE_COLUMNS;
172                    else if("column_procedures".equals(strType))    this.type=TYPE_PROCEDURE_COLUMNS;
173                    
174                    else if("procedurecolumns".equals(strType))     this.type=TYPE_PROCEDURE_COLUMNS;
175                    else if("procedurecolumn".equals(strType))              this.type=TYPE_PROCEDURE_COLUMNS;
176                    else if("columnprocedure".equals(strType))              this.type=TYPE_PROCEDURE_COLUMNS;
177                    else if("columnprocedures".equals(strType))     this.type=TYPE_PROCEDURE_COLUMNS;
178                    
179                    else if("foreignkeys".equals(strType))  this.type=TYPE_FOREIGNKEYS;
180                    else if("foreignkey".equals(strType))   this.type=TYPE_FOREIGNKEYS;
181                    else if("index".equals(strType))                this.type=TYPE_INDEX;
182                    else if("users".equals(strType))                this.type=TYPE_USERS;
183                    else if("user".equals(strType))                 this.type=TYPE_USERS;
184                    
185                    else if("term".equals(strType))         this.type=TYPE_TERMS;
186                    else if("terms".equals(strType))        this.type=TYPE_TERMS;
187                    
188                    else throw new ApplicationException("invalid value for attribute type ["+strType+"]",
189                                    "valid values are [dbname,tables,columns,version,procedures,foreignkeys,index,users]");
190                    
191            }
192    
193            /**
194             * @param dbname the dbname to set
195             */
196            public void setDbname(String dbname) {
197                    this.dbname = dbname;
198            }
199            public void setDbnames(String dbname) {
200                    this.dbname = dbname;
201            }
202    
203            /**
204             * @param password the password to set
205             */
206            public void setPassword(String password) {
207                    this.password = password;
208            }
209    
210            /**
211             * @param pattern the pattern to set
212             */
213            public void setPattern(String pattern) {
214                    this.pattern = pattern;
215            }
216    
217            /**
218             * @param table the table to set
219             */
220            public void setTable(String table) {
221                    this.table = table;
222            }
223    
224            /**
225             * @param username the username to set
226             */
227            public void setUsername(String username) {
228                    this.username = username;
229            }
230    
231    
232            /**
233            * @see javax.servlet.jsp.tagext.Tag#doStartTag()
234            */
235            public int doStartTag() throws PageException    {
236                    datasource=getDatasource(pageContext, datasource);
237                    DataSourceManager manager = pageContext.getDataSourceManager();
238                    DatasourceConnection dc=manager.getConnection(pageContext,datasource, username, password);
239                    try {
240                            
241                            if(type==TYPE_TABLE_COLUMNS)    typeColumns(dc.getConnection().getMetaData());
242                            else if(type==TYPE_DBNAMES)             typeDBNames(dc.getConnection().getMetaData());
243                            else if(type==TYPE_FOREIGNKEYS) typeForeignKeys(dc.getConnection().getMetaData());
244                            else if(type==TYPE_INDEX)               typeIndex(dc.getConnection().getMetaData());
245                            else if(type==TYPE_PROCEDURES)  typeProcedures(dc.getConnection().getMetaData());
246                            else if(type==TYPE_PROCEDURE_COLUMNS)typeProcedureColumns(dc.getConnection().getMetaData());
247                            else if(type==TYPE_TERMS)               typeTerms(dc.getConnection().getMetaData());
248                            else if(type==TYPE_TABLES)              typeTables(dc.getConnection().getMetaData());
249                            else if(type==TYPE_VERSION)             typeVersion(dc.getConnection().getMetaData());
250                            else if(type==TYPE_USERS)               typeUsers(dc.getConnection().getMetaData());
251                            
252                    }
253                    catch(SQLException sqle) {
254                            throw new DatabaseException(sqle,dc);
255                    }
256                    finally {
257                            manager.releaseConnection(pageContext,dc);
258                    }
259                    
260                    
261                                                                    
262                             
263                    return SKIP_BODY;
264            }
265    
266            
267            
268            private void typeColumns(DatabaseMetaData metaData) throws PageException, SQLException {
269                    required("table",table);
270                    
271                    Stopwatch stopwatch=new Stopwatch();
272                    stopwatch.start();
273    
274                    table=setCase(metaData, table);
275                    pattern=setCase(metaData, pattern);
276                    if(StringUtil.isEmpty(pattern,true)) pattern=null;
277                    String schema=null;
278                    int index=table.indexOf('.');
279                    if(index>0) {
280                            schema=table.substring(0,index);
281                            table=table.substring(index+1);
282                    }
283                    checkTable(metaData);
284                    
285            ResultSet columns = metaData.getColumns(dbname, schema, table, pattern);
286            QueryPro qry = new QueryImpl(columns,"query");
287            
288                    int len=qry.getRecordcount();
289                    
290                    qry.rename(COLUMN_DEF,COLUMN_DEFAULT_VALUE);
291            
292                    // make sure decimal digits exists
293                    QueryColumn col = qry.getColumn(DECIMAL_DIGITS,null);
294                    if(col==null){
295                            Array arr=new ArrayImpl();
296                            for(int i=1;i<=len;i++) {
297                                    arr.append(Constants.DOUBLE_ZERO);
298                            }
299                            qry.addColumn(DECIMAL_DIGITS, arr);
300                    }
301                    
302                    
303                    // add is primary
304                    Map primaries = new HashMap();
305                    String tblName;
306                    Array isPrimary=new ArrayImpl();
307                    Set set;
308                    Object o;
309                    for(int i=1;i<=len;i++) {
310                            
311                            // decimal digits
312                            o=qry.getAt(DECIMAL_DIGITS, i,null);
313                            if(o==null)qry.setAtEL(DECIMAL_DIGITS, i,Constants.DOUBLE_ZERO);
314                            
315                            set=(Set) primaries.get(tblName=(String) qry.getAt(TABLE_NAME, i));
316                            if(set==null) {
317                                    set=toSet(metaData.getPrimaryKeys(dbname, null, tblName),"COLUMN_NAME");
318                                    primaries.put(tblName,set);
319                            }
320                            isPrimary.append(set.contains(qry.getAt(COLUMN_NAME, i))?"YES":"NO"); 
321                    }
322                    qry.addColumn(IS_PRIMARYKEY, isPrimary);
323                    
324                    // add is foreignkey
325                    Map foreigns = new HashMap();
326                    Array isForeign=new ArrayImpl();
327                    Array refPrim=new ArrayImpl();
328                    Array refPrimTbl=new ArrayImpl();
329                    //Map map,inner;
330                    Map<String, Map<String, SVArray>> map;
331                    Map<String, SVArray> inner;
332                    for(int i=1;i<=len;i++) {
333                            map=(Map) foreigns.get(tblName=(String) qry.getAt(TABLE_NAME, i));
334                            if(map==null) {
335                                    map=toMap(metaData.getImportedKeys(dbname, schema, table),"FKCOLUMN_NAME",new String[]{"PKCOLUMN_NAME","PKTABLE_NAME"});
336                                    foreigns.put(tblName, map);
337                            }
338                            inner = map.get(qry.getAt(COLUMN_NAME, i));
339                            if(inner!=null) {
340                                    isForeign.append("YES");
341                                    refPrim.append(inner.get("PKCOLUMN_NAME")); 
342                                    refPrimTbl.append(inner.get("PKTABLE_NAME"));
343                            }
344                            else {
345                                    isForeign.append("NO"); 
346                                    refPrim.append("N/A"); 
347                                    refPrimTbl.append("N/A");        
348                            }
349                    }
350                    qry.addColumn(IS_FOREIGNKEY, isForeign);
351                    qry.addColumn(REFERENCED_PRIMARYKEY, refPrim);
352                    qry.addColumn(REFERENCED_PRIMARYKEY_TABLE, refPrimTbl);
353                    
354                    
355                    qry.setExecutionTime(stopwatch.time());
356            
357            
358                    pageContext.setVariable(name, qry);
359            }
360    
361            private Map<String,Map<String, SVArray>> toMap(ResultSet result,String columnName,String[] additional) throws SQLException {
362                    Map<String,Map<String, SVArray>> map=new HashMap<String,Map<String, SVArray>>();
363                    Map<String, SVArray> inner;
364                    String col;
365                    SVArray item;
366                    while(result.next()){
367                            col=result.getString(columnName);
368                            inner=map.get(col);
369                            if(inner!=null) {
370                                    for(int i=0;i<additional.length;i++) {
371                                            item=(SVArray) inner.get(additional[i]);
372                                            item.add(result.getString(additional[i]));
373                                            item.setPosition(item.size());
374                                    }
375                            }
376                            else {
377                                    inner=new HashMap<String, SVArray>();
378                                    map.put(col, inner);
379                                    for(int i=0;i<additional.length;i++) {
380                                            item=new SVArray();
381                                            item.add(result.getString(additional[i]));
382                                            inner.put(additional[i], item);
383                                    }
384                            }
385                    }
386                    return map;
387            }
388            
389            private Set<String> toSet(ResultSet result,String columnName) throws SQLException {
390                    Set<String> set = new HashSet<String>();
391                    while(result.next()){
392                            set.add(result.getString(columnName)); 
393                    }
394                    return set;
395            }
396    
397            private void typeDBNames(DatabaseMetaData metaData) throws PageException, SQLException {
398    
399                    Stopwatch stopwatch=new Stopwatch();
400                    stopwatch.start();
401            
402            railo.runtime.type.Query catalogs = new QueryImpl(metaData.getCatalogs(),"query");
403            railo.runtime.type.Query scheme = new QueryImpl(metaData.getSchemas(),"query");
404            
405            Pattern p=null;
406            if(pattern!=null && !"%".equals(pattern)) 
407                    p=SQLUtil.pattern(pattern, true);
408                    
409            
410            
411            String[] columns=new String[]{"database_name","type"};
412                    String[] types=new String[]{"VARCHAR","VARCHAR"};
413                    railo.runtime.type.Query qry=new QueryImpl(columns,types,0,"query");
414                    int row=1,len=catalogs.getRecordcount();
415                    String value;
416                    // catalog
417                    for(int i=1;i<=len;i++) {
418                            value=(String) catalogs.getAt(TABLE_CAT, i);
419                            if(!matchPattern(value,p)) continue;
420                            qry.addRow();
421                            qry.setAt(DATABASE_NAME, row, value);
422                            qry.setAt(KeyImpl.TYPE, row, "CATALOG");
423                            row++;
424                    }
425                    // scheme
426                    len=scheme.getRecordcount();
427                    for(int i=1;i<=len;i++) {
428                            value=(String) scheme.getAt(TABLE_SCHEM, i);
429                            if(!matchPattern(value,p)) continue;
430                            qry.addRow();
431                            qry.setAt(DATABASE_NAME, row, value);
432                            qry.setAt(KeyImpl.TYPE, row, "SCHEMA");
433                            row++;
434                    }
435                    
436            qry.setExecutionTime(stopwatch.time());
437            
438            
439                    pageContext.setVariable(name, qry);
440            }
441    
442            private void typeForeignKeys(DatabaseMetaData metaData) throws PageException, SQLException {
443                    required("table",table);
444                    
445                    Stopwatch stopwatch=new Stopwatch();
446                    stopwatch.start();
447            table=setCase(metaData, table);
448            int index=table.indexOf('.');
449                    String schema=null;
450            if(index>0) {
451                            schema=table.substring(0,index);
452                            table=table.substring(index+1);
453                    }
454                    
455                    checkTable(metaData);
456                    
457                    ResultSet columns = metaData.getCrossReference(dbname, schema, table, null, null, null);// TODO ist das ok
458                    railo.runtime.type.Query qry = new QueryImpl(columns,"query");
459                    
460                    
461            qry.setExecutionTime(stopwatch.time());
462            
463            
464                    pageContext.setVariable(name, qry);
465            }
466    
467            private void checkTable(DatabaseMetaData metaData) throws SQLException, ApplicationException {
468                    ResultSet tables =null;
469                    
470                    try {
471                            tables = metaData.getTables(null, null, setCase(metaData,table), null);
472                            if(!tables.next()) throw new ApplicationException("there is no table that match the following pattern ["+table+"]");
473                    }
474                    finally {
475                            if(tables!=null) tables.close();
476                    }
477            }
478    
479            private String setCase(DatabaseMetaData metaData, String id) throws SQLException {
480                    if(id==null) return null;
481                    
482                    if(metaData.storesLowerCaseIdentifiers()) return id.toLowerCase();
483                    if(metaData.storesUpperCaseIdentifiers()) return id.toUpperCase();
484                    return id;
485            }
486    
487            private void typeIndex(DatabaseMetaData metaData) throws PageException, SQLException {
488                    required("table",table);
489                    
490                    Stopwatch stopwatch=new Stopwatch();
491                    stopwatch.start();
492            
493                    table=setCase(metaData, table);
494            int index=table.indexOf('.');
495                    String schema=null;
496            if(index>0) {
497                            schema=table.substring(0,index);
498                            table=table.substring(index+1);
499                    }
500                    
501                    checkTable(metaData);
502                    
503            ResultSet tables = metaData.getIndexInfo(dbname, schema, table, false, true);
504            railo.runtime.type.Query qry = new QueryImpl(tables,"query");
505            
506            // type int 2 string
507            int rows = qry.getRecordcount();
508            String strType;
509            int type,card;
510            for(int row=1;row<=rows;row++){
511                    
512                    // type
513                    switch(type=Caster.toIntValue(qry.getAt(KeyImpl.TYPE,row))){
514                    case 0:
515                            strType="Table Statistic";
516                    break;
517                    case 1:
518                            strType="Clustered Index";
519                    break;
520                    case 2:
521                            strType="Hashed Index";
522                    break;
523                    case 3:
524                            strType="Other Index";
525                    break;
526                    default:
527                            strType=Caster.toString(type);
528                    }
529                    qry.setAt(KeyImpl.TYPE, row, strType);
530                    
531                    // CARDINALITY
532                    card=Caster.toIntValue(qry.getAt(CARDINALITY,row),0);
533                    qry.setAt(CARDINALITY, row, Caster.toDouble(card));
534                    
535            }
536            qry.setExecutionTime(stopwatch.time());
537            
538            
539                    pageContext.setVariable(name, qry);
540            }
541    
542            private void typeProcedures(DatabaseMetaData metaData) throws SQLException, PageException {
543                    Stopwatch stopwatch=new Stopwatch();
544                    stopwatch.start();
545            
546                    String schema=null;
547                    pattern=setCase(metaData, pattern);
548                    if(StringUtil.isEmpty(pattern,true)) {
549                            pattern=null;
550                    }
551                    
552            ResultSet tables = metaData.getProcedures(dbname, schema, pattern);
553            railo.runtime.type.Query qry = new QueryImpl(tables,"query");
554            qry.setExecutionTime(stopwatch.time());
555            
556            
557                    pageContext.setVariable(name, qry);
558            }
559            
560            private void typeProcedureColumns(DatabaseMetaData metaData) throws SQLException, PageException {
561                    required("procedure",procedure);
562                    
563                    Stopwatch stopwatch=new Stopwatch();
564                    stopwatch.start();
565                    
566                    procedure=setCase(metaData, procedure);         
567                    pattern=setCase(metaData, pattern);
568                    if(StringUtil.isEmpty(pattern,true)) pattern=null;
569                    String schema=null;
570                    int index=procedure.indexOf('.');
571                    if(index>0) {
572                            schema=procedure.substring(0,index);
573                            procedure=procedure.substring(index+1);
574                    }
575                    
576                    
577                    ResultSet tables = metaData.getProcedureColumns(dbname, schema, procedure, pattern);
578                    
579                    railo.runtime.type.Query qry = new QueryImpl(tables,"query");
580            qry.setExecutionTime(stopwatch.time());
581            
582            
583                    pageContext.setVariable(name, qry);
584            }
585    
586            private void typeTerms(DatabaseMetaData metaData) throws SQLException, PageException {
587                    Struct sct=new StructImpl();
588                    sct.setEL(PROCEDURE, metaData.getProcedureTerm());
589                    sct.setEL(CATALOG, metaData.getCatalogTerm());
590                    sct.setEL(SCHEMA, metaData.getSchemaTerm());
591                    
592                    pageContext.setVariable(name, sct);
593            }
594    
595            private void typeTables(DatabaseMetaData metaData) throws PageException, SQLException {
596    
597                    
598                    
599                    Stopwatch stopwatch=new Stopwatch();
600                    stopwatch.start();
601            
602                    pattern=setCase(metaData, pattern);
603                    
604            ResultSet tables = metaData.getTables(dbname, null, pattern, null);
605            railo.runtime.type.Query qry = new QueryImpl(tables,"query");
606            
607            qry.setExecutionTime(stopwatch.time());
608            
609            
610                    pageContext.setVariable(name, qry);
611            }
612    
613            private void typeVersion(DatabaseMetaData metaData) throws PageException, SQLException {
614    
615                    Stopwatch stopwatch=new Stopwatch();
616                    stopwatch.start();
617                    
618                    Key[] columns=new Key[]{DATABASE_PRODUCTNAME,DATABASE_VERSION,DRIVER_NAME,DRIVER_VERSION,JDBC_MAJOR_VERSION,JDBC_MINOR_VERSION};
619                    String[] types=new String[]{"VARCHAR","VARCHAR","VARCHAR","VARCHAR","DOUBLE","DOUBLE"};
620                    
621                    railo.runtime.type.Query qry=new QueryImpl(columns,types,1,"query");
622    
623                    qry.setAt(DATABASE_PRODUCTNAME,1,metaData.getDatabaseProductName());
624                    qry.setAt(DATABASE_VERSION,1,metaData.getDatabaseProductVersion());
625                    qry.setAt(DRIVER_NAME,1,metaData.getDriverName());
626                    qry.setAt(DRIVER_VERSION,1,metaData.getDriverVersion());
627                    qry.setAt(JDBC_MAJOR_VERSION,1,new Double(metaData.getJDBCMajorVersion()));
628                    qry.setAt(JDBC_MINOR_VERSION,1,new Double(metaData.getJDBCMinorVersion()));
629                    
630                    
631            qry.setExecutionTime(stopwatch.time());
632            
633            
634                    pageContext.setVariable(name, qry);
635            }
636            
637            private void typeUsers(DatabaseMetaData metaData) throws PageException, SQLException {
638                    
639                    Stopwatch stopwatch=new Stopwatch();
640                    stopwatch.start();
641            
642                    checkTable(metaData);
643                    ResultSet result = metaData.getSchemas();
644                    QueryPro qry = new QueryImpl(result,"query");
645                    
646                    
647                    qry.rename(TABLE_SCHEM,USER);
648            
649            qry.setExecutionTime(stopwatch.time());
650            
651            
652                    pageContext.setVariable(name, qry);
653            }
654    
655            private void required(String name, String value) throws ApplicationException {
656                    if(value==null)
657                            throw new ApplicationException("Missing attribute ["+name+"]. The type ["+strType+"] requires the attribute [" + name + "].");
658            }
659    
660            private static  boolean matchPattern(String value, Pattern pattern) {
661                    if(pattern==null) return true;
662                    return SQLUtil.match(pattern, value);
663            }
664    
665            /**
666            * @see javax.servlet.jsp.tagext.Tag#doEndTag()
667            */
668            public int doEndTag()   {
669                    return EVAL_PAGE;
670            }
671            
672    
673            public static String getDatasource(PageContext pageContext, String datasource) throws ApplicationException {
674                    if(StringUtil.isEmpty(datasource)){
675                            datasource=((ApplicationContextPro)pageContext.getApplicationContext()).getDefaultDataSource();
676    
677                            if(StringUtil.isEmpty(datasource))
678                                    throw new ApplicationException(
679                                                    "attribute [datasource] is required, when no default datasource is defined",
680                                                    "you can define a default datasource as attribute [defaultdatasource] of the tag cfapplication or as data member of the application.cfc (this.defaultdatasource=\"mydatasource\";)");
681                    }
682                    return datasource;
683            }
684    }