/**
* ESUP-Portail Helpdesk - Copyright (c) 2004-2009 ESUP-Portail consortium.
*/
package org.esupportail.helpdesk.domain.departmentSelection.conditions;
import java.net.InetAddress;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import org.esupportail.helpdesk.domain.DomainService;
import org.esupportail.helpdesk.domain.beans.User;
import org.esupportail.helpdesk.domain.departmentSelection.DepartmentSelectionCompileError;
/**
* A condition that is matched according to SQL query.
*/
public class ExternalDbCondition extends AbstractFinalCondition {
/**
* Parameter used in query.
*/
private enum ParamType {
/**
* Username.
*/
USER,
/**
* IP address.
*/
IP,
/**
* Computer hostname.
*/
HOSTNAME;
/**
* @return Parameter form used in query.
*/
@Override
public String toString() {
switch (this) {
case USER:
return "%USER%";
case HOSTNAME:
return "%HOSTNAME%";
case IP:
return "%IP%";
}
return null;
}
/**
* Returns first parameter found in string.
*
* @param str the string to find in
* @return the found parameter; null on not found
*/
static ParamType getFirstParam(final String str) {
int userPos = str.indexOf(USER.toString());
int hostnamePos = str.indexOf(HOSTNAME.toString());
int ipPos = str.indexOf(IP.toString());
userPos = userPos < 0 ? Integer.MAX_VALUE : userPos;
hostnamePos = hostnamePos < 0 ? Integer.MAX_VALUE : hostnamePos;
ipPos = ipPos < 0 ? Integer.MAX_VALUE : ipPos;
if ((userPos < hostnamePos) && (userPos < ipPos)) {
return USER;
}
if ((hostnamePos < userPos) && (hostnamePos < ipPos)) {
return HOSTNAME;
}
if ((ipPos < hostnamePos) && (ipPos < userPos)) {
return IP;
}
return null;
}
}
/**
* The serialization id.
*/
private static final long serialVersionUID = -2868435305144749927L;
/**
* The JNDI context to connect to.
*/
private String ctx;
/**
* The JNDI source to connect to.
*/
private String jndi;
/**
* The raw SQL query.
*/
private String sql;
/**
* The SQL query with replaced parameters.
*/
private String sqlInternal;
/**
* Parameters list of the query.
*/
private List<ParamType> params;
/**
* The data source fetched via JNDI.
*/
private DataSource dataSource;
/**
* Get the JNDI context.
*
* @return the context; null for default
*/
public String getCtx() {
return ctx;
}
/**
* Set the JNDI context.
*
* @param ctx the context; null for default
*/
public void setCtx(final String ctx) {
this.ctx = ctx;
}
/**
* Get the name of JNDI source.
*
* @return the name of JNDI source
*/
public String getJndi() {
return jndi;
}
/**
* Set the name of JNDI source.
*
* @param jndi the name of JNDI source
*/
public void setJndi(final String jndi) {
this.jndi = jndi;
}
/**
* Get the SQL query.
*
* @return the SQL query
*/
public String getSql() {
return sql;
}
/**
* Set the SQL query and translate it to form suitable for PreparedStatement
*
* @param sql the SQL query
*/
public void setSql(final String sql) {
this.sql = sql;
this.sqlInternal = sql;
this.params = new ArrayList<ParamType>();
ParamType paramType;
while ((paramType = ParamType.getFirstParam(sqlInternal)) != null) {
params.add(paramType);
sqlInternal = sqlInternal.replaceFirst(paramType.toString(), "?");
}
}
/**
* Get the connection to database from JNDI
*
* @return the connection
* @throws NamingException on JNDI context or JNDI source not found
* @throws SQLException on DB connection failure
*/
private Connection getConnection() throws NamingException, SQLException {
if (dataSource == null) {
Context ic = new InitialContext();
Context context = (Context) ic.lookup(ctx == null ? "java:comp/env"
: ctx);
dataSource = (DataSource) context.lookup(jndi);
}
return dataSource.getConnection();
}
/**
* @see org.esupportail.helpdesk.domain.departmentSelection.conditions.AbstractCondition
* #isMatchedInternal(org.esupportail.helpdesk.domain.DomainService,
* org.esupportail.helpdesk.domain.beans.User, java.net.InetAddress)
*/
@Override
protected boolean isMatchedInternal(
@SuppressWarnings("unused") final DomainService domainService,
final User user, final InetAddress client) {
boolean isMatched = false;
PreparedStatement stmt = null;
Connection connection = null;
try {
connection = getConnection();
stmt = connection.prepareStatement(sqlInternal);
int paramIndex = 0;
for (ParamType paramType : params) {
paramIndex++;
switch (paramType) {
case USER:
stmt.setString(paramIndex, user.getRealId());
break;
case HOSTNAME:
stmt.setString(paramIndex, client.getHostName());
break;
case IP:
stmt.setString(paramIndex, client.getHostAddress());
break;
}
}
ResultSet rs = stmt.executeQuery();
if (rs.next() && (rs.getInt(1) > 0)) {
isMatched = true;
}
} catch (Exception ex) {
isMatched = false;
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException ex) {
//nothing to close
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException ex) {
//nothing to close
}
}
return isMatched;
}
/**
* @see org.esupportail.helpdesk.domain.departmentSelection.conditions.AbstractCondition#checkInternal()
*/
@Override
protected void checkInternal() throws DepartmentSelectionCompileError {
if (getJndi() == null) {
throw new DepartmentSelectionCompileError(
"<external-db> tags should have 'jndi' attributes");
}
if (getSql() == null) {
throw new DepartmentSelectionCompileError(
"<external-db> tags should have 'sql' attributes");
}
}
/**
* @see org.esupportail.helpdesk.domain.departmentSelection.conditions.Condition#getNodeType()
*/
@Override
public String getNodeType() {
return "externalDb";
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
String str = "<external-db";
if (getCtx() != null) {
str += " ctx=\"" + getCtx() + "\"";
}
str += " jndi=\"" + getJndi() + "\" sql=\"" + getSql() + "\" />";
return str;
}
}