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 javax.swing.JTextArea;
|
||||||
import org.apache.lucene.analysis.Analyzer;
|
import org.apache.lucene.analysis.Analyzer;
|
||||||
import org.apache.lucene.analysis.custom.CustomAnalyzer;
|
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.MessageBroker;
|
||||||
import org.apache.lucene.luke.app.desktop.components.dialog.analysis.AnalysisChainDialogFactory;
|
import org.apache.lucene.luke.app.desktop.components.dialog.analysis.AnalysisChainDialogFactory;
|
||||||
import org.apache.lucene.luke.app.desktop.components.dialog.analysis.TokenAttributeDialogFactory;
|
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.messageBroker = MessageBroker.getInstance();
|
||||||
|
|
||||||
this.analysisModel = new AnalysisFactory().newInstance();
|
this.analysisModel = new AnalysisFactory().newInstance();
|
||||||
analysisModel.createAnalyzerFromClassName(StandardAnalyzer.class.getName());
|
|
||||||
|
|
||||||
this.simpleResult = new SimpleAnalyzeResultPanelProvider(tokenAttrDialogFactory).get();
|
this.simpleResult = new SimpleAnalyzeResultPanelProvider(tokenAttrDialogFactory).get();
|
||||||
this.stepByStepResult = new StepByStepAnalyzeResultPanelProvider(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.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.BorderFactory;
|
||||||
import javax.swing.BoxLayout;
|
import javax.swing.BoxLayout;
|
||||||
import javax.swing.ButtonGroup;
|
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.app.desktop.util.StyleConstants;
|
||||||
import org.apache.lucene.luke.models.LukeException;
|
import org.apache.lucene.luke.models.LukeException;
|
||||||
import org.apache.lucene.luke.util.LoggerFactory;
|
import org.apache.lucene.luke.util.LoggerFactory;
|
||||||
import org.apache.lucene.luke.util.reflection.ClassScanner;
|
import org.apache.lucene.store.MMapDirectory;
|
||||||
import org.apache.lucene.store.FSDirectory;
|
import org.apache.lucene.store.NIOFSDirectory;
|
||||||
import org.apache.lucene.util.NamedThreadFactory;
|
import org.apache.lucene.util.NamedThreadFactory;
|
||||||
import org.apache.lucene.util.SuppressForbidden;
|
import org.apache.lucene.util.SuppressForbidden;
|
||||||
|
|
||||||
|
@ -258,16 +255,7 @@ public final class OpenIndexDialogFactory implements DialogOpener.DialogFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
private String[] supportedDirImpls() {
|
private String[] supportedDirImpls() {
|
||||||
// supports FS-based built-in implementations
|
return new String[] {MMapDirectory.class.getName(), NIOFSDirectory.class.getName()};
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private JPanel buttons() {
|
private JPanel buttons() {
|
||||||
|
|
|
@ -37,19 +37,19 @@ import javax.swing.JSeparator;
|
||||||
import javax.swing.JTextField;
|
import javax.swing.JTextField;
|
||||||
import org.apache.lucene.analysis.Analyzer;
|
import org.apache.lucene.analysis.Analyzer;
|
||||||
import org.apache.lucene.analysis.custom.CustomAnalyzer;
|
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.ComponentOperatorRegistry;
|
||||||
import org.apache.lucene.luke.app.desktop.components.TabSwitcherProxy;
|
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.components.TabbedPaneProvider;
|
||||||
import org.apache.lucene.luke.app.desktop.util.FontUtils;
|
import org.apache.lucene.luke.app.desktop.util.FontUtils;
|
||||||
import org.apache.lucene.luke.app.desktop.util.MessageUtils;
|
import org.apache.lucene.luke.app.desktop.util.MessageUtils;
|
||||||
|
import org.apache.lucene.luke.models.analysis.AnalysisFactory;
|
||||||
|
|
||||||
/** Provider of the Analyzer pane */
|
/** Provider of the Analyzer pane */
|
||||||
public final class AnalyzerPaneProvider implements AnalyzerTabOperator {
|
public final class AnalyzerPaneProvider implements AnalyzerTabOperator {
|
||||||
|
|
||||||
private final TabSwitcherProxy tabSwitcher;
|
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<>();
|
private final JList<String> charFilterList = new JList<>();
|
||||||
|
|
||||||
|
@ -59,6 +59,8 @@ public final class AnalyzerPaneProvider implements AnalyzerTabOperator {
|
||||||
|
|
||||||
public AnalyzerPaneProvider() {
|
public AnalyzerPaneProvider() {
|
||||||
this.tabSwitcher = TabSwitcherProxy.getInstance();
|
this.tabSwitcher = TabSwitcherProxy.getInstance();
|
||||||
|
this.analyzerNameLbl.setText(
|
||||||
|
new AnalysisFactory().newInstance().currentAnalyzer().getClass().getName());
|
||||||
|
|
||||||
ComponentOperatorRegistry.getInstance().register(AnalyzerTabOperator.class, this);
|
ComponentOperatorRegistry.getInstance().register(AnalyzerTabOperator.class, this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ import org.apache.lucene.util.IOUtils;
|
||||||
/** Default implementation of {@link AnalysisImpl} */
|
/** Default implementation of {@link AnalysisImpl} */
|
||||||
public final class AnalysisImpl implements Analysis {
|
public final class AnalysisImpl implements Analysis {
|
||||||
|
|
||||||
private Analyzer analyzer;
|
private Analyzer analyzer = defaultAnalyzer();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addExternalJars(List<String> jarFiles) {
|
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
|
@Override
|
||||||
public Analyzer buildCustomAnalyzer(CustomAnalyzerConfig config) {
|
public Analyzer buildCustomAnalyzer(CustomAnalyzerConfig config) {
|
||||||
Objects.requireNonNull(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);
|
assertNotNull(tokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = LukeException.class)
|
public void testAnalyze_default() {
|
||||||
public void testAnalyze_not_set() {
|
|
||||||
AnalysisImpl analysis = new AnalysisImpl();
|
AnalysisImpl analysis = new AnalysisImpl();
|
||||||
String text = "This test must fail.";
|
String text = "Apache Lucene";
|
||||||
analysis.analyze(text);
|
List<Analysis.Token> tokens = analysis.analyze(text);
|
||||||
|
assertNotNull(tokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = LukeException.class)
|
@Test(expected = LukeException.class)
|
||||||
|
|
Loading…
Reference in New Issue