package com.ikokoon.serenity;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;
import org.apache.log4j.Logger;
import org.objectweb.asm.ClassVisitor;
import com.ikokoon.serenity.instrumentation.complexity.ComplexityClassAdapter;
import com.ikokoon.serenity.instrumentation.coverage.CoverageClassAdapter;
import com.ikokoon.serenity.instrumentation.dependency.DependencyClassAdapter;
import com.ikokoon.serenity.instrumentation.profiling.ProfilingClassAdviceAdapter;
import com.ikokoon.serenity.model.Project;
import com.ikokoon.toolkit.LoggingConfigurator;
import com.ikokoon.toolkit.Toolkit;
/**
* The configuration object holds the parameters for the processing, some from the system parameters that can be set by the user and some internal
* like packages to be excluded always for example java.lang.
*
* @author Michael Couck
* @since 05.10.09
* @version 01.00
*/
public class Configuration {
/** The instance of the configuration. */
private static Configuration configuration = new Configuration();
/** The logger for the class. */
public Logger logger;
/** Packages that are included in the enhancement. */
public Set<String> includedPackages = new TreeSet<String>();
/** Patterns in class names that are excluded from enhancement. */
public Set<String> excludedPackages = new TreeSet<String>();
/** The class adapters that the system will chain. */
public List<Class<ClassVisitor>> classAdapters = new ArrayList<Class<ClassVisitor>>();
/**
* System wide access to the configuration.
*
* @return the configuration for the system
*/
public static synchronized Configuration getConfiguration() {
return configuration;
}
/**
* Private access insures singularity.
*/
private Configuration() {
LoggingConfigurator.configure();
logger = Logger.getLogger(this.getClass());
addIncludedPackages();
addExcludedPackages();
addIncludedClassAdapters();
addDefaultExcludedPackages();
}
/**
* Checks to see that the class name is included in the packages that are to be included.
*
* @param string
* the string to check for pattern inclusion
* @return whether the string is included in the pattern list
*/
public boolean included(String string) {
if (string == null) {
return false;
}
string = Toolkit.slashToDot(string);
for (String pattern : includedPackages) {
// logger.info("String : " + string + ", pattern : " + pattern + ", index of : " + (string.indexOf(pattern) > -1));
if (string.indexOf(pattern) > -1) {
return true;
}
}
return false;
}
/**
* Checks to see if the class is included in the classes that can be enhanced, so for example java.lang is excluded.
*
* @param string
* the string that is to be checked for exclusion
* @return whether the class is excluded and should not be used
*/
public boolean excluded(String string) {
if (string == null) {
return true;
}
string = Toolkit.slashToDot(string);
for (String pattern : excludedPackages) {
if (string.indexOf(pattern) > -1) {
return true;
}
}
return false;
}
/**
* Access to the system properties. This method can be extended to include other properties like in files etc.
*
* @param name
* the name of the property
* @return the system property with the specified name
*/
public String getProperty(String name) {
return System.getProperty(name);
}
/**
* Access to the classpath of the system. Included in the classpath are the jars that were manually added by the user.
*
* @return the classpath of the system including the Surefire classpath
*/
public String getClassPath() {
StringBuilder builder = new StringBuilder();
String classpath = System.getProperty(IConstants.JAVA_CLASS_PATH);
builder.append(classpath);
String surefireClasspath = System.getProperty(IConstants.SUREFIRE_TEST_CLASS_PATH);
if (surefireClasspath != null) {
builder.append(File.pathSeparator);
builder.append(surefireClasspath);
}
String includedJars = System.getProperty(IConstants.INCLUDED_JARS_PROPERTY);
logger.debug("Included jars : " + includedJars);
if (includedJars != null) {
StringTokenizer tokenizer = new StringTokenizer(includedJars, ";:", false);
while (tokenizer.hasMoreTokens()) {
String jarFile = tokenizer.nextToken();
builder.append(File.pathSeparator);
builder.append(jarFile);
}
}
return builder.toString();
}
public long getSnapshotInterval() {
String snapshotInterval = System.getProperty(IConstants.SNAPSHOT_INTERVAL);
if (snapshotInterval != null && Toolkit.isDigits(snapshotInterval)) {
return Long.parseLong(snapshotInterval);
}
return -1;
}
public long getReportInterval() {
String reportInterval = System.getProperty(IConstants.REPORT_INTERVAL);
if (reportInterval != null && Toolkit.isDigits(reportInterval)) {
return Long.parseLong(reportInterval);
}
return -1;
}
private void addIncludedPackages() {
String packageNames = System.getProperty(IConstants.INCLUDED_PACKAGES_PROPERTY);
logger.debug("Package names : " + packageNames);
if (packageNames != null) {
StringTokenizer tokenizer = new StringTokenizer(packageNames, ";: ", false);
while (tokenizer.hasMoreTokens()) {
String packageName = tokenizer.nextToken();
packageName = Toolkit.stripWhitespace(packageName);
includedPackages.add(packageName);
logger.debug("Added package to enhance : " + packageName);
}
}
}
private void addExcludedPackages() {
String excludedPatterns = System.getProperty(IConstants.EXCLUDED_PACKAGES_PROPERTY);
if (excludedPatterns != null) {
StringTokenizer tokenizer = new StringTokenizer(excludedPatterns, ";: ", false);
while (tokenizer.hasMoreTokens()) {
String excludedPattern = tokenizer.nextToken();
excludedPackages.add(excludedPattern);
}
}
}
@SuppressWarnings("unchecked")
private void addIncludedClassAdapters() {
String adapterNames = System.getProperty(IConstants.INCLUDED_ADAPTERS_PROPERTY);
if (adapterNames != null) {
StringTokenizer tokenizer = new StringTokenizer(adapterNames, ";: ", false);
while (tokenizer.hasMoreTokens()) {
String adapterName = tokenizer.nextToken();
adapterName = Toolkit.stripWhitespace(adapterName);
try {
if (adapterName.equals(IConstants.COVERAGE)) {
classAdapters.add((Class<ClassVisitor>) Class.forName(CoverageClassAdapter.class.getName()));
}
if (adapterName.equals(IConstants.COMPLEXITY)) {
classAdapters.add((Class<ClassVisitor>) Class.forName(ComplexityClassAdapter.class.getName()));
}
if (adapterName.equals(IConstants.DEPENDENCY)) {
classAdapters.add((Class<ClassVisitor>) Class.forName(DependencyClassAdapter.class.getName()));
}
if (adapterName.equals(IConstants.PROFILING)) {
classAdapters.add((Class<ClassVisitor>) Class.forName(ProfilingClassAdviceAdapter.class.getName()));
}
} catch (ClassNotFoundException e) {
logger.error("Class : " + adapterName + " not found", e);
}
}
}
}
private void addDefaultExcludedPackages() {
excludedPackages.add("java.lang");
excludedPackages.add("sun");
excludedPackages.add("sunw");
excludedPackages.add("com.sun");
excludedPackages.add("Test");
excludedPackages.add(Project.class.getPackage().getName());
}
}