1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.ds;
17
18 import java.io.File;
19 import java.io.InputStream;
20 import java.nio.file.FileSystem;
21 import java.nio.file.FileSystems;
22 import java.nio.file.Files;
23 import java.nio.file.Path;
24 import java.util.HashSet;
25 import java.util.LinkedHashMap;
26 import java.util.List;
27 import java.util.Locale;
28 import java.util.Map;
29 import java.util.Set;
30 import java.util.stream.Collectors;
31
32 import javax.xml.parsers.DocumentBuilder;
33 import javax.xml.parsers.DocumentBuilderFactory;
34
35 import org.apache.logging.log4j.LogManager;
36 import org.apache.logging.log4j.Logger;
37 import org.codelibs.core.lang.StringUtil;
38 import org.codelibs.fess.Constants;
39 import org.codelibs.fess.helper.PluginHelper;
40 import org.codelibs.fess.util.ResourceUtil;
41 import org.w3c.dom.Document;
42 import org.w3c.dom.NamedNodeMap;
43 import org.w3c.dom.Node;
44 import org.w3c.dom.NodeList;
45
46 public class DataStoreFactory {
47 private static final Logger logger = LogManager.getLogger(DataStoreFactory.class);
48
49 protected Map<String, DataStore> dataStoreMap = new LinkedHashMap<>();
50
51 protected String[] dataStoreNames = StringUtil.EMPTY_STRINGS;
52
53 protected long lastLoadedTime = 0;
54
55 public void add(final String name, final DataStore dataStore) {
56 if (name == null || dataStore == null) {
57 throw new IllegalArgumentException("name or dataStore is null.");
58 }
59 if (logger.isDebugEnabled()) {
60 logger.debug("Loaded {}", name);
61 }
62 dataStoreMap.put(name.toLowerCase(Locale.ROOT), dataStore);
63 dataStoreMap.put(dataStore.getClass().getSimpleName().toLowerCase(Locale.ROOT), dataStore);
64 }
65
66 public DataStore getDataStore(final String name) {
67 if (name == null) {
68 return null;
69 }
70 return dataStoreMap.get(name.toLowerCase(Locale.ROOT));
71 }
72
73 public String[] getDataStoreNames() {
74 final long now = System.currentTimeMillis();
75 if (now - lastLoadedTime > 60000L) {
76 final List<String> nameList = loadDataStoreNameList();
77 dataStoreNames = nameList.toArray(n -> new String[nameList.size()]);
78 lastLoadedTime = now;
79 }
80 return dataStoreNames;
81 }
82
83 protected List<String> loadDataStoreNameList() {
84 final Set<String> nameSet = new HashSet<>();
85 final File[] jarFiles = ResourceUtil.getPluginJarFiles(PluginHelper.ArtifactType.DATA_STORE.getId());
86 for (final File jarFile : jarFiles) {
87 try (FileSystem fs = FileSystems.newFileSystem(jarFile.toPath(), ClassLoader.getSystemClassLoader())) {
88 final Path xmlPath = fs.getPath("fess_ds++.xml");
89 try (InputStream is = Files.newInputStream(xmlPath)) {
90 final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
91 factory.setFeature(org.codelibs.fess.crawler.Constants.FEATURE_SECURE_PROCESSING, true);
92 factory.setFeature(org.codelibs.fess.crawler.Constants.FEATURE_EXTERNAL_GENERAL_ENTITIES, false);
93 factory.setFeature(org.codelibs.fess.crawler.Constants.FEATURE_EXTERNAL_PARAMETER_ENTITIES, false);
94 factory.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.LOAD_EXTERNAL_DTD_FEATURE, false);
95 final DocumentBuilder builder = factory.newDocumentBuilder();
96
97 final Document doc = builder.parse(is);
98 final NodeList nodeList = doc.getElementsByTagName("component");
99 for (int i = 0; i < nodeList.getLength(); i++) {
100 final Node node = nodeList.item(i);
101 final NamedNodeMap attributes = node.getAttributes();
102 if (attributes != null) {
103 final Node classAttr = attributes.getNamedItem("class");
104 if (classAttr != null) {
105 final String value = classAttr.getNodeValue();
106 if (StringUtil.isNotBlank(value)) {
107 final String[] values = value.split("\\.");
108 nameSet.add(values[values.length - 1]);
109 }
110 }
111 }
112 }
113 }
114 } catch (final Exception e) {
115 logger.warn("Failed to load {}", jarFile.getAbsolutePath(), e);
116 }
117 }
118 return nameSet.stream().sorted().collect(Collectors.toList());
119 }
120
121 }