/* * Copyright (C) 2000 - 2008 TagServlet Ltd * * This file is part of Open BlueDragon (OpenBD) CFML Server Engine. * * OpenBD is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * Free Software Foundation,version 3. * * OpenBD is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenBD. If not, see http://www.gnu.org/licenses/ * * Additional permission under GNU GPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or combining * it with any of the JARS listed in the README.txt (or a modified version of * (that library), containing parts covered by the terms of that JAR, the * licensors of this Program grant you additional permission to convey the * resulting work. * README.txt @ http://www.openbluedragon.org/license/README.txt * * http://www.openbluedragon.org/ */ package com.naryx.tagfusion.cfm.tag.net; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Map; import com.nary.util.FastMap; import com.naryx.tagfusion.cfm.engine.cfBinaryData; import com.naryx.tagfusion.cfm.engine.cfEngine; import com.naryx.tagfusion.cfm.engine.cfQueryResultData; import com.naryx.tagfusion.cfm.engine.cfSession; import com.naryx.tagfusion.cfm.engine.cfStringData; import com.naryx.tagfusion.cfm.engine.cfmRunTimeException; /** * cfldapQueryData is the query object returned by cfLDAP when an * LDAP query is made. */ public class cfldapQueryData { /** * TODO: this is a bit of a mess because "_results" is passed in as type List<Map<String, String>>, but * gets converted to type List<Map<String, cfData>> before being passed to queryResults.populateQuery(). * Therefore, it's going to take a bit of work to get rid of the raw List types and replace them with * parameterized types. */ public cfldapQueryData( cfSession _Session, String _name, List /* List<Map<String, String> */ _results, String [] _attributes, String _sort, String _sortControl, int _startRow, int _maxRows, List<String> _returnAsBinary ) throws cfmRunTimeException{ List /* List<Map<String, cfData> */ data = _results; String [] columnList; // note ordering differs depending on if attributes=* if ( _attributes.length == 1 && _attributes[0].equals("*") ){ // get name-value pairs data = sortResults( data, _sort, _sortControl ); data = adjustToStartRow( data, _startRow ); data = convertToNameValuePairs( data ); data = removeExcessRows( data, _maxRows ); columnList = new String [] {"name","value"}; }else{ data = removeExcessRows( data, _maxRows ); data = sortResults( data, _sort, _sortControl ); data = adjustToStartRow( data, _startRow ); data = convertResultsForQuery( data, _attributes, _returnAsBinary ); columnList = _attributes; } cfQueryResultData queryResult = new cfQueryResultData( columnList, "CFLDAP" ); //printResults( data ); // testing queryResult.populateQuery( data ); _Session.setData( _name, queryResult ); }// cfldapQueryData() private static List adjustToStartRow( List _data, int _startRow ){ for ( int i = 1; i < _startRow ; i++ ){ _data.remove( 0 ); } return _data; }// adjustToStartRow() private List sortResults( List _data, String _sort, String _sortControl ){ if ( !_sort.equals("") ){ String [] control = com.nary.util.string.convertToList( _sortControl.toLowerCase(), ',' ); boolean caseSensitive = true; boolean ascending = true; for (int i = 0; i < control.length; i++ ){ if ( control[i].equals( "asc" )){ ascending = true; }else if ( control[i].equals( "desc" )){ ascending = false; }else if ( control[i].equals( "nocase" )){ caseSensitive = false; } } String [] sortOnAttributes = com.nary.util.string.convertToList( _sort.toLowerCase(), ',' ); Collections.sort( _data, new entryComparator( sortOnAttributes, caseSensitive, ascending ) ); } return _data; }// sortResults() private static List convertToNameValuePairs( List _data){ List newData = new ArrayList(); int dataLength = _data.size(); // for each entry for ( int i = 0; i < dataLength; i++ ){ Map entry = (Map)_data.get(i); // get all the attributes (key-value pairs) putting them into a vector of hashtables of name-value pairs Iterator keys = entry.keySet().iterator(); Object nextEntry; while ( keys.hasNext() ){ String name = keys.next().toString(); FastMap singleEntry = new FastMap(2); singleEntry.put( "name", new cfStringData(name) ); nextEntry = entry.get(name); if ( nextEntry.getClass().isArray() && nextEntry.getClass().getComponentType().equals( byte.class ) ){ singleEntry.put( "value", new cfStringData( new String( (byte[]) nextEntry ) ) ); }else{ singleEntry.put( "value", new cfStringData( (String) nextEntry ) ); } newData.add( singleEntry ); } } return newData; }// convertToNameValuePairs() private static List removeExcessRows( List _data, int _maxEntries ){ if ( _maxEntries!= 0 && _maxEntries < _data.size() ){ // remove excess entries int no_excess = _data.size() - _maxEntries; for (int i = 0; i < no_excess; i++ ){ _data.remove( _data.get( _data.size()-1 ) ); } } return _data; }// removeExcessEntries // converts all results values from Strings to cfStringDatas and // adds in blank entries where an entry does not have the req'd attributes private static List convertResultsForQuery( List _data, String [] _columnList, List<String> _returnAsBinary ){ boolean [] returnAsBinary = new boolean[ _columnList.length ]; if ( _returnAsBinary != null ){ for ( int i = 0; i < _columnList.length; i++ ){ if ( _returnAsBinary.contains( _columnList[i] ) ){ returnAsBinary[i] = true; } // else default is false } } Iterator iter = _data.iterator(); while (iter.hasNext()){ Map entry = (Map) iter.next(); for ( int i = 0; i < _columnList.length; i++ ){ String key = _columnList[i];//(String)enum2.nextElement(); try{ if ( entry.containsKey( key ) ){ Object nextEntry = entry.get( key ); if ( nextEntry.getClass().isArray() && nextEntry.getClass().getComponentType().equals( byte.class ) ){ if ( returnAsBinary[i] ){ entry.put( key, new cfBinaryData( (byte[]) nextEntry ) ); }else{ entry.put( key, new cfStringData( new String( (byte[]) nextEntry ) ) ); } }else{ if ( returnAsBinary[i] ){ entry.put( key, new cfBinaryData( ( (String) nextEntry ).getBytes() ) ); }else{ entry.put( key, new cfStringData( (String) nextEntry ) ); } } }else{ entry.put( key, new cfStringData( "" ) ); } }catch(Exception e){ cfEngine.log("Exception thrown by " + key + " : " + e.getMessage() ); } } } return _data; }// convertResultsToCFString() /**--- class entryComparator -----------------------------------------**/ public class entryComparator implements Comparator<Map<String, String>>{ String [] attributes; boolean caseSensitive; boolean ascending; public entryComparator( String [] _attributes, boolean _caseSensitive, boolean _asc ){ attributes = _attributes; caseSensitive = _caseSensitive; ascending = _asc; } public int compare( Map<String, String> ht1, Map<String, String> ht2 ) { int compResult = 0; for (int i = 0; i < attributes.length; i++ ){ compResult = compareOnAttribute( attributes[i], ht1, ht2 ); if ( compResult != 0 ){ return compResult; } } return compResult; }// compare() private int compareOnAttribute( String attribute, Map<String, String> o1, Map<String, String> o2 ) { String str1 = o1.get( attribute ); String str2 = o2.get( attribute ); if ( str1 == null ){ str1 = ""; } if ( str2 == null ){ str2 = ""; } if ( caseSensitive ){ if ( ascending ){ return str1.compareTo( str2 ); }else{ return str2.compareTo( str1 ); } } if ( ascending ){ return str1.toLowerCase().compareTo( str2.toLowerCase() ); }else{ return str2.toLowerCase().compareTo( str1.toLowerCase() ); } }// compareOnAttribute() }// entryComparator }//cfldapQueryData