Commit 1f74f67f authored by Clayton Donley's avatar Clayton Donley
Browse files

Quoted dn's now work

fixed dn and comma issues with SELECT, UPDATE and DELETE
by adding EXP_ROWS=true in the connection string, row expansion can be used for retrieving results in addition to column expansion and concatination
parent b0445ede
......@@ -37,6 +37,7 @@ public class Delete {
StringBuffer buf = new StringBuffer();
SqlStore store = del.getSqlStore();
int count = 0;
//System.out.println("from : " + store.getFrom());
if (store.getSimple()) {
try {
con.destroySubcontext(store.getFrom());
......
......@@ -197,4 +197,4 @@ public class FieldStore {
}
}
}
\ No newline at end of file
......@@ -33,6 +33,13 @@ import com.octetstring.jdbcLdap.sql.statements.JdbcLdapSql;
*@author Marc Boorshtein, OctetString
*/
public class JndiLdapConnection implements java.sql.Connection {
public final static String LDAP_COMMA = "\\,";
public final static String LDAP_EQUALS = "\\=";
public final static String LDAP_PLUS = "\\+";
public final static String LDAP_LESS = "\\<";
public final static String LDAP_GREATER = "\\>";
public final static String LDAP_SEMI_COLON = "\\;";
/** Object scope */
public static final String OBJECT_SCOPE = "objectScope";
......@@ -46,6 +53,10 @@ public class JndiLdapConnection implements java.sql.Connection {
* [val1][val2][val3]. Must be true or false */
public static final String CONCAT_ATTS = "CONCAT_ATTS";
/** Determines if multiple value attributes will cause rows to be expanded for each value of the attribute */
public static final String EXP_ROWS = "EXP_ROWS";
/** Determines what type of authentication will be used, none, simple, sasl */
public static final String AUTHENTICATION_TYPE = javax.naming.Context.SECURITY_AUTHENTICATION;
......@@ -64,6 +75,9 @@ public class JndiLdapConnection implements java.sql.Connection {
/** The JNDI factory for connecting */
public static final String JNDI_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";
/** The JNDI DSML factory*/
public static final String JNDI_DSML_FACTORY = "com.sun.jndi.dsml.DsmlCtxFactory";
/** user property */
static final String USER = "user";
......@@ -88,6 +102,9 @@ public class JndiLdapConnection implements java.sql.Connection {
/** Determinies if statements are cached */
boolean cacheStatements;
/** Determines if rows are expanded */
boolean expandRow;
/** The default search scope */
String scope;
......@@ -100,11 +117,17 @@ public class JndiLdapConnection implements java.sql.Connection {
/** Determines if attributes are concattintated */
boolean concatAtts;
/** temporary string buffer */
StringBuffer tmpBuff;
/*
*Public methods not part of java.sql.Connection
*/
/**
Caches a statement
@param statement The statement to cache
......@@ -178,7 +201,7 @@ public class JndiLdapConnection implements java.sql.Connection {
env = new Hashtable();
this.concatAtts = false;
boolean authFound = false;
this.tmpBuff = new StringBuffer();
Enumeration en = props.propertyNames();
// System.out.println("JndiLdapConnection.<init>: url="+url);
......@@ -187,6 +210,7 @@ public class JndiLdapConnection implements java.sql.Connection {
String prop;
String user=null, pass=null ;
env.put(Context.INITIAL_CONTEXT_FACTORY,JNDI_FACTORY);
//env.put(Context.INITIAL_CONTEXT_FACTORY,JNDI_DSML_FACTORY);
env.put(Context.PROVIDER_URL,url.substring(ELIM_JDBC));
while (en.hasMoreElements()) {
......@@ -201,6 +225,9 @@ public class JndiLdapConnection implements java.sql.Connection {
else if (prop.equalsIgnoreCase(CACHE_STATEMENTS)) {
cacheStatements = props.getProperty(prop).equalsIgnoreCase("true");
}
else if (prop.equalsIgnoreCase(EXP_ROWS)) {
this.expandRow = props.getProperty(prop).equalsIgnoreCase("true");
}
else if (prop.equalsIgnoreCase(SEARCH_SCOPE)) {
scope = props.getProperty(prop);
}
......@@ -241,7 +268,7 @@ public class JndiLdapConnection implements java.sql.Connection {
try {
con = new InitialDirContext(env);
// System.out.println("JndiLdapConnection.<init>: called InitialDirContext");
//System.out.println("JndiLdapConnection.<init>: called InitialDirContext");
}
......@@ -281,10 +308,10 @@ public class JndiLdapConnection implements java.sql.Connection {
public boolean isClosed() throws java.sql.SQLException {
try {
return con == null || con.lookup(baseDN) == null;
return con == null || con.lookup("") == null;
}
catch (NamingException e) {
e.printStackTrace(System.out);
//e.printStackTrace(System.out);
return false;
}
......@@ -292,6 +319,34 @@ public class JndiLdapConnection implements java.sql.Connection {
}
/**
* escaping the following characters per rfc2253 -- "," / "=" / "+" / "<" / ">" / "#" / ";"
* @param a variable passed in
* @return a cleaned LDAP parameter
*/
public String ldapClean(String val) {
char c;
for (int i=0,m= val.length(); i<m; i++) {
c = val.charAt(i);
switch (c) {
case ',':
case '=':
case '+':
case '<':
case '>':
case '#':
case ';': this.tmpBuff.setLength(0);
tmpBuff .append('"').append(val).append('"');
return tmpBuff.toString();
}
}
return val;
}
public void setCatalog(java.lang.String str) throws java.sql.SQLException {
}
......@@ -419,4 +474,32 @@ public class JndiLdapConnection implements java.sql.Connection {
throw new SQLException("LDAP Does Not Support Transactions");
}
/**
* @return trie if expanding rows
*/
public boolean isExpandRow() {
return expandRow;
}
/**
* @param b sets if expanding rows
*/
public void setExpandRow(boolean b) {
expandRow = b;
}
/**
* @return
*/
public String getScope() {
return scope;
}
/**
* @param string
*/
public void setScope(String string) {
scope = string;
}
}
......@@ -24,6 +24,7 @@ import javax.naming.*;
import javax.naming.directory.*;
import com.octetstring.jdbcLdap.sql.statements.*;
import java.sql.*;
import java.util.*;
/**
*Retrieves the results from a qeury
*@author Marc Boorshtein, OctetString
......@@ -40,7 +41,27 @@ public class RetrieveResults {
SearchControls ctls = new SearchControls();
int num;
ctls.setReturningAttributes(select.getSearchAttributes().length != 0 ? select.getSearchAttributes() : null);
//System.out.println("select.getSearchAttributes().length : " + select.getSearchAttributes().length);
String[] fields = select.getSearchAttributes();
fields = fields != null ? fields : new String[0];
ArrayList ar = new ArrayList();
for (int i=0, m=fields.length;i<m;i++) {
if (! fields[i].equalsIgnoreCase("dn")) {
ar.add(fields[i]);
}
}
String[] searchAttribs = new String[ar.size()];
System.arraycopy(ar.toArray(),0,searchAttribs,0,ar.size());
ctls.setReturningAttributes(searchAttribs.length != 0 ? searchAttribs : null);
ctls.setSearchScope(select.getSearchScope());
num = select.getMaxRecords();
......
......@@ -32,197 +32,251 @@ import java.sql.*;
*@author Marc Boorshtein, OctetString
*/
public class UnpackResults {
/** DN attribute name */
static final String DN_ATT = "DN";
/** The Connection to the LDAP server */
JndiLdapConnection con;
/** List of Field Names */
HashMap names;
/** List of rows */
LinkedList rows;
/** Creates new UnpackResults */
public UnpackResults(JndiLdapConnection con) {
this.con = con;
names = new HashMap();
rows = new LinkedList();
}
/** Returns the field names of the result */
public LinkedList getFieldNames() {
LinkedList fields = new LinkedList();
Iterator it = names.keySet().iterator();
FieldStore f;
int i;
StringBuffer buf = new StringBuffer();
while (it.hasNext()) {
f = (FieldStore) names.get(it.next());
if (f.numVals > 0) {
for (i=0;i<f.numVals;i++) {
buf.setLength(0);
fields.add(buf.append(f.name).append('_').append(i).toString());
}
}
else {
fields.add(f.name);
}
}
return fields;
}
/** Returns the types for the query */
public int[] getFieldTypes() {
LinkedList fields = new LinkedList();
Iterator it = names.keySet().iterator();
FieldStore f;
int i;
StringBuffer buf = new StringBuffer();
int count=0;
while (it.hasNext()) {
f = (FieldStore) names.get(it.next());
if (f.numVals > 0) {
for (i=0;i<f.numVals;i++) {
buf.setLength(0);
fields.add(new Integer(f.getType()));
count++;
}
}
else {
fields.add(new Integer(f.getType()));
count++;
}
}
int[] types = new int[count];
for (i=0;i<count;i++) {
types[i] = ((Integer) fields.get(i)).intValue();
}
return types;
}
/** Returns the results of the search */
public LinkedList getRows() {
return rows;
}
public void unpack(NamingEnumeration results,boolean dn,String fromContext, String baseContext) throws SQLException {
try {
SearchResult res;
Attributes atts;
NamingEnumeration enumAtts;
Enumeration vals;
Attribute att;
String attrid;
String val;
//String dn;
FieldStore field;
StringBuffer buff = new StringBuffer();
String base;
names.clear();
rows.clear();
int currNumVals;
HashMap row;
buff.setLength(0);
if (fromContext != null && fromContext.length() != 0) buff.append(',').append(fromContext);
if (baseContext != null && baseContext.length() != 0) buff.append(',').append(baseContext);
base = buff.toString();
while (results.hasMore()) {
res = (SearchResult) results.next();
row = new HashMap();
atts = (Attributes) res.getAttributes();
enumAtts = atts.getAll();
if (dn) {
field = (FieldStore) names.get(DN_ATT);
if (field == null) {
field = new FieldStore();
field.name = DN_ATT;
names.put(field.name,field);
}
buff.setLength(0);
buff.append(res.getName()).append(base);
// System.out.println("Unpack: dn="+buff);
row.put(DN_ATT,buff.toString());
}
while (enumAtts.hasMore()) {
att = (Attribute) enumAtts.next();
attrid = att.getID();
// System.out.println("Unpack: att="+att+", attrid="+attrid);
field = (FieldStore) names.get(attrid);
if (field == null) {
field = new FieldStore();
field.name = attrid;
names.put(field.name,field);
}
if (att.size() > 1) {
if (con.getConcatAtts()) {
buff.setLength(0);
field.numVals = 0;
for (vals = att.getAll();vals.hasMoreElements();) {
val = vals.nextElement().toString();
field.determineType(val);
buff.append('[').append(val).append(']');
}
row.put(field.name,buff.toString());
}
else {
currNumVals = 0;
for (vals = att.getAll();vals.hasMoreElements();) {
buff.setLength(0);
val = vals.nextElement().toString();
field.determineType(val);
row.put(buff.append(field.name).append('_').append(currNumVals).toString(),val);
currNumVals++;
}
field.numVals = (currNumVals > field.numVals) ? currNumVals : field.numVals;
}
}
else {
val = att.get(0).toString();
field.determineType(val);
row.put(field.name,val);
}
}
enumAtts.close();
rows.add(row);
}
results.close();
}
catch (NamingException e) {
throw new SQLNamingException(e);
}
}
}
/** DN attribute name */
static final String DN_ATT = "DN";
/** The Connection to the LDAP server */
JndiLdapConnection con;
/** List of Field Names */
HashMap names;
/** List of rows */
LinkedList rows;
/** Creates new UnpackResults */
public UnpackResults(JndiLdapConnection con) {
this.con = con;
names = new HashMap();
rows = new LinkedList();
}
/** Returns the field names of the result */
public LinkedList getFieldNames() {
LinkedList fields = new LinkedList();
Iterator it = names.keySet().iterator();
FieldStore f;
int i;
StringBuffer buf = new StringBuffer();
while (it.hasNext()) {
f = (FieldStore) names.get(it.next());
if (f.numVals > 0) {
for (i = 0; i < f.numVals; i++) {
buf.setLength(0);
fields.add(
buf.append(f.name).append('_').append(i).toString());
}
} else {
fields.add(f.name);
}
}
return fields;
}
/** Returns the types for the query */
public int[] getFieldTypes() {
LinkedList fields = new LinkedList();
Iterator it = names.keySet().iterator();
FieldStore f;
int i;
StringBuffer buf = new StringBuffer();
int count = 0;
while (it.hasNext()) {
f = (FieldStore) names.get(it.next());
if (f.numVals > 0) {
for (i = 0; i < f.numVals; i++) {
buf.setLength(0);
fields.add(new Integer(f.getType()));
count++;
}
} else {
fields.add(new Integer(f.getType()));
count++;
}
}
int[] types = new int[count];
for (i = 0; i < count; i++) {
types[i] = ((Integer) fields.get(i)).intValue();
}
return types;
}
/** Returns the results of the search */
public LinkedList getRows() {
return rows;
}
public void unpack(
NamingEnumeration results,
boolean dn,
String fromContext,
String baseContext)
throws SQLException {
try {
LinkedList tmprows;
LinkedList expRows = null;
SearchResult res;
Attributes atts;
NamingEnumeration enumAtts;
Enumeration vals;
Attribute att;
String attrid;
String val;
//String dn;
FieldStore field;
StringBuffer buff = new StringBuffer();
String base;
names.clear();
rows.clear();
int currNumVals;
HashMap row;
Iterator it;
buff.setLength(0);
if (fromContext != null && fromContext.length() != 0)
buff.append(',').append(fromContext);
if (baseContext != null && baseContext.length() != 0)
buff.append(',').append(baseContext);
base = buff.toString();
while (results.hasMore()) {
res = (SearchResult) results.next();
row = new HashMap();
if (con.isExpandRow()) {
expRows = new LinkedList();
expRows.add(row);
}
atts = (Attributes) res.getAttributes();
enumAtts = atts.getAll();
if (dn) {
field = (FieldStore) names.get(DN_ATT);
if (field == null) {
field = new FieldStore();
field.name = DN_ATT;
names.put(field.name, field);
}
buff.setLength(0);
buff.append(res.getName()).append(base);
if (buff.charAt(0) == ',')
buff.deleteCharAt(0);
// System.out.println("Unpack: dn="+buff);
row.put(DN_ATT, buff.toString());
}
while (enumAtts.hasMore()) {
att = (Attribute) enumAtts.next();
if (att.size() == 0) continue;
attrid = att.getID();
// System.out.println("Unpack: att="+att+", attrid="+attrid);
field = (FieldStore) names.get(attrid);
if (field == null) {
field = new FieldStore();
field.name = attrid;
names.put(field.name, field);
}
if (att.size() > 1) {
if (con.getConcatAtts()) {
buff.setLength(0);
field.numVals = 0;
for (vals = att.getAll();
vals.hasMoreElements();
) {
val = vals.nextElement().toString();
field.determineType(val);
buff.append('[').append(val).append(']');
}
row.put(field.name, buff.toString());
}
else if (con.isExpandRow()){
tmprows =new LinkedList();