/** * Copyright (c) 2009-2011 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.springsource.insight.plugin.cassandra; import static com.springsource.insight.util.StringUtil.indexOfNotIn; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeMap; import com.datastax.driver.core.BoundStatement; import com.datastax.driver.core.Statement; import com.springsource.insight.intercept.operation.Operation; import com.springsource.insight.intercept.operation.OperationList; import com.springsource.insight.intercept.operation.OperationMap; import com.springsource.insight.util.ListUtil; import com.springsource.insight.util.StringFormatterUtils; import com.springsource.insight.util.StringUtil; public class CassandraOperationFinalizer { public static final String KEYSPACE = "keyspace"; public static final String CLUSTER_NAME ="clustername"; public static final String PORT = "cassandra_port"; public static final String HOSTS = "cassandra_hosts"; public static final String PARAMS_VALUES = "params"; public static final String UNKNOWN_CQL = "UNKNOWN"; static final WeakKeyHashMap<Statement, Operation> storage = new WeakKeyHashMap<Statement, Operation>(); private CassandraOperationFinalizer() { throw new UnsupportedOperationException("No instance"); } public static Operation get(Statement statement) { return storage.get(statement); } public static Operation put(Statement statement, Operation operation) { return storage.put(statement, operation); } public static Operation remove(Statement statement) { return storage.remove(statement); } public static void addParam(Operation operation, String key, Object param) { OperationMap params = operation.get(PARAMS_VALUES, OperationMap.class); if (params == null) params = operation.createMap(PARAMS_VALUES); params.put(key, StringFormatterUtils.formatObjectAndTrim(param)); } public static void addParam(Operation operation, int index, Object param) { addParam(operation, "P_" + index, param); } private static class Keywords { private String keyword; private String argPos; public Keywords(String keyword, String argPos) { this.argPos = argPos; this.keyword = keyword; } public String getKeyword() { return keyword; } public String getArgPos() { return argPos; } } private static final Collection<Keywords> stmtsList = Collections.unmodifiableList(new ArrayList<Keywords>() { { add(new Keywords("SELECT", " FROM ")); add(new Keywords("INSERT", " INTO ")); add(new Keywords("DELETE", " FROM ")); add(new Keywords("UPDATE", "UPDATE ")); add(new Keywords("CREATE TABLE IF NOT EXISTS", " EXISTS ")); add(new Keywords("CREATE TABLE", " TABLE ")); add(new Keywords("CREATE KEYSPACE IF NOT EXISTS", " EXISTS ")); add(new Keywords("CREATE KEYSPACE", " KEYSPACE ")); add(new Keywords("ALTER TABLE", " TABLE ")); add(new Keywords("DROP TABLE IF EXISTS", " EXISTS ")); add(new Keywords("DROP TABLE", " TABLE ")); add(new Keywords("CREATE INDEX IF NOT EXISTS", " EXISTS ")); add(new Keywords("CREATE INDEX", " INDEX ")); add(new Keywords("CREATE CUSTOM INDEX IF NOT EXISTS", " EXISTS ")); add(new Keywords("CREATE CUSTOM INDEX", " INDEX ")); add(new Keywords("DROP INDEX IF EXISTS", " EXISTS ")); add(new Keywords("DROP INDEX", " INDEX ")); add(new Keywords("TRUNCATE", " TRUNCATE ")); add(new Keywords("USE", " USE ")); } }); public static String createLabel(String cql) { if (StringUtil.isEmpty(cql)) { return "CQL"; } String upperSql = cql.toUpperCase().trim(); for (Keywords keywords : stmtsList) { String kwd = keywords.getKeyword(); if (!upperSql.startsWith(kwd)) { continue; } String argPos = keywords.getArgPos(); return appendArgumentValue("CQL " + kwd, captureWordAfter(upperSql, argPos)); } // some special extra statements if (upperSql.startsWith("CREATE") || upperSql.startsWith("DROP") || upperSql.startsWith("ALTER") ) { return "CQL DML"; } else { return "CQL STATEMENT"; // could be any number of unhandled CQL statements } } private static String appendArgumentValue(String prefix, String agrValue) { if (StringUtil.isEmpty(agrValue)) { return prefix; } else { return prefix + " (" + agrValue + ")"; } } private static final Set<Character> WORD_DELIMS = Collections.unmodifiableSet(ListUtil.asSet(Character.valueOf(' '), Character.valueOf('('))); private static String captureWordAfter(String source, String delim) { if (delim.charAt(delim.length() - 1) != ' ') { throw new IllegalArgumentException("Last char must be a ' '"); } int fromIdx = source.indexOf(delim); if (fromIdx < 0) { return null; } String strAfterDelim = source.substring(fromIdx + delim.length() - 1).trim(); int wordIdx = indexOfNotIn(strAfterDelim, WORD_DELIMS); if (wordIdx < 0) { return null; } else if (wordIdx > 0) { strAfterDelim = strAfterDelim.substring(wordIdx); } int wordEndIdx = StringUtil.indexOfIn(strAfterDelim, WORD_DELIMS); if (wordEndIdx < 0) { return strAfterDelim; } else { return strAfterDelim.substring(0, wordEndIdx); } } }