From 8f83b6c091706cd4b404fd94a8c910b49cfda62e Mon Sep 17 00:00:00 2001 From: Chrriis Date: Mon, 30 Apr 2012 23:02:24 +0200 Subject: [PATCH] [#1177] Add SQL Console module to jOOQ - Statement matcher for server level filtering of data to log. --- .../java/org/jooq/debug/StatementInfo.java | 82 +++++++++ .../java/org/jooq/debug/StatementMatcher.java | 173 ++++++++++++++++++ ...ServerLoggingStatementMatchersMessage.java | 57 ++++++ 3 files changed, 312 insertions(+) create mode 100644 jOOQ-console/src/main/java/org/jooq/debug/StatementInfo.java create mode 100644 jOOQ-console/src/main/java/org/jooq/debug/StatementMatcher.java create mode 100644 jOOQ-console/src/main/java/org/jooq/debug/console/remote/ServerLoggingStatementMatchersMessage.java diff --git a/jOOQ-console/src/main/java/org/jooq/debug/StatementInfo.java b/jOOQ-console/src/main/java/org/jooq/debug/StatementInfo.java new file mode 100644 index 0000000000..fc94e0ae37 --- /dev/null +++ b/jOOQ-console/src/main/java/org/jooq/debug/StatementInfo.java @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2009-2012, Lukas Eder, lukas.eder@gmail.com + * Christopher Deckers, chrriis@gmail.com + * All rights reserved. + * + * This software is licensed to you under the Apache License, Version 2.0 + * (the "License"); You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name "jOOQ" nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package org.jooq.debug; + +import java.io.Serializable; + +@SuppressWarnings("serial") +public class StatementInfo implements Serializable { + + private SqlQueryType queryType; + private String[] queries; + private String parameterDescription; + private String threadName; + private long threadID; + + public StatementInfo(SqlQueryType queryType, String[] queries, String parameterDescription) { + Thread currentThread = Thread.currentThread(); + this.threadName = currentThread.getName(); + this.threadID = currentThread.getId(); + this.queryType = queryType; + this.queries = queries; + this.parameterDescription = parameterDescription; + } + + public String getThreadName() { + return threadName; + } + + public long getThreadID() { + return threadID; + } + + public SqlQueryType getQueryType() { + return queryType; + } + + public String[] getQueries() { + return queries; + } + + /** + * @return non null if queries consist of a single prepared statement with parameters. + */ + public String getParameterDescription() { + return parameterDescription; + } + +} diff --git a/jOOQ-console/src/main/java/org/jooq/debug/StatementMatcher.java b/jOOQ-console/src/main/java/org/jooq/debug/StatementMatcher.java new file mode 100644 index 0000000000..2c5423f51d --- /dev/null +++ b/jOOQ-console/src/main/java/org/jooq/debug/StatementMatcher.java @@ -0,0 +1,173 @@ +/** + * Copyright (c) 2009-2012, Lukas Eder, lukas.eder@gmail.com + * Christopher Deckers, chrriis@gmail.com + * All rights reserved. + * + * This software is licensed to you under the Apache License, Version 2.0 + * (the "License"); You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name "jOOQ" nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package org.jooq.debug; + +import java.io.Serializable; +import java.util.EnumSet; +import java.util.Set; +import java.util.regex.Pattern; + +@SuppressWarnings("serial") +public class StatementMatcher implements Serializable { + + public static enum TextMatchingType { + STARTS_WITH, + CONTAINS, + EQUALS, + MATCHES_REG_EXP, + } + + private String threadName; + private TextMatchingType textMatchingType; + private String text; + private boolean isTextMatchingCaseSensitive; + private Set queryTypeSet; + + private Pattern pattern; + + /** + * @param threadName a name or null for no matching on thread name. + * @param textMatchingType a type or null for no text matching. + * @param queryTypeSet some types or null for all types. + */ + public StatementMatcher(String threadName, TextMatchingType textMatchingType, String text, boolean isTextMatchingCaseSensitive, Set queryTypeSet) { + this.threadName = threadName; + this.textMatchingType = textMatchingType; + this.text = text; + this.isTextMatchingCaseSensitive = isTextMatchingCaseSensitive; + this.queryTypeSet = queryTypeSet == null? null: EnumSet.copyOf(queryTypeSet); + switch (textMatchingType) { + case CONTAINS: { + String patternText = ".*\\Q" + text.replace("\\E", "\\\\E").replace("\\Q", "\\\\Q") + "\\E.*\\Q"; + pattern = Pattern.compile(patternText, isTextMatchingCaseSensitive? 0: Pattern.CASE_INSENSITIVE); + break; + } + case MATCHES_REG_EXP: { + pattern = Pattern.compile(text, isTextMatchingCaseSensitive? 0: Pattern.CASE_INSENSITIVE); + break; + } + } + } + + public boolean matches(StatementInfo statementInfo) { + if(threadName != null) { + if(!threadName.equals(statementInfo.getThreadName())) { + return false; + } + } + if(textMatchingType != null) { + if(text == null) { + return false; + } + switch(textMatchingType) { + case STARTS_WITH: { + boolean isMatching = false; + for(String sql: statementInfo.getQueries()) { + if(isTextMatchingCaseSensitive) { + if(sql.startsWith(text)) { + isMatching = true; + break; + } + } else if(sql.length() >= text.length()) { + // Let's avoid creating new String instance. + if(sql.substring(0, text.length()).equalsIgnoreCase(text)) { + isMatching = true; + break; + } + } + } + if(!isMatching) { + return false; + } + break; + } + case EQUALS: { + boolean isMatching = false; + for(String sql: statementInfo.getQueries()) { + if(isTextMatchingCaseSensitive) { + if(sql.equals(text)) { + isMatching = true; + break; + } + } else { + if(sql.equalsIgnoreCase(text)) { + isMatching = true; + break; + } + } + } + if(!isMatching) { + return false; + } + break; + } + case CONTAINS: { + boolean isMatching = false; + for(String sql: statementInfo.getQueries()) { + if(pattern.matcher(sql).matches()) { + isMatching = true; + break; + } + } + if(!isMatching) { + return false; + } + } + case MATCHES_REG_EXP: { + boolean isMatching = false; + for(String sql: statementInfo.getQueries()) { + if(pattern.matcher(sql).matches()) { + isMatching = true; + break; + } + } + if(!isMatching) { + return false; + } + } + } + } + if(queryTypeSet != null) { + if(!queryTypeSet.contains(statementInfo.getQueryType())) { + return false; + } + } + return true; + } + + +} diff --git a/jOOQ-console/src/main/java/org/jooq/debug/console/remote/ServerLoggingStatementMatchersMessage.java b/jOOQ-console/src/main/java/org/jooq/debug/console/remote/ServerLoggingStatementMatchersMessage.java new file mode 100644 index 0000000000..613c4196da --- /dev/null +++ b/jOOQ-console/src/main/java/org/jooq/debug/console/remote/ServerLoggingStatementMatchersMessage.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2009-2012, Lukas Eder, lukas.eder@gmail.com + * Christopher Deckers, chrriis@gmail.com + * All rights reserved. + * + * This software is licensed to you under the Apache License, Version 2.0 + * (the "License"); You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name "jOOQ" nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package org.jooq.debug.console.remote; + +import org.jooq.debug.StatementMatcher; + +/** + * @author Christopher Deckers + */ +@SuppressWarnings("serial") +public class ServerLoggingStatementMatchersMessage implements Message { + + private StatementMatcher[] statementMatchers; + + public ServerLoggingStatementMatchersMessage(StatementMatcher[] statementMatchers) { + this.statementMatchers = statementMatchers; + } + + public StatementMatcher[] getStatementMatchers() { + return statementMatchers; + } + +}