package org.apache.cassandra.auth; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.StringTokenizer; import org.apache.cassandra.thrift.CassandraServer; import org.apache.cassandra.thrift.ColumnOrSuperColumn; import org.apache.cassandra.thrift.ColumnPath; import org.apache.cassandra.thrift.ConsistencyLevel; import org.apache.cassandra.thrift.InvalidRequestException; import org.apache.cassandra.thrift.NotFoundException; import org.apache.cassandra.thrift.TimedOutException; import org.apache.cassandra.thrift.UnavailableException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Node; import org.w3c.dom.NodeList; public class Evaluator { private static Logger logger = LoggerFactory.getLogger(Evaluator.class); protected static final String YYYY_MM_DD = "yyyy/MM/dd"; protected static final String CURRENT_TIME = "CURRENT_TIME"; protected static boolean evaluate(ByteBuffer key, AuthenticatedUser user, Node whereNode, CassandraServer server) { boolean result = false; NodeList whereNodeChildren = whereNode.getChildNodes(); for (int k = 0; k < whereNodeChildren.getLength(); k++) { Node n = whereNodeChildren.item(k); if (n.getNodeName().equals("in")) { result = evaluate_in(key, user, n, server); } if (n.getNodeName().equals("equal")) { result = evaluate_equal(key, user, n, server); } if (n.getNodeName().equals("and")) { result = evaluate_and(key, user, n, server); } } return result; } protected static boolean evaluate_in(ByteBuffer key, AuthenticatedUser user, Node inNode, CassandraServer server) { boolean result = false; Node lhsNode, rhsNode; lhsNode = XMLHelper.getChildNodeByName(inNode, "op1"); rhsNode = XMLHelper.getChildNodeByName(inNode, "op2"); if (lhsNode != null && rhsNode != null) { String lhs = lhsNode.getTextContent().trim(); String rhs = rhsNode.getTextContent().trim(); String lhsResult = evaluate(key, user, lhs, server); String rhsResult = evaluate(key, user, rhs, server); if (rhs.equals("CURRENT_TIME")) { DateFormat dateFormat = new SimpleDateFormat( "yyyy/MM/dd HH:mm:ss"); Date date = new Date(); int i = compareDates(dateFormat.format(date), lhsResult); if (i == 1) return true; else return false; } return (rhsResult.contains(lhsResult)); } return result; } protected static boolean evaluate_equal(ByteBuffer key, AuthenticatedUser user, Node andNode, CassandraServer server) { boolean result = false; Node lhsNode, rhsNode; lhsNode = XMLHelper.getChildNodeByName(andNode, "op1"); rhsNode = XMLHelper.getChildNodeByName(andNode, "op2"); if (lhsNode != null && rhsNode != null) { String lhs = lhsNode.getTextContent().trim(); String rhs = rhsNode.getTextContent().trim(); String lhsResult = evaluate(key, user, lhs, server); String rhsResult = evaluate(key, user, rhs, server); return (rhsResult.equals(lhsResult)); } return result; } protected static boolean evaluate_and(ByteBuffer key, AuthenticatedUser user, Node andNode, CassandraServer server) { boolean result = true; NodeList children = andNode.getChildNodes(); for (int k = 0; k < children.getLength(); k++) { Node n = children.item(k); if (n.getNodeName().equals("in")) { result = result && evaluate_in(key, user, n, server); } if (n.getNodeName().equals("equal")) { result = result && evaluate_equal(key, user, n, server); } if (n.getNodeName().equals("and")) { result = result && evaluate_and(key, user, n, server); } } return result; } protected static int compareDates(String inputDate, String dateRange) { String[] dateEndPoints = dateRange.split("-"); DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); try { Date date = dateFormat.parse(inputDate); Date leftEndPoint = dateFormat.parse(dateEndPoints[0]); Date rightEndPoint = dateFormat.parse(dateEndPoints[1]); if (date.after(leftEndPoint) && date.before(rightEndPoint)) { return 1; } else { return 0; } } catch (ParseException e) { e.printStackTrace(); } return 0; } private static String evaluate(ByteBuffer key, AuthenticatedUser user, String expr, CassandraServer server) { String answer = null; if (expr.equals(CURRENT_TIME)) { DateFormat dateFormat = new SimpleDateFormat(YYYY_MM_DD); Date date = new Date(); return dateFormat.format(date); } String columnFamily = parseColumnFamily(expr); String column = parseColumn(expr); ByteBuffer queryKey = parseKey(key, user, expr, server); String queryKeyString = KVACUtil.getStringRepresentation(queryKey); ColumnPath accessorColPath = new ColumnPath(); accessorColPath.setColumn_family(columnFamily); accessorColPath.setColumn(column.getBytes()); try { ConsistencyLevel consistency_level = ConsistencyLevel .findByValue(1); ColumnOrSuperColumn accessorsSpecificColumn; //System.out.println("(Evaluator - evaluate) Making a GET call for:" + queryKeyString); accessorsSpecificColumn = server.get(queryKey, accessorColPath, consistency_level); String accessorColValue = KVACUtil .getStringRepresentation(accessorsSpecificColumn.getColumn() .bufferForValue()); //logger.info(" -- KVAC --- Accessor column value:" // + accessorColValue); //System.out.println(" Column value:" + accessorColValue); answer = accessorColValue; } catch (NotFoundException e) { e.printStackTrace(); } catch (InvalidRequestException e) { e.printStackTrace(); } catch (UnavailableException e) { e.printStackTrace(); } catch (TimedOutException e) { e.printStackTrace(); } return answer; } protected static String parseColumnFamily(String expression) { // input = /PatientInfoSystem/Patient(key=thisKey)/name // output = "Patient" String columnFamily = null; StringTokenizer tokenizer = new StringTokenizer(expression, "/"); int count = 0; while (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken(); if (count == 1) { int index = token.indexOf("("); columnFamily = token.substring(0, index > 0 ? index : token .length()); break; } else { count++; } } return columnFamily; } protected static String parseColumn_prev(String expression) { // input = /PatientInfoSystem/Patient(key=thisKey)/name // output = "name" String column = null; StringTokenizer tokenizer = new StringTokenizer(expression, "/"); int count = 0; while (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken(); if (count == 2) { int index = token.indexOf("("); column = token.substring(0, index > 0 ? index : token.length()); break; } else { count++; } } return column; } protected static String parseColumn(String expression) { // input = /PatientInfoSystem/Patient(key=thisKey)/name // output = "name" // input = // /PatientInfoSystem/Doctor(key=/PatientInfoSystem/Patient(key=thisKey)/curr_doctor)/location // output = "location" // input = // /SocialShare/Person(key=thisKey)/message(value=$c) // output = message String[] colNameValueArr = new String[2]; String column = null; String value = null; int lastSlashIndex = expression.lastIndexOf("/"); column = expression.substring(lastSlashIndex + 1); int firstParenIndex = column.indexOf("("); if (firstParenIndex >= 0) { value = column.substring(firstParenIndex + 1, column .lastIndexOf("")); value = value.substring(value.indexOf("=") + 1, value.length() - 1); column = column.substring(0, firstParenIndex); } colNameValueArr[0] = column; colNameValueArr[1] = value; return column; } protected static ByteBuffer parseKey(ByteBuffer inputKey, AuthenticatedUser user, String expression, CassandraServer server) { // 1) input = /PatientInfoSystem/Patient(key=thisKey)/name // output = inputKey // 2) input = /PatientInfoSystem/Doctor(key=user.name)/curr_patients // output = key constructed from user's username // 3) input = /PatientInfoSystem/Doctor(key=/PatientInfoSystem/Patient(key=thisKey)/curr_doctor)/location // output = key corresponding to the name of "curr_doctor" for inputKey int start = expression.indexOf("("); int end = expression.lastIndexOf(")"); String keyVal = expression.substring(start + 1, end); if (keyVal.equals("key=thisKey")) { return inputKey; } else if (keyVal.equals("key=user.name")) { String keyName = user.username; ByteBuffer keyOfAccessor = getKey(keyName); return keyOfAccessor; } else { keyVal = keyVal.substring(keyVal.indexOf("/")); String keyString = evaluate(inputKey, user, keyVal, server); ByteBuffer keyOfAccessor = getKey(keyString); return keyOfAccessor; } } private static ByteBuffer getKey(String keyName) { byte[] keyNameArray = keyName.getBytes(Charset.forName("ISO-8859-1")); ByteBuffer keyOfAccessor = ByteBuffer.wrap(keyNameArray); return keyOfAccessor; } private static String evaluate_poc(ByteBuffer key, AuthenticatedUser user, String expr, CassandraServer server) { String answer = null; // 2.1 Create the key ByteBuffer keyOfAccessor = ByteBuffer.allocate(6); String t1 = "jsmith"; byte[] t1array = t1.getBytes(Charset.forName("ISO-8859-1")); keyOfAccessor = ByteBuffer.wrap(t1array); String temp = KVACUtil.getStringRepresentation(keyOfAccessor); // 2.2 Create the ColumnPath ColumnPath accessorColPath = new ColumnPath(); accessorColPath.setColumn_family("Doctor"); accessorColPath.setColumn("curr_patients".getBytes()); // 2.3 Query the accessor's Column Family try { ConsistencyLevel consistency_level = ConsistencyLevel .findByValue(1); ColumnOrSuperColumn accessorsSpecificColumn; try { accessorsSpecificColumn = server.get(keyOfAccessor, accessorColPath, consistency_level); String accessorColValue = KVACUtil .getStringRepresentation(accessorsSpecificColumn .getColumn().bufferForValue()); logger.info(" -- KVAC --- Accessor column value:" + accessorColValue); answer = accessorColValue; } catch (InvalidRequestException e) { e.printStackTrace(); } catch (UnavailableException e) { e.printStackTrace(); } catch (TimedOutException e) { e.printStackTrace(); } } catch (NotFoundException e) { e.printStackTrace(); } return answer; } }