| /* |
| * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| // Contributors: |
| // dclarke - Dynamic Persistence |
| // http://wiki.eclipse.org/EclipseLink/Development/Dynamic |
| // (https://bugs.eclipse.org/bugs/show_bug.cgi?id=200045) |
| // - initial JPA Employee example using XML (bug 217884) |
| // ported from earlier Oracle TopLink examples |
| // mnorman - tweaks to work from Ant command-line, |
| // get database properties from System, etc. |
| // |
| package org.eclipse.persistence.testing.tests.dynamic; |
| |
| //javase imports |
| import java.io.StringWriter; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.List; |
| |
| //EclipseLink imports |
| import org.eclipse.persistence.internal.helper.Helper; |
| import org.eclipse.persistence.logging.DefaultSessionLog; |
| import org.eclipse.persistence.logging.SessionLog; |
| import org.eclipse.persistence.logging.SessionLogEntry; |
| import org.eclipse.persistence.queries.DatabaseQuery; |
| import org.eclipse.persistence.sessions.Session; |
| import org.eclipse.persistence.sessions.SessionEvent; |
| import org.eclipse.persistence.sessions.SessionEventAdapter; |
| |
| /** |
| * |
| * @author dclarke |
| * @since EclipseLink 1.1.2 |
| */ |
| public class QuerySQLTracker extends SessionEventAdapter { |
| private List<QueryResult> queries; |
| |
| /** |
| * Constructs and installs the event listener and sql tracking session log |
| * |
| */ |
| private QuerySQLTracker(Session session) { |
| session.getEventManager().addListener(this); |
| session.setSessionLog(new SQLTrackingSessionLog(session, this)); |
| reset(); |
| } |
| |
| public static QuerySQLTracker install(Session session) { |
| if (session.getSessionLog() instanceof SQLTrackingSessionLog) { |
| return ((SQLTrackingSessionLog) session.getSessionLog()) |
| .getTracker(); |
| } |
| return new QuerySQLTracker(session); |
| } |
| |
| /** |
| * Helper method to retrieve a tracker from a session where it was installed |
| * If the session exists but does not have a tracler installed then an |
| * exception is thrown. |
| */ |
| public static QuerySQLTracker getTracker(Session session) { |
| if (session == null) { |
| return null; |
| } |
| SessionLog sessionLog = session.getSessionLog(); |
| |
| if (sessionLog instanceof QuerySQLTracker.SQLTrackingSessionLog) { |
| return ((QuerySQLTracker.SQLTrackingSessionLog) sessionLog) |
| .getTracker(); |
| } |
| throw new RuntimeException( |
| "Could not retireve QuerySQLTracke from session: " + session); |
| } |
| |
| /** |
| * Reset the lists of SQL and queries being tracked |
| */ |
| public void reset() { |
| this.queries = new ArrayList<QueryResult>(); |
| } |
| |
| public List<QueryResult> getQueries() { |
| return this.queries; |
| } |
| |
| protected QuerySQLTracker.QueryResult getCurrentResult() { |
| if (getQueries().size() == 0) { |
| getQueries().add(new QueryResult(null)); |
| // throw new RuntimeException("Received SQL without a Query ???"); |
| } |
| return getQueries().get(getQueries().size() - 1); |
| } |
| |
| public int getTotalSQLCalls() { |
| int totalSQLCalls = 0; |
| |
| for (QueryResult result : getQueries()) { |
| totalSQLCalls += result.sqlStatements.size(); |
| } |
| |
| return totalSQLCalls; |
| } |
| |
| public int getTotalSQLCalls(String startsWith) { |
| int sqlCalls = 0; |
| |
| for (QueryResult result : getQueries()) { |
| for (String sql : result.sqlStatements) { |
| String sub = sql.substring(0, startsWith.length()); |
| if (sub.equalsIgnoreCase(startsWith)) { |
| sqlCalls++; |
| } |
| } |
| } |
| |
| return sqlCalls; |
| } |
| |
| public int getTotalSQLSELECTCalls() { |
| return getTotalSQLCalls("SELECT"); |
| } |
| |
| public int getTotalSQLINSERTCalls() { |
| return getTotalSQLCalls("INSERT"); |
| } |
| |
| public int getTotalSQLUPDATECalls() { |
| return getTotalSQLCalls("UPDATE"); |
| } |
| |
| public int getTotalSQLDELETECalls() { |
| return getTotalSQLCalls("DELETE"); |
| } |
| |
| @Override |
| public void preExecuteQuery(SessionEvent event) { |
| //System.err.println("*** QuerySQLTracker.preExecuteQuery(" + event.getQuery() + ")"); |
| //Thread.dumpStack(); |
| QueryResult result = new QueryResult(event.getQuery()); |
| getQueries().add(result); |
| } |
| |
| @Override |
| public void postExecuteQuery(SessionEvent event) { |
| if (getCurrentResult().query == null) { |
| getCurrentResult().setQuery(event.getQuery()); |
| } |
| getCurrentResult().setResult(event.getResult()); |
| } |
| |
| protected class QueryResult { |
| private DatabaseQuery query; |
| private String resultString = null; |
| private List<String> sqlStatements = new ArrayList<String>(); |
| |
| QueryResult(DatabaseQuery q) { |
| query = q; |
| } |
| |
| protected void setQuery(DatabaseQuery query) { |
| this.query = query; |
| } |
| |
| @SuppressWarnings("unchecked") |
| protected void setResult(Object queryResult) { |
| StringWriter writer = new StringWriter(); |
| writer.write(Helper.getShortClassName(query)); |
| writer.write("[" + System.identityHashCode(query) + "]"); |
| writer.write(" result = "); |
| |
| Object result = queryResult; |
| if (queryResult instanceof Collection) { |
| result = ((Collection) queryResult).toArray(); |
| } |
| |
| if (result == null) { |
| writer.write("NONE"); |
| } else { |
| if (result instanceof Object[]) { |
| Object[] results = (Object[]) result; |
| writer.write("<" + results.length + "> ["); |
| for (int index = 0; index < results.length; index++) { |
| if (index > 0) { |
| writer.write(", "); |
| } |
| writer.write(results[index] + ""); |
| } |
| writer.write("]"); |
| resultString = writer.toString(); |
| } else { |
| writer.write(result.toString()); |
| } |
| } |
| |
| this.resultString = writer.toString(); |
| } |
| |
| public void addSQL(String sql) { |
| sqlStatements.add(sql); |
| } |
| |
| public String toString() { |
| if (this.resultString == null) { |
| setResult(null); |
| } |
| return this.resultString; |
| } |
| } |
| |
| /** |
| * This custom SessionLog implementation wraps the existing one and redirects |
| * all SQL calls to the tracker. All messages are also passed to the original |
| * tracker. |
| */ |
| public class SQLTrackingSessionLog extends DefaultSessionLog { |
| |
| private QuerySQLTracker tracker; |
| |
| private SessionLog originalLog; |
| |
| protected SQLTrackingSessionLog(Session session, |
| QuerySQLTracker aTracker) { |
| this.tracker = aTracker; |
| this.originalLog = session.getSessionLog(); |
| setSession(session); |
| setWriter(this.originalLog.getWriter()); |
| } |
| |
| public QuerySQLTracker getTracker() { |
| return this.tracker; |
| } |
| |
| @Override |
| public synchronized void log(SessionLogEntry entry) { |
| |
| if (entry.getNameSpace() != null |
| && entry.getNameSpace().equalsIgnoreCase(SessionLog.SQL)) { |
| getTracker().getCurrentResult().addSQL(entry.getMessage()); |
| } |
| super.log(entry); |
| } |
| |
| @Override |
| public int getLevel(String category) { |
| return this.originalLog.getLevel(category); |
| } |
| |
| @Override |
| public void setLevel(int level, String category) { |
| this.originalLog.setLevel(level, category); |
| } |
| |
| @Override |
| public int getLevel() { |
| return this.originalLog.getLevel(); |
| } |
| |
| @Override |
| public void setLevel(int level) { |
| this.originalLog.setLevel(level); |
| } |
| |
| @Override |
| public boolean shouldPrintConnection() { |
| return this.originalLog.shouldPrintConnection(); |
| } |
| |
| @Override |
| public boolean shouldPrintDate() { |
| return this.originalLog.shouldPrintDate(); |
| } |
| |
| @Override |
| public boolean shouldPrintSession() { |
| return this.originalLog.shouldPrintSession(); |
| } |
| |
| @Override |
| public boolean shouldPrintThread() { |
| return this.originalLog.shouldPrintThread(); |
| } |
| } |
| |
| public void printResults(String prefix) { |
| System.out.println(prefix + "-QuerySQLTracker-Queries:"); |
| |
| int sql = 0; |
| for (int index = 0; index < getQueries().size(); index++) { |
| QueryResult result = getQueries().get(index); |
| |
| System.out.println("\t" + (index + 1) + "> " + result); |
| |
| for (int sqlNum = 0; sqlNum < result.sqlStatements.size(); sqlNum++) { |
| sql++; |
| System.out.println("\t\t" + (index + 1) + "." + (sqlNum + 1) |
| + "-" + sql + "> " + result.sqlStatements.get(sqlNum)); |
| } |
| } |
| |
| System.out.println(prefix + "-QuerySQLTracker-Queries: " |
| + getQueries().size()); |
| System.out.println(prefix + "-QuerySQLTracker-INSERT: " |
| + getTotalSQLINSERTCalls()); |
| System.out.println(prefix + "-QuerySQLTracker-SELECT: " |
| + getTotalSQLSELECTCalls()); |
| System.out.println(prefix + "-QuerySQLTracker-UPDATE: " |
| + getTotalSQLUPDATECalls()); |
| System.out.println(prefix + "-QuerySQLTracker-DELETE: " |
| + getTotalSQLDELETECalls()); |
| } |
| |
| } |