001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.runtime.exp; 020 021import java.sql.DatabaseMetaData; 022import java.sql.SQLException; 023import java.util.ArrayList; 024import java.util.List; 025 026import lucee.commons.lang.ExceptionUtil; 027import lucee.commons.lang.StringUtil; 028import lucee.runtime.PageContext; 029import lucee.runtime.config.Config; 030import lucee.runtime.db.DataSource; 031import lucee.runtime.db.DatasourceConnection; 032import lucee.runtime.db.SQL; 033import lucee.runtime.listener.ApplicationContextPro; 034import lucee.runtime.op.Caster; 035import lucee.runtime.type.KeyImpl; 036import lucee.runtime.type.util.KeyConstants; 037 038 039/** 040 * Database Exception Object 041 */ 042 043 044 045public final class DatabaseException extends PageExceptionImpl { 046 047 private SQL sql; 048 private String sqlstate=""; 049 private int errorcode=-1; 050 private DataSource datasource; 051 052 public DatabaseException(SQLException sqle,DatasourceConnection dc) { 053 super( 054 sqle.getCause() instanceof SQLException? 055 (sqle=(SQLException)sqle.getCause()).getMessage(): 056 sqle.getMessage(),"database"); 057 058 set(sqle); 059 set(dc); 060 } 061 062 public DatabaseException(String message,String detail,SQL sql,DatasourceConnection dc) { 063 super(message,"database"); 064 065 set(sql); 066 set(null,detail); 067 set(dc); 068 } 069 070 /** 071 * Constructor of the class 072 * @param message error message 073 * @param detail detailed error message 074 * @param sqle 075 * @param sql 076 * @param dc 077 */ 078 private DatabaseException(String message, String detail, SQLException sqle, SQL sql,DatasourceConnection dc) { 079 super(sqle.getCause() instanceof SQLException?message:"","database"); 080 081 set(sql); 082 set(sqle,detail); 083 set(sqle); 084 set(dc); 085 } 086 087 private void set(SQL sql) { 088 this.sql=sql; 089 if(sql!=null) { 090 setAdditional(KeyConstants._SQL,sql.toString()); 091 } 092 } 093 094 private void set(SQLException sqle,String detail) { 095 String sqleMessage=sqle!=null?sqle.getMessage():""; 096 if(detail!=null){ 097 if(!StringUtil.isEmpty(sqleMessage)) 098 setDetail(detail+"\n"+sqleMessage); 099 else 100 setDetail(detail); 101 } 102 else { 103 if(!StringUtil.isEmpty(sqleMessage)) 104 setDetail(sqleMessage); 105 } 106 } 107 108 private void set(SQLException sqle) { 109 if(sqle!=null) { 110 sqlstate=sqle.getSQLState(); 111 errorcode=sqle.getErrorCode(); 112 113 this.setStackTrace(sqle.getStackTrace()); 114 } 115 } 116 117 private void set(DatasourceConnection dc) { 118 if(dc!=null) { 119 datasource=dc.getDatasource(); 120 try { 121 DatabaseMetaData md = dc.getConnection().getMetaData(); 122 md.getDatabaseProductName(); 123 setAdditional(KeyImpl.init("DatabaseName"),md.getDatabaseProductName()); 124 setAdditional(KeyImpl.init("DatabaseVersion"),md.getDatabaseProductVersion()); 125 setAdditional(KeyImpl.init("DriverName"),md.getDriverName()); 126 setAdditional(KeyImpl.init("DriverVersion"),md.getDriverVersion()); 127 //setAdditional("url",md.getURL()); 128 129 setAdditional(KeyConstants._Datasource,dc.getDatasource().getName()); 130 131 132 } 133 catch (SQLException e) {} 134 } 135 } 136 137 /** 138 * Constructor of the class 139 * @param message 140 * @param sqle 141 * @param sql 142 143 public DatabaseException(String message, SQLException sqle, SQL sql,DatasourceConnection dc) { 144 this(message,null,sqle,sql,dc); 145 } */ 146 147 148 /** 149 * Constructor of the class 150 * @param sqle 151 * @param sql 152 */ 153 public DatabaseException(SQLException sqle, SQL sql,DatasourceConnection dc) { 154 this(sqle!=null?sqle.getMessage():null,null,sqle,sql,dc); 155 } 156 157 /** 158 * Constructor of the class 159 * @param sqle 160 */ 161 162 163 @Override 164 public CatchBlock getCatchBlock(Config config) { 165 String strSQL=sql==null?"":sql.toString(); 166 if(StringUtil.isEmpty(strSQL))strSQL=Caster.toString(getAdditional().get("SQL", ""),""); 167 168 String datasourceName=datasource==null?"":datasource.getName(); 169 if(StringUtil.isEmpty(datasourceName))datasourceName=Caster.toString(getAdditional().get("DataSource", ""),""); 170 171 CatchBlock sct = super.getCatchBlock(config); 172 sct.setEL("NativeErrorCode",new Double(errorcode)); 173 sct.setEL("DataSource",datasourceName); 174 sct.setEL("SQLState",sqlstate); 175 sct.setEL("Sql",strSQL); 176 sct.setEL("queryError",strSQL); 177 sct.setEL("where",""); 178 return sct; 179 } 180 181 public static DatabaseException notFoundException(PageContext pc, String datasource) { 182 183 184 List<String> list=new ArrayList<String>(); 185 186 // application based datasources 187 DataSource[] datasources = ((ApplicationContextPro)pc.getApplicationContext()).getDataSources(); 188 if(datasources!=null)for(int i=0;i<datasources.length;i++){ 189 list.add(datasources[i].getName()); 190 } 191 192 // config based datasources 193 datasources=pc.getConfig().getDataSources(); 194 if(datasources!=null)for(int i=0;i<datasources.length;i++){ 195 list.add(datasources[i].getName()); 196 } 197 198 // create error detail 199 DatabaseException de = new DatabaseException("datasource ["+datasource+"] doesn't exist",null,null,null); 200 de.setDetail(ExceptionUtil.createSoundexDetail(datasource,list.iterator(),"datasource names")); 201 de.setAdditional(KeyConstants._Datasource,datasource); 202 return de; 203 } 204 205 private static ApplicationContextPro getApplicationContext() { 206 // TODO Auto-generated method stub 207 return null; 208 } 209}