Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/jorphan/org/apache/jorphan/reflect/ClassFilter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.jorphan.reflect;

/**
* filter class when visiting the search path with {@link ClassFinder}
*/
public interface ClassFilter {

boolean accept(String className);
}
145 changes: 70 additions & 75 deletions src/jorphan/org/apache/jorphan/reflect/ClassFinder.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,10 @@ private ClassFinder() {
}

/**
* Filter updates to TreeSet by only storing classes
* Filter updates by only storing classes
* that extend one of the parent classes
*
*
*/
private static class FilterTreeSet extends TreeSet<String>{
private static final long serialVersionUID = 234L;
private static class ExtendsClassFilter implements ClassFilter {

private final Class<?>[] parents; // parent classes to check
private final boolean inner; // are inner classes OK?
Expand All @@ -75,73 +72,50 @@ private static class FilterTreeSet extends TreeSet<String>{
private final transient ClassLoader contextClassLoader
= Thread.currentThread().getContextClassLoader(); // Potentially expensive; do it once

FilterTreeSet(Class<?> []parents, boolean inner, String contains, String notContains){
super();
this.parents=parents;
this.inner=inner;
this.contains=contains;
this.notContains=notContains;
ExtendsClassFilter(Class<?> []parents, boolean inner, String contains, String notContains){
this.parents = parents;
this.inner = inner;
this.contains = contains;
this.notContains = notContains;
}

/**
* Override the superclass so we only add classnames that
* meet the criteria.
*
* @param s - classname (must be a String)
* @return true if it is a new entry
*
* @see java.util.TreeSet#add(java.lang.Object)
*/
@Override
public boolean add(String s){
if (contains(s)) {
return false;// No need to check it again
}
if (contains!=null && s.indexOf(contains) == -1){
public boolean accept(String className) {

if (contains!=null && className.indexOf(contains) == -1){
return false; // It does not contain a required string
}
if (notContains!=null && s.indexOf(notContains) != -1){
if (notContains!=null && className.indexOf(notContains) != -1){
return false; // It contains a banned string
}
if ((s.indexOf('$') == -1) || inner) { // $NON-NLS-1$
if (isChildOf(parents,s, contextClassLoader)) {
return super.add(s);
if ((className.indexOf('$') == -1) || inner) { // $NON-NLS-1$
if (isChildOf(parents,className, contextClassLoader)) {
return true;
}
}
return false;
}
}

private static class AnnoFilterTreeSet extends TreeSet<String>{
private static final long serialVersionUID = 240L;


private static class AnnoClassFilter implements ClassFilter {
private final boolean inner; // are inner classes OK?

private final Class<? extends Annotation>[] annotations; // annotation classes to check
private final transient ClassLoader contextClassLoader
= Thread.currentThread().getContextClassLoader(); // Potentially expensive; do it once
AnnoFilterTreeSet(Class<? extends Annotation> []annotations, boolean inner){
super();

AnnoClassFilter(Class<? extends Annotation> []annotations, boolean inner){
this.annotations = annotations;
this.inner=inner;
this.inner = inner;
}
/**
* Override the superclass so we only add classnames that
* meet the criteria.
*
* @param s - classname (must be a String)
* @return true if it is a new entry
*
* @see java.util.TreeSet#add(java.lang.Object)
*/

@Override
public boolean add(String s){
if (contains(s)) {
return false;// No need to check it again
}
if ((s.indexOf('$') == -1) || inner) { // $NON-NLS-1$
if (hasAnnotationOnMethod(annotations,s, contextClassLoader)) {
return super.add(s);
public boolean accept(String className) {
if ((className.indexOf('$') == -1) || inner) { // $NON-NLS-1$
if (hasAnnotationOnMethod(annotations,className, contextClassLoader)) {
return true;
}
}
return false;
Expand Down Expand Up @@ -276,29 +250,45 @@ public static List<String> findClassesThatExtend(String[] searchPathsOrJars,
log.debug("contains: " + contains + " notContains: " + notContains);
}


ClassFilter filter = null;
if(annotations) {
@SuppressWarnings("unchecked") // Should only be called with classes that extend annotations
final Class<? extends Annotation>[] annoclassNames = (Class<? extends Annotation>[]) classNames;
filter = new AnnoClassFilter(annoclassNames, innerClasses);
}
else {
filter = new ExtendsClassFilter(classNames, innerClasses, contains, notContains);
}

return findClasses(searchPathsOrJars, filter);
}

public static List<String> findClasses(String[] searchPathsOrJars, ClassFilter filter) throws IOException {
if (log.isDebugEnabled()) {
log.debug("searchPathsOrJars : " + Arrays.toString(searchPathsOrJars));
}

// Find all jars in the search path
String[] strPathsOrJars = addJarsInPath(searchPathsOrJars);
for (int k = 0; k < strPathsOrJars.length; k++) {
strPathsOrJars[k] = fixPathEntry(strPathsOrJars[k]);
}

// Now eliminate any classpath entries that do not "match" the search
List<String> listPaths = getClasspathMatches(strPathsOrJars);
if (log.isDebugEnabled()) {
for (String path : listPaths) {
log.debug("listPaths : " + path);
}
}

@SuppressWarnings("unchecked") // Should only be called with classes that extend annotations
final Class<? extends Annotation>[] annoclassNames = (Class<? extends Annotation>[]) classNames;
Set<String> listClasses =
annotations ?
new AnnoFilterTreeSet(annoclassNames, innerClasses)
:
new FilterTreeSet(classNames, innerClasses, contains, notContains);

Set<String> listClasses = new TreeSet<>();
// first get all the classes
findClassesInPaths(listPaths, listClasses);
for (String path : listPaths) {
findClassesInOnePath(path, listClasses, filter);
}

if (log.isDebugEnabled()) {
log.debug("listClasses.size()="+listClasses.size());
for (String clazz : listClasses) {
Expand Down Expand Up @@ -440,10 +430,11 @@ private static String fixClassName(String strClassName) {
return strClassName;
}

private static void findClassesInOnePath(String strPath, Set<String> listClasses) throws IOException {

private static void findClassesInOnePath(String strPath, Set<String> listClasses, ClassFilter filter) throws IOException {
File file = new File(strPath);
if (file.isDirectory()) {
findClassesInPathsDir(strPath, file, listClasses);
findClassesInPathsDir(strPath, file, listClasses, filter);
} else if (file.exists()) {
ZipFile zipFile = null;
try {
Expand All @@ -452,7 +443,10 @@ private static void findClassesInOnePath(String strPath, Set<String> listClasses
while (entries.hasMoreElements()) {
String strEntry = entries.nextElement().toString();
if (strEntry.endsWith(DOT_CLASS)) {
listClasses.add(fixClassName(strEntry));
String fixedClassName = fixClassName(strEntry);
if(filter.accept(fixedClassName)) {
listClasses.add(fixedClassName);
}
}
}
} catch (IOException e) {
Expand All @@ -466,29 +460,30 @@ private static void findClassesInOnePath(String strPath, Set<String> listClasses
}
}

private static void findClassesInPaths(List<String> listPaths, Set<String> listClasses) throws IOException {
for (String path : listPaths) {
findClassesInOnePath(path, listClasses);
}
}

private static void findClassesInPathsDir(String strPathElement, File dir, Set<String> listClasses) throws IOException {
private static void findClassesInPathsDir(String strPathElement, File dir, Set<String> listClasses, ClassFilter filter) throws IOException {
String[] list = dir.list();
if(list==null) {
if(list == null) {
log.warn(dir.getAbsolutePath()+" is not a folder");
return;
}

for (String aList : list) {
File file = new File(dir, aList);
if (file.isDirectory()) {
// Recursive call
findClassesInPathsDir(strPathElement, file, listClasses);
} else if (aList.endsWith(DOT_CLASS) && file.exists() && (file.length() != 0)) {
findClassesInPathsDir(strPathElement, file, listClasses, filter);
}
else if (aList.endsWith(DOT_CLASS) && file.exists() && (file.length() != 0)) {
final String path = file.getPath();
listClasses.add(path.substring(strPathElement.length() + 1,
String className = path.substring(strPathElement.length() + 1,
path.lastIndexOf('.')) // $NON-NLS-1$
.replace(File.separator.charAt(0), '.')); // $NON-NLS-1$
.replace(File.separator.charAt(0), '.');// $NON-NLS-1$
if(filter.accept(className)) {
listClasses.add(className);
}
}
}
}

}
11 changes: 11 additions & 0 deletions test/src/org/apache/jmeter/gui/util/TestMenuFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,16 @@

package org.apache.jmeter.gui.util;

import java.awt.GraphicsEnvironment;

import org.apache.jmeter.junit.JMeterTestCase;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;

public final class TestMenuFactory extends JMeterTestCase {

private static final Logger log = LoggingManager.getLoggerForClass();

public TestMenuFactory() {
super();
}
Expand All @@ -35,6 +41,11 @@ private static void check(String s, int i) throws Exception {
}

public void testMenu() throws Exception {
if(GraphicsEnvironment.isHeadless()) {
System.out.println("Skipping test:"+getClass().getName()+"#testCloneSampler"+", cannot run in Headless mode");
log.warn("Skipping test:"+getClass().getName()+"#testCloneSampler"+", cannot run in Headless mode");
return;
}
check("menumap", MenuFactory.menuMap_size());

check("assertions", MenuFactory.assertions_size());
Expand Down
9 changes: 8 additions & 1 deletion test/src/org/apache/jmeter/junit/JMeterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package org.apache.jmeter.junit;

import java.awt.Component;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
Expand Down Expand Up @@ -129,12 +130,18 @@ public JMeterTest(String testName, Function fi) {
* Use a suite to allow the tests to be generated at run-time
*/
public static Test suite() throws Exception {
TestSuite suite = new TestSuite("JMeterTest");
if(GraphicsEnvironment.isHeadless()) {
System.out.println("Skipping test:"+JMeterTest.class.getName()+", cannot run in Headless mode");
log.warn("Skipping test:"+JMeterTest.class.getName()+", cannot run in Headless mode");
return suite;
}

// The Locale used to instantiate the GUI objects
JMeterUtils.setLocale(TEST_LOCALE);
Locale.setDefault(TEST_LOCALE);
// Needs to be done before any GUI classes are instantiated

TestSuite suite = new TestSuite("JMeterTest");
suite.addTest(new JMeterTest("readAliases"));
suite.addTest(new JMeterTest("createTitleSet"));
suite.addTest(new JMeterTest("createTagSet"));
Expand Down
Loading