mirror of https://github.com/apache/lucene.git
LUCENE-10261: clean up reflection stuff in luke module and make minor adjustments (#480)
This commit is contained in:
parent
1029651d12
commit
57f695b14d
|
@ -37,7 +37,6 @@ import javax.swing.JSplitPane;
|
|||
import javax.swing.JTextArea;
|
||||
import org.apache.lucene.analysis.Analyzer;
|
||||
import org.apache.lucene.analysis.custom.CustomAnalyzer;
|
||||
import org.apache.lucene.analysis.standard.StandardAnalyzer;
|
||||
import org.apache.lucene.luke.app.desktop.MessageBroker;
|
||||
import org.apache.lucene.luke.app.desktop.components.dialog.analysis.AnalysisChainDialogFactory;
|
||||
import org.apache.lucene.luke.app.desktop.components.dialog.analysis.TokenAttributeDialogFactory;
|
||||
|
@ -100,7 +99,6 @@ public final class AnalysisPanelProvider implements AnalysisTabOperator {
|
|||
this.messageBroker = MessageBroker.getInstance();
|
||||
|
||||
this.analysisModel = new AnalysisFactory().newInstance();
|
||||
analysisModel.createAnalyzerFromClassName(StandardAnalyzer.class.getName());
|
||||
|
||||
this.simpleResult = new SimpleAnalyzeResultPanelProvider(tokenAttrDialogFactory).get();
|
||||
this.stepByStepResult = new StepByStepAnalyzeResultPanelProvider(tokenAttrDialogFactory).get();
|
||||
|
|
|
@ -29,12 +29,9 @@ import java.lang.invoke.MethodHandles;
|
|||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.ButtonGroup;
|
||||
|
@ -59,8 +56,8 @@ import org.apache.lucene.luke.app.desktop.util.MessageUtils;
|
|||
import org.apache.lucene.luke.app.desktop.util.StyleConstants;
|
||||
import org.apache.lucene.luke.models.LukeException;
|
||||
import org.apache.lucene.luke.util.LoggerFactory;
|
||||
import org.apache.lucene.luke.util.reflection.ClassScanner;
|
||||
import org.apache.lucene.store.FSDirectory;
|
||||
import org.apache.lucene.store.MMapDirectory;
|
||||
import org.apache.lucene.store.NIOFSDirectory;
|
||||
import org.apache.lucene.util.NamedThreadFactory;
|
||||
import org.apache.lucene.util.SuppressForbidden;
|
||||
|
||||
|
@ -258,16 +255,7 @@ public final class OpenIndexDialogFactory implements DialogOpener.DialogFactory
|
|||
}
|
||||
|
||||
private String[] supportedDirImpls() {
|
||||
// supports FS-based built-in implementations
|
||||
ClassScanner scanner = new ClassScanner("org.apache.lucene.store", getClass().getClassLoader());
|
||||
Set<Class<? extends FSDirectory>> clazzSet = scanner.scanSubTypes(FSDirectory.class);
|
||||
|
||||
List<String> clazzNames = new ArrayList<>();
|
||||
clazzNames.add(FSDirectory.class.getName());
|
||||
clazzNames.addAll(clazzSet.stream().map(Class::getName).collect(Collectors.toList()));
|
||||
|
||||
String[] result = new String[clazzNames.size()];
|
||||
return clazzNames.toArray(result);
|
||||
return new String[] {MMapDirectory.class.getName(), NIOFSDirectory.class.getName()};
|
||||
}
|
||||
|
||||
private JPanel buttons() {
|
||||
|
|
|
@ -37,19 +37,19 @@ import javax.swing.JSeparator;
|
|||
import javax.swing.JTextField;
|
||||
import org.apache.lucene.analysis.Analyzer;
|
||||
import org.apache.lucene.analysis.custom.CustomAnalyzer;
|
||||
import org.apache.lucene.analysis.standard.StandardAnalyzer;
|
||||
import org.apache.lucene.luke.app.desktop.components.ComponentOperatorRegistry;
|
||||
import org.apache.lucene.luke.app.desktop.components.TabSwitcherProxy;
|
||||
import org.apache.lucene.luke.app.desktop.components.TabbedPaneProvider;
|
||||
import org.apache.lucene.luke.app.desktop.util.FontUtils;
|
||||
import org.apache.lucene.luke.app.desktop.util.MessageUtils;
|
||||
import org.apache.lucene.luke.models.analysis.AnalysisFactory;
|
||||
|
||||
/** Provider of the Analyzer pane */
|
||||
public final class AnalyzerPaneProvider implements AnalyzerTabOperator {
|
||||
|
||||
private final TabSwitcherProxy tabSwitcher;
|
||||
|
||||
private final JLabel analyzerNameLbl = new JLabel(StandardAnalyzer.class.getName());
|
||||
private final JLabel analyzerNameLbl = new JLabel();
|
||||
|
||||
private final JList<String> charFilterList = new JList<>();
|
||||
|
||||
|
@ -59,6 +59,8 @@ public final class AnalyzerPaneProvider implements AnalyzerTabOperator {
|
|||
|
||||
public AnalyzerPaneProvider() {
|
||||
this.tabSwitcher = TabSwitcherProxy.getInstance();
|
||||
this.analyzerNameLbl.setText(
|
||||
new AnalysisFactory().newInstance().currentAnalyzer().getClass().getName());
|
||||
|
||||
ComponentOperatorRegistry.getInstance().register(AnalyzerTabOperator.class, this);
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ import org.apache.lucene.util.IOUtils;
|
|||
/** Default implementation of {@link AnalysisImpl} */
|
||||
public final class AnalysisImpl implements Analysis {
|
||||
|
||||
private Analyzer analyzer;
|
||||
private Analyzer analyzer = defaultAnalyzer();
|
||||
|
||||
@Override
|
||||
public void addExternalJars(List<String> jarFiles) {
|
||||
|
@ -152,6 +152,14 @@ public final class AnalysisImpl implements Analysis {
|
|||
}
|
||||
}
|
||||
|
||||
private Analyzer defaultAnalyzer() {
|
||||
try {
|
||||
return CustomAnalyzer.builder().withTokenizer("standard").build();
|
||||
} catch (IOException e) {
|
||||
throw new LukeException("Failed to build custom analyzer.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Analyzer buildCustomAnalyzer(CustomAnalyzerConfig config) {
|
||||
Objects.requireNonNull(config);
|
||||
|
|
|
@ -1,113 +0,0 @@
|
|||
/*
|
||||
* 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.lucene.luke.util.reflection;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.lucene.luke.util.LoggerFactory;
|
||||
import org.apache.lucene.util.NamedThreadFactory;
|
||||
|
||||
/** Utility class for scanning class files in jars. */
|
||||
public class ClassScanner {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
private final String packageName;
|
||||
private final ClassLoader[] classLoaders;
|
||||
|
||||
public ClassScanner(String packageName, ClassLoader... classLoaders) {
|
||||
this.packageName = packageName;
|
||||
this.classLoaders = classLoaders;
|
||||
}
|
||||
|
||||
public <T> Set<Class<? extends T>> scanSubTypes(Class<T> superType) {
|
||||
final int numThreads = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
List<SubtypeCollector<T>> collectors = new ArrayList<>();
|
||||
for (int i = 0; i < numThreads; i++) {
|
||||
collectors.add(new SubtypeCollector<T>(superType, packageName, classLoaders));
|
||||
}
|
||||
|
||||
try {
|
||||
List<URL> urls = getJarUrls();
|
||||
for (int i = 0; i < urls.size(); i++) {
|
||||
collectors.get(i % numThreads).addUrl(urls.get(i));
|
||||
}
|
||||
|
||||
ExecutorService executorService =
|
||||
Executors.newFixedThreadPool(numThreads, new NamedThreadFactory("scanner-scan-subtypes"));
|
||||
for (SubtypeCollector<T> collector : collectors) {
|
||||
executorService.submit(collector);
|
||||
}
|
||||
|
||||
try {
|
||||
executorService.shutdown();
|
||||
executorService.awaitTermination(10, TimeUnit.SECONDS);
|
||||
} catch (
|
||||
@SuppressWarnings("unused")
|
||||
InterruptedException e) {
|
||||
} finally {
|
||||
executorService.shutdownNow();
|
||||
}
|
||||
|
||||
Set<Class<? extends T>> types = new HashSet<>();
|
||||
for (SubtypeCollector<T> collector : collectors) {
|
||||
types.addAll(collector.getTypes());
|
||||
}
|
||||
return types;
|
||||
} catch (IOException e) {
|
||||
log.error("Cannot load jar file entries", e);
|
||||
}
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
private List<URL> getJarUrls() throws IOException {
|
||||
List<URL> urls = new ArrayList<>();
|
||||
String resourceName = resourceName(packageName);
|
||||
for (ClassLoader loader : classLoaders) {
|
||||
for (Enumeration<URL> e = loader.getResources(resourceName); e.hasMoreElements(); ) {
|
||||
URL url = e.nextElement();
|
||||
// extract jar file path from the resource name
|
||||
int index = url.getPath().lastIndexOf(".jar");
|
||||
if (index > 0) {
|
||||
String path = url.getPath().substring(0, index + 4);
|
||||
urls.add(new URL(path));
|
||||
}
|
||||
}
|
||||
}
|
||||
return urls;
|
||||
}
|
||||
|
||||
private static String resourceName(String packageName) {
|
||||
if (packageName == null || packageName.equals("")) {
|
||||
return packageName;
|
||||
}
|
||||
return packageName.replace('.', '/');
|
||||
}
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
/*
|
||||
* 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.lucene.luke.util.reflection;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.net.URL;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarInputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.lucene.luke.util.LoggerFactory;
|
||||
|
||||
final class SubtypeCollector<T> implements Runnable {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
private final Set<URL> urls = new HashSet<>();
|
||||
|
||||
private final Class<T> superType;
|
||||
|
||||
private final String packageName;
|
||||
|
||||
private final ClassLoader[] classLoaders;
|
||||
|
||||
private final Set<Class<? extends T>> types = new HashSet<>();
|
||||
|
||||
SubtypeCollector(Class<T> superType, String packageName, ClassLoader... classLoaders) {
|
||||
this.superType = superType;
|
||||
this.packageName = packageName;
|
||||
this.classLoaders = classLoaders;
|
||||
}
|
||||
|
||||
void addUrl(URL url) {
|
||||
urls.add(url);
|
||||
}
|
||||
|
||||
Set<Class<? extends T>> getTypes() {
|
||||
return Set.copyOf(types);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (URL url : urls) {
|
||||
try (JarInputStream jis = new JarInputStream(url.openStream())) {
|
||||
// iterate all zip entry in the jar
|
||||
ZipEntry entry;
|
||||
while ((entry = jis.getNextEntry()) != null) {
|
||||
String name = entry.getName();
|
||||
if (name.endsWith(".class")
|
||||
&& name.indexOf('$') < 0
|
||||
&& !name.contains("package-info")
|
||||
&& !name.startsWith("META-INF")) {
|
||||
String fqcn = convertToFQCN(name);
|
||||
if (!fqcn.startsWith(packageName)) {
|
||||
continue;
|
||||
}
|
||||
for (ClassLoader cl : classLoaders) {
|
||||
try {
|
||||
Class<?> clazz = Class.forName(fqcn, false, cl);
|
||||
if (superType.isAssignableFrom(clazz) && !Objects.equals(superType, clazz)) {
|
||||
types.add(clazz.asSubclass(superType));
|
||||
}
|
||||
break;
|
||||
} catch (
|
||||
@SuppressWarnings("unused")
|
||||
Throwable e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("Cannot load jar {}", url, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String convertToFQCN(String name) {
|
||||
if (name == null || name.equals("")) {
|
||||
return name;
|
||||
}
|
||||
int index = name.lastIndexOf(".class");
|
||||
return name.replace('/', '.').substring(0, index);
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/** Utilities for reflections */
|
||||
package org.apache.lucene.luke.util.reflection;
|
|
@ -125,11 +125,11 @@ public class TestAnalysisImpl extends LuceneTestCase {
|
|||
assertNotNull(tokens);
|
||||
}
|
||||
|
||||
@Test(expected = LukeException.class)
|
||||
public void testAnalyze_not_set() {
|
||||
public void testAnalyze_default() {
|
||||
AnalysisImpl analysis = new AnalysisImpl();
|
||||
String text = "This test must fail.";
|
||||
analysis.analyze(text);
|
||||
String text = "Apache Lucene";
|
||||
List<Analysis.Token> tokens = analysis.analyze(text);
|
||||
assertNotNull(tokens);
|
||||
}
|
||||
|
||||
@Test(expected = LukeException.class)
|
||||
|
|
Loading…
Reference in New Issue