/*
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.max.vma.tools.qa;
import java.text.DecimalFormat;
import java.text.FieldPosition;
import java.util.ArrayList;
import java.util.regex.*;
import java.io.*;
import java.net.*;
/**
* Base class for query implementations that defines some useful methods.
*
*/
public abstract class QueryBase {
protected final static String INDENT_TWO = " ";
protected final static String INDENT_FOUR = " ";
protected final static String DEFAULT_QUERY_PACKAGE = "com.oracle.max.vma.tools.qa.queries";
protected static DecimalFormat format6 = new DecimalFormat("#.000000");
protected static DecimalFormat format4 = new DecimalFormat("#.0000");
protected static DecimalFormat format2 = new DecimalFormat("#.00");
protected static FieldPosition fpos0 = new FieldPosition(0);
private static ArrayList<URL> queryClassURLs = new ArrayList<URL>();
private static URLClassLoader urlClassLoader;
private static String packageName = DEFAULT_QUERY_PACKAGE;
public boolean verbose;
public String className;
public String id;
public String clId;
public String thread;
public boolean absTime = false;
private Pattern classPattern;
public static void addQueryClassDir(String dir) {
try {
queryClassURLs.add(new URL(dir));
} catch (Exception e) {
throw new RuntimeException("malformed class directory " + dir);
}
}
public static void setQueryPackage(String p) {
packageName = p;
}
public static QueryBase ensureLoaded(String queryName) {
try {
if (urlClassLoader == null) {
urlClassLoader = new URLClassLoader(queryClassURLs.toArray(new URL[queryClassURLs.size()]));
}
Class<?> q = urlClassLoader.loadClass(packageName + "." + queryName + "Query");
QueryBase query = (QueryBase) q.newInstance();
return query;
} catch (Exception e) {
throw new RuntimeException("failed to load query class " + queryName);
}
}
/**
* TODO find all the class files rooted at queryClassURLs.
*/
public static void listQueries() {
for (URL url : queryClassURLs) {
String[] files = new File(url.getPath()).list();
for (String file : files) {
if (!file.contains("Helper")) {
int ix = file.indexOf("Query");
if (ix > 0) {
System.out.println(file.substring(0, ix));
}
}
}
}
}
public Object execute(ArrayList<TraceRun> traceRuns, int traceFocus, PrintStream ps, String[] args) {
ps.println("no query defined");
return null;
}
/**
* Return true if {@code cr.getName()} matches {@link #className}.
* @param cr
*/
public boolean classMatches(ClassRecord cr) {
if (className == null) {
return true;
}
if (classPattern == null) {
classPattern = Pattern.compile(className);
}
return classPattern.matcher(cr.getName()).matches();
}
/**
* Parse standard arguments and return an array with them removed.
*
* @param args
*/
public String[] parseStandardArgs(String[] args) {
verbose = false;
className = null;
classPattern = null;
id = null;
clId = null;
thread = null;
absTime = false;
// Checkstyle: stop modified control variable check
for (int i = 0; i < args.length; i++) {
final String arg = args[i];
// assume remove
args[i] = null;
if (arg.equals("-v")) {
verbose = true;
} else if (arg.equals("-class") || arg.equals("-c")) {
className = args[++i];
} else if (arg.equals("-thread") || arg.equals("-t")) {
thread = args[++i];
} else if (arg.equals("-id")) {
id = args[++i];
} else if (arg.equals("-clid")) {
clId = args[++i];
} else if (arg.equals("-abs")) {
absTime = true;
} else {
// reinstate
args[i] = arg;
}
}
// Checkstyle: resume modified control variable check
return removeProcessedArgs(args);
}
protected String[] removeProcessedArgs(String[] args) {
String[] result = args;
int removed = 0;
for (String arg : args) {
if (arg == null) {
removed++;
}
}
if (removed > 0) {
result = new String[args.length - removed];
int i = 0;
for (String arg : args) {
if (arg != null) {
result[i++] = arg;
}
}
}
return result;
}
public long timeValue(TraceRun traceRun, long time) {
if (absTime) {
return time;
} else {
return traceRun.relTime(time);
}
}
public static double ms(long t) {
return ((double) t) / 1000000;
}
public static double percent(long a, long b) {
if (a == 0) {
return 0.0;
} else if (b == 0) {
return 100.0;
} else {
return (double) (a * 100) / (double) b;
}
}
public static String d6d(double d) {
return format6.format(d, new StringBuffer(), fpos0).toString();
}
public static String d4d(double d) {
return format4.format(d, new StringBuffer(), fpos0).toString();
}
public static String d2d(double d) {
return format2.format(d, new StringBuffer(), fpos0).toString();
}
public void space(PrintStream ps, int n) {
for (int i = 0; i < n; i++) {
ps.print(' ');
}
}
public static String getShowClassLoader(TraceRun traceRun, String classLoaderId) {
final String defaultName = classLoaderId;
ObjectRecord ctd = traceRun.objects.get(defaultName);
assert ctd != null;
return ctd.toString();
}
}