/*
* 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 net.grinder.util;
import static org.ngrinder.common.util.CollectionUtils.newArrayList;
import static org.ngrinder.common.util.Preconditions.checkNotNull;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
/**
* Grinder classpath optimization class.
*
* @author JunHo Yoon
* @since 3.0
*/
public abstract class AbstractGrinderClassPathProcessor {
private final List<String> foreMostJarList = newArrayList();
private final List<String> patchJarList = newArrayList();
private final List<String> usefulJarList = newArrayList();
private final List<String> uselessJarList = newArrayList();
/**
* Constructor.
*/
public AbstractGrinderClassPathProcessor() {
init();
initMore();
}
private static boolean junitContext = false;
static void setJUnitContext() {
junitContext = true;
}
/**
* Construct classPath for grinder from given classpath string.
*
* @param classPath classpath string
* @param logger logger
* @return classpath optimized for grinder.
*/
public String filterClassPath(String classPath, Logger logger) {
List<String> classPathList = new ArrayList<String>();
for (String eachClassPath : checkNotNull(classPath).split(File.pathSeparator)) {
String filename = FilenameUtils.getName(eachClassPath);
if (isUsefulJar(filename) || isUsefulReferenceProject(eachClassPath)) {
logger.trace("classpath :" + eachClassPath);
classPathList.add(eachClassPath);
}
}
return StringUtils.join(classPathList, File.pathSeparator);
}
private boolean isUsefulReferenceProject(String path) {
return junitContext && new File(path).isDirectory()
&& path.contains(File.separator + "ngrinder-groovy" + File.separator);
}
/**
* Construct the classpath of ngrinder which is very important and located in the head of
* classpath.
*
* @param classPath classpath string
* @param logger logger
* @return classpath optimized for grinder.
*/
public String filterForeMostClassPath(String classPath, Logger logger) {
List<String> classPathList = new ArrayList<String>();
for (String eachClassPath : checkNotNull(classPath).split(File.pathSeparator)) {
String filename = FilenameUtils.getName(eachClassPath);
if (isForemostJar(filename) || isUsefulForForemostReferenceProject(eachClassPath)) {
logger.trace("classpath :" + eachClassPath);
classPathList.add(eachClassPath);
}
}
return StringUtils.join(classPathList, File.pathSeparator);
}
/**
* Construct the classpath of ngrinder which is very important and located in the head of
* classpath.
*
* @param classPath classpath string
* @param logger logger
* @return classpath optimized for grinder.
*/
public String filterPatchClassPath(String classPath, Logger logger) {
List<String> classPathList = new ArrayList<String>();
for (String eachClassPath : checkNotNull(classPath).split(File.pathSeparator)) {
String filename = FilenameUtils.getName(eachClassPath);
if (isPatchJar(filename)) {
logger.trace("classpath :" + eachClassPath);
classPathList.add(eachClassPath);
}
}
return StringUtils.join(classPathList, File.pathSeparator);
}
private boolean isUsefulForForemostReferenceProject(String path) {
return junitContext && new File(path).isDirectory()
&& path.contains(File.separator + "ngrinder-runtime" + File.separator);
}
private boolean isPatchJar(String jarFilename) {
if ("jar".equals(FilenameUtils.getExtension(jarFilename))) {
for (String jarName : patchJarList) {
if (jarFilename.contains(jarName)) {
return true;
}
}
}
return false;
}
/**
* Initialize.
*/
public void init() {
foreMostJarList.add("ngrinder-runtime");
patchJarList.add("patch");
// TODO: If we have need another jar files, we should append it here.
usefulJarList.add("grinder");
usefulJarList.add("dnsjava");
usefulJarList.add("asm");
usefulJarList.add("picocontainer");
usefulJarList.add("slf4j-api");
usefulJarList.add("json");
usefulJarList.add("logback");
usefulJarList.add("jna");
usefulJarList.add("jsr173");
usefulJarList.add("xmlbeans");
usefulJarList.add("stax-api");
usefulJarList.add("ngrinder-patch");
usefulJarList.add("junit");
usefulJarList.add("hamcrest");
uselessJarList.add("jython-2.2");
uselessJarList.add("ngrinder-core");
uselessJarList.add("ngrinder-controller");
uselessJarList.add("ngrinder-groovy");
uselessJarList.add("spring");
}
protected abstract void initMore();
private boolean isForemostJar(String jarFilename) {
if ("jar".equals(FilenameUtils.getExtension(jarFilename))) {
for (String jarName : foreMostJarList) {
if (jarFilename.contains(jarName)) {
return true;
}
}
}
return false;
}
private boolean isUsefulJar(String jarFilename) {
if (isPatchJar(jarFilename)) {
return false;
}
if (!"jar".equals(FilenameUtils.getExtension(jarFilename))) {
return false;
}
for (String jarName : uselessJarList) {
if (jarFilename.contains(jarName)) {
return false;
}
}
for (String jarName : usefulJarList) {
if (jarFilename.contains(jarName)) {
return true;
}
}
return false;
}
/**
* Construct the foremost classPath from current classLoader.
*
* @param logger logger
* @return classpath optimized for grinder.
*/
public String buildForemostClasspathBasedOnCurrentClassLoader(Logger logger) {
URL[] urLs = ((URLClassLoader) AbstractGrinderClassPathProcessor.class.getClassLoader()).getURLs();
StringBuilder builder = new StringBuilder();
for (URL each : urLs) {
builder.append(each.getFile()).append(File.pathSeparator);
}
return filterForeMostClassPath(builder.toString(), logger);
}
/**
* Construct the patch classPath from current classLoader.
*
* @param logger logger
* @return classpath optimized for grinder.
*/
public String buildPatchClasspathBasedOnCurrentClassLoader(Logger logger) {
URL[] urLs = ((URLClassLoader) AbstractGrinderClassPathProcessor.class.getClassLoader()).getURLs();
StringBuilder builder = new StringBuilder();
for (URL each : urLs) {
builder.append(each.getFile()).append(File.pathSeparator);
}
return filterPatchClassPath(builder.toString(), logger);
}
/**
* Construct classPath from current classLoader.
*
* @param logger logger
* @return classpath optimized for grinder.
*/
public String buildClasspathBasedOnCurrentClassLoader(Logger logger) {
URL[] urls = ((URLClassLoader) AbstractGrinderClassPathProcessor.class.getClassLoader()).getURLs();
StringBuilder builder = new StringBuilder();
for (URL each : urls) {
builder.append(each.getFile()).append(File.pathSeparator);
}
if (builder.length() < 300) {
// In case of the URLClassLoader is not activated, Try with system class path
final String property = System.getProperty("java.class.path", "");
for (String each : property.split(File.pathSeparator)) {
builder.append(each).append(File.pathSeparator);
}
}
return filterClassPath(builder.toString(), logger);
}
public List<String> getUsefulJarList() {
return usefulJarList;
}
public List<String> getUselessJarList() {
return uselessJarList;
}
}