fix #1677 remove datastore impl
This commit is contained in:
parent
e9650b004c
commit
845e8392a2
17 changed files with 29 additions and 1933 deletions
|
@ -13,7 +13,7 @@
|
|||
* either express or implied. See the License for the specific language
|
||||
* governing permissions and limitations under the License.
|
||||
*/
|
||||
package org.codelibs.fess.ds.impl;
|
||||
package org.codelibs.fess.ds;
|
||||
|
||||
import static org.codelibs.core.stream.StreamUtil.stream;
|
||||
|
||||
|
@ -25,8 +25,7 @@ import java.util.Map;
|
|||
|
||||
import org.codelibs.core.lang.StringUtil;
|
||||
import org.codelibs.fess.Constants;
|
||||
import org.codelibs.fess.ds.DataStore;
|
||||
import org.codelibs.fess.ds.IndexUpdateCallback;
|
||||
import org.codelibs.fess.ds.callback.IndexUpdateCallback;
|
||||
import org.codelibs.fess.es.config.exentity.DataConfig;
|
||||
import org.codelibs.fess.helper.CrawlingInfoHelper;
|
||||
import org.codelibs.fess.helper.SystemHelper;
|
||||
|
@ -36,14 +35,20 @@ import org.codelibs.fess.util.GroovyUtil;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class AbstractDataStoreImpl implements DataStore {
|
||||
public abstract class AbstractDataStore implements DataStore {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(AbstractDataStoreImpl.class);
|
||||
private static final Logger logger = LoggerFactory.getLogger(AbstractDataStore.class);
|
||||
|
||||
public String mimeType = "application/datastore";
|
||||
|
||||
protected boolean alive = true;
|
||||
|
||||
public void register() {
|
||||
ComponentUtil.getDataStoreFactory().add(getName(), this);
|
||||
}
|
||||
|
||||
protected abstract String getName();
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
alive = false;
|
|
@ -17,6 +17,7 @@ package org.codelibs.fess.ds;
|
|||
|
||||
import java.util.Map;
|
||||
|
||||
import org.codelibs.fess.ds.callback.IndexUpdateCallback;
|
||||
import org.codelibs.fess.es.config.exentity.DataConfig;
|
||||
|
||||
public interface DataStore {
|
||||
|
|
|
@ -16,18 +16,27 @@
|
|||
package org.codelibs.fess.ds;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class DataStoreFactory {
|
||||
private static final Logger logger = LoggerFactory.getLogger(DataStoreFactory.class);
|
||||
|
||||
protected Map<String, DataStore> dataStoreMap = new LinkedHashMap<>();
|
||||
|
||||
public void add(final String name, final DataStore dataStore) {
|
||||
if (name == null || dataStore == null) {
|
||||
throw new IllegalArgumentException("name or dataStore is null.");
|
||||
}
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Loaded " + name);
|
||||
}
|
||||
dataStoreMap.put(name, dataStore);
|
||||
}
|
||||
|
||||
|
@ -39,6 +48,7 @@ public class DataStoreFactory {
|
|||
final Set<String> nameSet = dataStoreMap.keySet();
|
||||
final List<String> nameList = new ArrayList<>();
|
||||
nameList.addAll(nameSet);
|
||||
Collections.sort(nameList);
|
||||
return nameList;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* either express or implied. See the License for the specific language
|
||||
* governing permissions and limitations under the License.
|
||||
*/
|
||||
package org.codelibs.fess.ds.impl;
|
||||
package org.codelibs.fess.ds.callback;
|
||||
|
||||
import static org.codelibs.core.stream.StreamUtil.stream;
|
||||
|
||||
|
@ -40,7 +40,6 @@ import org.codelibs.fess.crawler.processor.impl.DefaultResponseProcessor;
|
|||
import org.codelibs.fess.crawler.rule.Rule;
|
||||
import org.codelibs.fess.crawler.rule.RuleManager;
|
||||
import org.codelibs.fess.crawler.transformer.Transformer;
|
||||
import org.codelibs.fess.ds.IndexUpdateCallback;
|
||||
import org.codelibs.fess.es.client.FessEsClient;
|
||||
import org.codelibs.fess.exception.DataStoreCrawlingException;
|
||||
import org.codelibs.fess.helper.IndexingHelper;
|
||||
|
@ -67,8 +66,8 @@ public class FileListIndexUpdateCallbackImpl implements IndexUpdateCallback {
|
|||
|
||||
private int executorTerminationTimeout = 300;
|
||||
|
||||
protected FileListIndexUpdateCallbackImpl(final IndexUpdateCallback indexUpdateCallback,
|
||||
final CrawlerClientFactory crawlerClientFactory, final int nThreads) {
|
||||
public FileListIndexUpdateCallbackImpl(final IndexUpdateCallback indexUpdateCallback, final CrawlerClientFactory crawlerClientFactory,
|
||||
final int nThreads) {
|
||||
this.indexUpdateCallback = indexUpdateCallback;
|
||||
this.crawlerClientFactory = crawlerClientFactory;
|
||||
executor = newFixedThreadPool(nThreads < 1 ? 1 : nThreads);
|
|
@ -13,7 +13,7 @@
|
|||
* either express or implied. See the License for the specific language
|
||||
* governing permissions and limitations under the License.
|
||||
*/
|
||||
package org.codelibs.fess.ds;
|
||||
package org.codelibs.fess.ds.callback;
|
||||
|
||||
import java.util.Map;
|
||||
|
|
@ -13,14 +13,13 @@
|
|||
* either express or implied. See the License for the specific language
|
||||
* governing permissions and limitations under the License.
|
||||
*/
|
||||
package org.codelibs.fess.ds.impl;
|
||||
package org.codelibs.fess.ds.callback;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.codelibs.fess.ds.IndexUpdateCallback;
|
||||
import org.codelibs.fess.es.client.FessEsClient;
|
||||
import org.codelibs.fess.exception.DataStoreException;
|
||||
import org.codelibs.fess.helper.CrawlingInfoHelper;
|
||||
|
@ -51,7 +50,7 @@ public class IndexUpdateCallbackImpl implements IndexUpdateCallback {
|
|||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.codelibs.fess.ds.impl.IndexUpdateCallback#store(java.util.Map)
|
||||
* @see org.codelibs.fess.ds.callback.IndexUpdateCallback#store(java.util.Map)
|
||||
*/
|
||||
@Override
|
||||
public void store(final Map<String, String> paramMap, final Map<String, Object> dataMap) {
|
|
@ -1,429 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012-2018 CodeLibs Project and the Others.
|
||||
*
|
||||
* 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 org.codelibs.fess.ds.impl;
|
||||
|
||||
import static org.codelibs.core.stream.StreamUtil.stream;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
import org.codelibs.core.io.CloseableUtil;
|
||||
import org.codelibs.core.lang.StringUtil;
|
||||
import org.codelibs.fess.Constants;
|
||||
import org.codelibs.fess.app.service.FailureUrlService;
|
||||
import org.codelibs.fess.crawler.exception.CrawlingAccessException;
|
||||
import org.codelibs.fess.crawler.exception.MultipleCrawlingAccessException;
|
||||
import org.codelibs.fess.ds.IndexUpdateCallback;
|
||||
import org.codelibs.fess.es.config.exentity.DataConfig;
|
||||
import org.codelibs.fess.exception.DataStoreCrawlingException;
|
||||
import org.codelibs.fess.exception.DataStoreException;
|
||||
import org.codelibs.fess.util.ComponentUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.orangesignal.csv.CsvConfig;
|
||||
import com.orangesignal.csv.CsvReader;
|
||||
|
||||
public class CsvDataStoreImpl extends AbstractDataStoreImpl {
|
||||
private static final Logger logger = LoggerFactory.getLogger(CsvDataStoreImpl.class);
|
||||
|
||||
protected static final String ESCAPE_CHARACTER_PARAM = "escapeCharacter";
|
||||
|
||||
protected static final String QUOTE_CHARACTER_PARAM = "quoteCharacter";
|
||||
|
||||
protected static final String SEPARATOR_CHARACTER_PARAM = "separatorCharacter";
|
||||
|
||||
protected static final String SKIP_LINES_PARAM = "skipLines";
|
||||
|
||||
protected static final String IGNORE_LINE_PATTERNS_PARAM = "ignoreLinePatterns";
|
||||
|
||||
protected static final String IGNORE_EMPTY_LINES_PARAM = "ignoreEmptyLines";
|
||||
|
||||
protected static final String IGNORE_TRAILING_WHITESPACES_PARAM = "ignoreTrailingWhitespaces";
|
||||
|
||||
protected static final String IGNORE_LEADING_WHITESPACES_PARAM = "ignoreLeadingWhitespaces";
|
||||
|
||||
protected static final String NULL_STRING_PARAM = "nullString";
|
||||
|
||||
protected static final String BREAK_STRING_PARAM = "breakString";
|
||||
|
||||
protected static final String ESCAPE_DISABLED_PARAM = "escapeDisabled";
|
||||
|
||||
protected static final String QUOTE_DISABLED_PARAM = "quoteDisabled";
|
||||
|
||||
protected static final String CSV_FILE_ENCODING_PARAM = "fileEncoding";
|
||||
|
||||
protected static final String CSV_FILES_PARAM = "files";
|
||||
|
||||
protected static final String CSV_DIRS_PARAM = "directories";
|
||||
|
||||
protected static final String CELL_PREFIX = "cell";
|
||||
|
||||
public String[] csvFileSuffixs = new String[] { ".csv", ".tsv" };
|
||||
|
||||
protected List<File> getCsvFileList(final Map<String, String> paramMap) {
|
||||
String value = paramMap.get(CSV_FILES_PARAM);
|
||||
final List<File> fileList = new ArrayList<>();
|
||||
if (StringUtil.isBlank(value)) {
|
||||
value = paramMap.get(CSV_DIRS_PARAM);
|
||||
if (StringUtil.isBlank(value)) {
|
||||
throw new DataStoreException(CSV_FILES_PARAM + " and " + CSV_DIRS_PARAM + " are blank.");
|
||||
}
|
||||
logger.info(CSV_DIRS_PARAM + "=" + value);
|
||||
final String[] values = value.split(",");
|
||||
for (final String path : values) {
|
||||
final File dir = new File(path);
|
||||
if (dir.isDirectory()) {
|
||||
stream(dir.listFiles()).of(
|
||||
stream -> stream.filter(f -> isCsvFile(f.getParentFile(), f.getName()))
|
||||
.sorted((f1, f2) -> (int) (f1.lastModified() - f2.lastModified())).forEach(f -> fileList.add(f)));
|
||||
} else {
|
||||
logger.warn(path + " is not a directory.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.info(CSV_FILES_PARAM + "=" + value);
|
||||
final String[] values = value.split(",");
|
||||
for (final String path : values) {
|
||||
final File file = new File(path);
|
||||
if (file.isFile() && isCsvFile(file.getParentFile(), file.getName())) {
|
||||
fileList.add(file);
|
||||
} else {
|
||||
logger.warn(path + " is not found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fileList.isEmpty() && logger.isDebugEnabled()) {
|
||||
logger.debug("No csv files in " + value);
|
||||
}
|
||||
return fileList;
|
||||
}
|
||||
|
||||
protected boolean isCsvFile(final File parentFile, final String filename) {
|
||||
final String name = filename.toLowerCase(Locale.ROOT);
|
||||
for (final String suffix : csvFileSuffixs) {
|
||||
if (name.endsWith(suffix)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected String getCsvFileEncoding(final Map<String, String> paramMap) {
|
||||
final String value = paramMap.get(CSV_FILE_ENCODING_PARAM);
|
||||
if (StringUtil.isBlank(value)) {
|
||||
return Constants.UTF_8;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
protected boolean hasHeaderLine(final Map<String, String> paramMap) {
|
||||
final String value = paramMap.get("hasHeaderLine");
|
||||
if (StringUtil.isBlank(value)) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return Boolean.parseBoolean(value);
|
||||
} catch (final Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void storeData(final DataConfig dataConfig, final IndexUpdateCallback callback, final Map<String, String> paramMap,
|
||||
final Map<String, String> scriptMap, final Map<String, Object> defaultDataMap) {
|
||||
|
||||
final long readInterval = getReadInterval(paramMap);
|
||||
|
||||
final List<File> csvFileList = getCsvFileList(paramMap);
|
||||
if (csvFileList.isEmpty()) {
|
||||
logger.warn("No CSV file.");
|
||||
return;
|
||||
}
|
||||
|
||||
final String csvFileEncoding = getCsvFileEncoding(paramMap);
|
||||
final boolean hasHeaderLine = hasHeaderLine(paramMap);
|
||||
final CsvConfig csvConfig = buildCsvConfig(paramMap);
|
||||
|
||||
for (final File csvFile : csvFileList) {
|
||||
processCsv(dataConfig, callback, paramMap, scriptMap, defaultDataMap, csvConfig, csvFile, readInterval, csvFileEncoding,
|
||||
hasHeaderLine);
|
||||
}
|
||||
}
|
||||
|
||||
protected void processCsv(final DataConfig dataConfig, final IndexUpdateCallback callback, final Map<String, String> paramMap,
|
||||
final Map<String, String> scriptMap, final Map<String, Object> defaultDataMap, final CsvConfig csvConfig, final File csvFile,
|
||||
final long readInterval, final String csvFileEncoding, final boolean hasHeaderLine) {
|
||||
logger.info("Loading " + csvFile.getAbsolutePath());
|
||||
CsvReader csvReader = null;
|
||||
try {
|
||||
csvReader = new CsvReader(new BufferedReader(new InputStreamReader(new FileInputStream(csvFile), csvFileEncoding)), csvConfig);
|
||||
List<String> headerList = null;
|
||||
if (hasHeaderLine) {
|
||||
headerList = csvReader.readValues();
|
||||
}
|
||||
List<String> list;
|
||||
boolean loop = true;
|
||||
while ((list = csvReader.readValues()) != null && loop && alive) {
|
||||
final Map<String, Object> dataMap = new HashMap<>();
|
||||
dataMap.putAll(defaultDataMap);
|
||||
final Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.putAll(paramMap);
|
||||
resultMap.put("csvfile", csvFile.getAbsolutePath());
|
||||
resultMap.put("csvfilename", csvFile.getName());
|
||||
resultMap.put("crawlingConfig", dataConfig);
|
||||
boolean foundValues = false;
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
String key = null;
|
||||
String value = list.get(i);
|
||||
if (value == null) {
|
||||
value = StringUtil.EMPTY;
|
||||
}
|
||||
if (StringUtil.isNotBlank(value)) {
|
||||
foundValues = true;
|
||||
}
|
||||
if (headerList != null && headerList.size() > i) {
|
||||
key = headerList.get(i);
|
||||
if (StringUtil.isNotBlank(key)) {
|
||||
resultMap.put(key, value);
|
||||
}
|
||||
}
|
||||
key = CELL_PREFIX + Integer.toString(i + 1);
|
||||
resultMap.put(key, value);
|
||||
}
|
||||
if (!foundValues) {
|
||||
logger.debug("No data in line: {}", resultMap);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
for (final Map.Entry<String, Object> entry : resultMap.entrySet()) {
|
||||
logger.debug(entry.getKey() + "=" + entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
final Map<String, Object> crawlingContext = new HashMap<>();
|
||||
crawlingContext.put("doc", dataMap);
|
||||
resultMap.put("crawlingContext", crawlingContext);
|
||||
for (final Map.Entry<String, String> entry : scriptMap.entrySet()) {
|
||||
final Object convertValue = convertValue(entry.getValue(), resultMap);
|
||||
if (convertValue != null) {
|
||||
dataMap.put(entry.getKey(), convertValue);
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
for (final Map.Entry<String, Object> entry : dataMap.entrySet()) {
|
||||
logger.debug(entry.getKey() + "=" + entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
callback.store(paramMap, dataMap);
|
||||
} catch (final CrawlingAccessException e) {
|
||||
logger.warn("Crawling Access Exception at : " + dataMap, e);
|
||||
|
||||
Throwable target = e;
|
||||
if (target instanceof MultipleCrawlingAccessException) {
|
||||
final Throwable[] causes = ((MultipleCrawlingAccessException) target).getCauses();
|
||||
if (causes.length > 0) {
|
||||
target = causes[causes.length - 1];
|
||||
}
|
||||
}
|
||||
|
||||
String errorName;
|
||||
final Throwable cause = target.getCause();
|
||||
if (cause != null) {
|
||||
errorName = cause.getClass().getCanonicalName();
|
||||
} else {
|
||||
errorName = target.getClass().getCanonicalName();
|
||||
}
|
||||
|
||||
String url;
|
||||
if (target instanceof DataStoreCrawlingException) {
|
||||
final DataStoreCrawlingException dce = (DataStoreCrawlingException) target;
|
||||
url = dce.getUrl();
|
||||
if (dce.aborted()) {
|
||||
loop = false;
|
||||
}
|
||||
} else {
|
||||
url = csvFile.getAbsolutePath() + ":" + csvReader.getLineNumber();
|
||||
}
|
||||
final FailureUrlService failureUrlService = ComponentUtil.getComponent(FailureUrlService.class);
|
||||
failureUrlService.store(dataConfig, errorName, url, target);
|
||||
} catch (final Throwable t) {
|
||||
logger.warn("Crawling Access Exception at : " + dataMap, t);
|
||||
final String url = csvFile.getAbsolutePath() + ":" + csvReader.getLineNumber();
|
||||
final FailureUrlService failureUrlService = ComponentUtil.getComponent(FailureUrlService.class);
|
||||
failureUrlService.store(dataConfig, t.getClass().getCanonicalName(), url, t);
|
||||
}
|
||||
|
||||
if (readInterval > 0) {
|
||||
sleep(readInterval);
|
||||
}
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
throw new DataStoreException("Failed to crawl data when reading csv file.", e);
|
||||
} finally {
|
||||
CloseableUtil.closeQuietly(csvReader);
|
||||
}
|
||||
}
|
||||
|
||||
protected CsvConfig buildCsvConfig(final Map<String, String> paramMap) {
|
||||
final CsvConfig csvConfig = new CsvConfig();
|
||||
|
||||
if (paramMap.containsKey(SEPARATOR_CHARACTER_PARAM)) {
|
||||
final String value = paramMap.get(SEPARATOR_CHARACTER_PARAM);
|
||||
if (StringUtil.isNotBlank(value)) {
|
||||
try {
|
||||
csvConfig.setSeparator(StringEscapeUtils.unescapeJava(value).charAt(0));
|
||||
} catch (final Exception e) {
|
||||
logger.warn("Failed to load " + SEPARATOR_CHARACTER_PARAM, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (paramMap.containsKey(QUOTE_CHARACTER_PARAM)) {
|
||||
final String value = paramMap.get(QUOTE_CHARACTER_PARAM);
|
||||
if (StringUtil.isNotBlank(value)) {
|
||||
try {
|
||||
csvConfig.setQuote(value.charAt(0));
|
||||
} catch (final Exception e) {
|
||||
logger.warn("Failed to load " + QUOTE_CHARACTER_PARAM, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (paramMap.containsKey(ESCAPE_CHARACTER_PARAM)) {
|
||||
final String value = paramMap.get(ESCAPE_CHARACTER_PARAM);
|
||||
if (StringUtil.isNotBlank(value)) {
|
||||
try {
|
||||
csvConfig.setEscape(value.charAt(0));
|
||||
} catch (final Exception e) {
|
||||
logger.warn("Failed to load " + ESCAPE_CHARACTER_PARAM, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (paramMap.containsKey(QUOTE_DISABLED_PARAM)) {
|
||||
final String value = paramMap.get(QUOTE_DISABLED_PARAM);
|
||||
if (StringUtil.isNotBlank(value)) {
|
||||
try {
|
||||
// デフォルトでは無効となっている囲み文字を有効にします。
|
||||
csvConfig.setQuoteDisabled(Boolean.parseBoolean(value));
|
||||
} catch (final Exception e) {
|
||||
logger.warn("Failed to load " + QUOTE_DISABLED_PARAM, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (paramMap.containsKey(ESCAPE_DISABLED_PARAM)) {
|
||||
final String value = paramMap.get(ESCAPE_DISABLED_PARAM);
|
||||
if (StringUtil.isNotBlank(value)) {
|
||||
try {
|
||||
// デフォルトでは無効となっているエスケープ文字を有効にします。
|
||||
csvConfig.setEscapeDisabled(Boolean.parseBoolean(value));
|
||||
} catch (final Exception e) {
|
||||
logger.warn("Failed to load " + ESCAPE_DISABLED_PARAM, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (paramMap.containsKey(BREAK_STRING_PARAM)) {
|
||||
final String value = paramMap.get(BREAK_STRING_PARAM);
|
||||
if (StringUtil.isNotBlank(value)) {
|
||||
// 項目値中の改行を \n で置換えます。
|
||||
csvConfig.setBreakString(value);
|
||||
}
|
||||
}
|
||||
|
||||
if (paramMap.containsKey(NULL_STRING_PARAM)) {
|
||||
final String value = paramMap.get(NULL_STRING_PARAM);
|
||||
if (StringUtil.isNotBlank(value)) {
|
||||
// null 値扱いする文字列を指定します。
|
||||
csvConfig.setNullString(value);
|
||||
}
|
||||
}
|
||||
|
||||
if (paramMap.containsKey(IGNORE_LEADING_WHITESPACES_PARAM)) {
|
||||
final String value = paramMap.get(IGNORE_LEADING_WHITESPACES_PARAM);
|
||||
if (StringUtil.isNotBlank(value)) {
|
||||
try {
|
||||
// 項目値前のホワイトスペースを除去します。
|
||||
csvConfig.setIgnoreLeadingWhitespaces(Boolean.parseBoolean(value));
|
||||
} catch (final Exception e) {
|
||||
logger.warn("Failed to load " + IGNORE_LEADING_WHITESPACES_PARAM, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (paramMap.containsKey(IGNORE_TRAILING_WHITESPACES_PARAM)) {
|
||||
final String value = paramMap.get(IGNORE_TRAILING_WHITESPACES_PARAM);
|
||||
if (StringUtil.isNotBlank(value)) {
|
||||
try {
|
||||
// 項目値後のホワイトスペースを除去します。
|
||||
csvConfig.setIgnoreTrailingWhitespaces(Boolean.parseBoolean(value));
|
||||
} catch (final Exception e) {
|
||||
logger.warn("Failed to load " + IGNORE_TRAILING_WHITESPACES_PARAM, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (paramMap.containsKey(IGNORE_EMPTY_LINES_PARAM)) {
|
||||
final String value = paramMap.get(IGNORE_EMPTY_LINES_PARAM);
|
||||
if (StringUtil.isNotBlank(value)) {
|
||||
try {
|
||||
// 空行を無視するようにします。
|
||||
csvConfig.setIgnoreEmptyLines(Boolean.parseBoolean(value));
|
||||
} catch (final Exception e) {
|
||||
logger.warn("Failed to load " + IGNORE_EMPTY_LINES_PARAM, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (paramMap.containsKey(IGNORE_LINE_PATTERNS_PARAM)) {
|
||||
final String value = paramMap.get(IGNORE_LINE_PATTERNS_PARAM);
|
||||
if (StringUtil.isNotBlank(value)) {
|
||||
// 正規表現による無視する行パターンを設定します。(この例では # で始まる行)
|
||||
csvConfig.setIgnoreLinePatterns(Pattern.compile(value));
|
||||
}
|
||||
}
|
||||
|
||||
if (paramMap.containsKey(SKIP_LINES_PARAM)) {
|
||||
final String value = paramMap.get(SKIP_LINES_PARAM);
|
||||
if (StringUtil.isNotBlank(value)) {
|
||||
try {
|
||||
// 最初の1行目をスキップして読込みます。
|
||||
csvConfig.setSkipLines(Integer.parseInt(value));
|
||||
} catch (final Exception e) {
|
||||
logger.warn("Failed to load " + SKIP_LINES_PARAM, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return csvConfig;
|
||||
}
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012-2018 CodeLibs Project and the Others.
|
||||
*
|
||||
* 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 org.codelibs.fess.ds.impl;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
|
||||
import org.codelibs.fess.Constants;
|
||||
import org.codelibs.fess.crawler.client.CrawlerClientFactory;
|
||||
import org.codelibs.fess.ds.IndexUpdateCallback;
|
||||
import org.codelibs.fess.es.config.exentity.DataConfig;
|
||||
import org.codelibs.fess.exception.DataStoreException;
|
||||
import org.codelibs.fess.util.ComponentUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.orangesignal.csv.CsvConfig;
|
||||
|
||||
public class CsvListDataStoreImpl extends CsvDataStoreImpl {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(CsvListDataStoreImpl.class);
|
||||
|
||||
public boolean deleteProcessedFile = true;
|
||||
|
||||
public long csvFileTimestampMargin = 60 * 1000L;// 1min
|
||||
|
||||
public boolean ignoreDataStoreException = true;
|
||||
|
||||
@Override
|
||||
protected boolean isCsvFile(final File parentFile, final String filename) {
|
||||
if (super.isCsvFile(parentFile, filename)) {
|
||||
final File file = new File(parentFile, filename);
|
||||
final long now = System.currentTimeMillis();
|
||||
return now - file.lastModified() > csvFileTimestampMargin;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void storeData(final DataConfig dataConfig, final IndexUpdateCallback callback, final Map<String, String> paramMap,
|
||||
final Map<String, String> scriptMap, final Map<String, Object> defaultDataMap) {
|
||||
int nThreads = 1;
|
||||
if (paramMap.containsKey(Constants.NUM_OF_THREADS)) {
|
||||
try {
|
||||
nThreads = Integer.parseInt(paramMap.get(Constants.NUM_OF_THREADS));
|
||||
} catch (final NumberFormatException e) {
|
||||
logger.warn(Constants.NUM_OF_THREADS + " is not int value.", e);
|
||||
}
|
||||
}
|
||||
final CrawlerClientFactory crawlerClientFactory = ComponentUtil.getCrawlerClientFactory();
|
||||
dataConfig.initializeClientFactory(crawlerClientFactory);
|
||||
try {
|
||||
final FileListIndexUpdateCallbackImpl fileListIndexUpdateCallback =
|
||||
new FileListIndexUpdateCallbackImpl(callback, crawlerClientFactory, nThreads);
|
||||
super.storeData(dataConfig, fileListIndexUpdateCallback, paramMap, scriptMap, defaultDataMap);
|
||||
fileListIndexUpdateCallback.commit();
|
||||
} catch (final Exception e) {
|
||||
throw new DataStoreException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processCsv(final DataConfig dataConfig, final IndexUpdateCallback callback, final Map<String, String> paramMap,
|
||||
final Map<String, String> scriptMap, final Map<String, Object> defaultDataMap, final CsvConfig csvConfig, final File csvFile,
|
||||
final long readInterval, final String csvFileEncoding, final boolean hasHeaderLine) {
|
||||
try {
|
||||
super.processCsv(dataConfig, callback, paramMap, scriptMap, defaultDataMap, csvConfig, csvFile, readInterval, csvFileEncoding,
|
||||
hasHeaderLine);
|
||||
|
||||
// delete csv file
|
||||
if (deleteProcessedFile && !csvFile.delete()) {
|
||||
logger.warn("Failed to delete {}", csvFile.getAbsolutePath());
|
||||
}
|
||||
} catch (final DataStoreException e) {
|
||||
if (ignoreDataStoreException) {
|
||||
logger.error("Failed to process " + csvFile.getAbsolutePath(), e);
|
||||
// rename csv file, or delete it if failed
|
||||
if (!csvFile.renameTo(new File(csvFile.getParent(), csvFile.getName() + ".txt")) && !csvFile.delete()) {
|
||||
logger.warn("Failed to delete {}", csvFile.getAbsolutePath());
|
||||
}
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,284 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012-2018 CodeLibs Project and the Others.
|
||||
*
|
||||
* 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 org.codelibs.fess.ds.impl;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.ResultSetMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.codelibs.core.lang.StringUtil;
|
||||
import org.codelibs.fess.app.service.FailureUrlService;
|
||||
import org.codelibs.fess.crawler.exception.CrawlingAccessException;
|
||||
import org.codelibs.fess.crawler.exception.MultipleCrawlingAccessException;
|
||||
import org.codelibs.fess.ds.IndexUpdateCallback;
|
||||
import org.codelibs.fess.es.config.exentity.DataConfig;
|
||||
import org.codelibs.fess.exception.DataStoreCrawlingException;
|
||||
import org.codelibs.fess.exception.DataStoreException;
|
||||
import org.codelibs.fess.exception.FessSystemException;
|
||||
import org.codelibs.fess.util.ComponentUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class DatabaseDataStoreImpl extends AbstractDataStoreImpl {
|
||||
private static final Logger logger = LoggerFactory.getLogger(DatabaseDataStoreImpl.class);
|
||||
|
||||
private static final String SQL_PARAM = "sql";
|
||||
|
||||
private static final String URL_PARAM = "url";
|
||||
|
||||
private static final String PASSWORD_PARAM = "password";
|
||||
|
||||
private static final String USERNAME_PARAM = "username";
|
||||
|
||||
private static final String DRIVER_PARAM = "driver";
|
||||
|
||||
protected String getDriverClass(final Map<String, String> paramMap) {
|
||||
final String driverName = paramMap.get(DRIVER_PARAM);
|
||||
if (StringUtil.isBlank(driverName)) {
|
||||
throw new DataStoreException("JDBC driver is null");
|
||||
}
|
||||
return driverName;
|
||||
}
|
||||
|
||||
protected String getUsername(final Map<String, String> paramMap) {
|
||||
return paramMap.get(USERNAME_PARAM);
|
||||
}
|
||||
|
||||
protected String getPassword(final Map<String, String> paramMap) {
|
||||
return paramMap.get(PASSWORD_PARAM);
|
||||
}
|
||||
|
||||
protected String getUrl(final Map<String, String> paramMap) {
|
||||
return paramMap.get(URL_PARAM);
|
||||
}
|
||||
|
||||
protected String getSql(final Map<String, String> paramMap) {
|
||||
final String sql = paramMap.get(SQL_PARAM);
|
||||
if (StringUtil.isBlank(sql)) {
|
||||
throw new DataStoreException("sql is null");
|
||||
}
|
||||
return sql;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void storeData(final DataConfig config, final IndexUpdateCallback callback, final Map<String, String> paramMap,
|
||||
final Map<String, String> scriptMap, final Map<String, Object> defaultDataMap) {
|
||||
|
||||
final long readInterval = getReadInterval(paramMap);
|
||||
|
||||
Connection con = null;
|
||||
Statement stmt = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
Class.forName(getDriverClass(paramMap));
|
||||
|
||||
final String jdbcUrl = getUrl(paramMap);
|
||||
final String username = getUsername(paramMap);
|
||||
final String password = getPassword(paramMap);
|
||||
if (StringUtil.isNotEmpty(username)) {
|
||||
con = DriverManager.getConnection(jdbcUrl, username, password);
|
||||
} else {
|
||||
con = DriverManager.getConnection(jdbcUrl);
|
||||
}
|
||||
|
||||
final String sql = getSql(paramMap);
|
||||
stmt = con.createStatement();
|
||||
rs = stmt.executeQuery(sql); // SQL generated by an administrator
|
||||
boolean loop = true;
|
||||
while (rs.next() && loop && alive) {
|
||||
final Map<String, Object> dataMap = new HashMap<>();
|
||||
dataMap.putAll(defaultDataMap);
|
||||
final Map<String, Object> crawlingContext = new HashMap<>();
|
||||
crawlingContext.put("doc", dataMap);
|
||||
for (final Map.Entry<String, String> entry : scriptMap.entrySet()) {
|
||||
final Object convertValue =
|
||||
convertValue(entry.getValue(), new ResultSetParamMap(config, crawlingContext, rs, paramMap));
|
||||
if (convertValue != null) {
|
||||
dataMap.put(entry.getKey(), convertValue);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
callback.store(paramMap, dataMap);
|
||||
} catch (final CrawlingAccessException e) {
|
||||
logger.warn("Crawling Access Exception at : " + dataMap, e);
|
||||
|
||||
Throwable target = e;
|
||||
if (target instanceof MultipleCrawlingAccessException) {
|
||||
final Throwable[] causes = ((MultipleCrawlingAccessException) target).getCauses();
|
||||
if (causes.length > 0) {
|
||||
target = causes[causes.length - 1];
|
||||
}
|
||||
}
|
||||
|
||||
String errorName;
|
||||
final Throwable cause = target.getCause();
|
||||
if (cause != null) {
|
||||
errorName = cause.getClass().getCanonicalName();
|
||||
} else {
|
||||
errorName = target.getClass().getCanonicalName();
|
||||
}
|
||||
|
||||
String url;
|
||||
if (target instanceof DataStoreCrawlingException) {
|
||||
final DataStoreCrawlingException dce = (DataStoreCrawlingException) target;
|
||||
url = dce.getUrl();
|
||||
if (dce.aborted()) {
|
||||
loop = false;
|
||||
}
|
||||
} else {
|
||||
url = sql + ":" + rs.getRow();
|
||||
}
|
||||
final FailureUrlService failureUrlService = ComponentUtil.getComponent(FailureUrlService.class);
|
||||
failureUrlService.store(config, errorName, url, target);
|
||||
} catch (final Throwable t) {
|
||||
logger.warn("Crawling Access Exception at : " + dataMap, t);
|
||||
final String url = sql + ":" + rs.getRow();
|
||||
final FailureUrlService failureUrlService = ComponentUtil.getComponent(FailureUrlService.class);
|
||||
failureUrlService.store(config, t.getClass().getCanonicalName(), url, t);
|
||||
}
|
||||
|
||||
if (readInterval > 0) {
|
||||
sleep(readInterval);
|
||||
}
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
throw new DataStoreException("Failed to crawl data in DB.", e);
|
||||
} finally {
|
||||
try {
|
||||
if (rs != null) {
|
||||
rs.close();
|
||||
}
|
||||
} catch (final SQLException e) {
|
||||
logger.warn("Failed to close a result set.", e);
|
||||
} finally {
|
||||
try {
|
||||
if (stmt != null) {
|
||||
stmt.close();
|
||||
}
|
||||
} catch (final SQLException e) {
|
||||
logger.warn("Failed to close a statement.", e);
|
||||
} finally {
|
||||
try {
|
||||
if (con != null) {
|
||||
con.close();
|
||||
}
|
||||
} catch (final SQLException e) {
|
||||
logger.warn("Failed to close a db connection.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected static class ResultSetParamMap implements Map<String, Object> {
|
||||
private final Map<String, Object> paramMap = new HashMap<>();
|
||||
|
||||
public ResultSetParamMap(final DataConfig config, final Map<String, Object> crawlingContext, final ResultSet resultSet,
|
||||
final Map<String, String> paramMap) {
|
||||
this.paramMap.putAll(paramMap);
|
||||
this.paramMap.put("crawlingConfig", config);
|
||||
this.paramMap.put("crawlingContext", crawlingContext);
|
||||
|
||||
try {
|
||||
final ResultSetMetaData metaData = resultSet.getMetaData();
|
||||
final int columnCount = metaData.getColumnCount();
|
||||
for (int i = 0; i < columnCount; i++) {
|
||||
try {
|
||||
final String label = metaData.getColumnLabel(i + 1);
|
||||
final String value = resultSet.getString(i + 1);
|
||||
this.paramMap.put(label, value);
|
||||
} catch (final SQLException e) {
|
||||
logger.warn("Failed to parse data in a result set. The column is " + (i + 1) + ".", e);
|
||||
}
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
throw new FessSystemException("Failed to access meta data.", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
paramMap.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(final Object key) {
|
||||
return paramMap.containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(final Object value) {
|
||||
return paramMap.containsValue(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<java.util.Map.Entry<String, Object>> entrySet() {
|
||||
return paramMap.entrySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(final Object key) {
|
||||
return paramMap.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return paramMap.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> keySet() {
|
||||
return paramMap.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object put(final String key, final Object value) {
|
||||
return paramMap.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(final Map<? extends String, ? extends Object> m) {
|
||||
paramMap.putAll(m);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object remove(final Object key) {
|
||||
return paramMap.remove(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return paramMap.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Object> values() {
|
||||
return paramMap.values();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,258 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012-2018 CodeLibs Project and the Others.
|
||||
*
|
||||
* 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 org.codelibs.fess.ds.impl;
|
||||
|
||||
import static org.codelibs.core.stream.StreamUtil.split;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.codelibs.core.lang.StringUtil;
|
||||
import org.codelibs.fess.Constants;
|
||||
import org.codelibs.fess.app.service.FailureUrlService;
|
||||
import org.codelibs.fess.crawler.exception.CrawlingAccessException;
|
||||
import org.codelibs.fess.crawler.exception.MultipleCrawlingAccessException;
|
||||
import org.codelibs.fess.ds.IndexUpdateCallback;
|
||||
import org.codelibs.fess.es.config.exentity.DataConfig;
|
||||
import org.codelibs.fess.exception.DataStoreCrawlingException;
|
||||
import org.codelibs.fess.exception.DataStoreException;
|
||||
import org.codelibs.fess.util.ComponentUtil;
|
||||
import org.elasticsearch.action.bulk.BulkRequestBuilder;
|
||||
import org.elasticsearch.action.bulk.BulkResponse;
|
||||
import org.elasticsearch.action.search.SearchRequestBuilder;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.transport.TransportAddress;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.search.SearchHits;
|
||||
import org.elasticsearch.transport.client.PreBuiltTransportClient;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class EsDataStoreImpl extends AbstractDataStoreImpl {
|
||||
private static final String PREFERENCE = "preference";
|
||||
|
||||
private static final String QUERY = "query";
|
||||
|
||||
private static final String FIELDS = "fields";
|
||||
|
||||
private static final String SIZE = "size";
|
||||
|
||||
private static final String TYPE = "type";
|
||||
|
||||
private static final String TIMEOUT = "timeout";
|
||||
|
||||
private static final String SCROLL = "scroll";
|
||||
|
||||
private static final String INDEX = "index";
|
||||
|
||||
private static final String HOSTS = "hosts";
|
||||
|
||||
private static final String SETTINGS_PREFIX = "settings.";
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(EsDataStoreImpl.class);
|
||||
|
||||
@Override
|
||||
protected void storeData(final DataConfig dataConfig, final IndexUpdateCallback callback, final Map<String, String> paramMap,
|
||||
final Map<String, String> scriptMap, final Map<String, Object> defaultDataMap) {
|
||||
final String hostsStr = paramMap.get(HOSTS);
|
||||
if (StringUtil.isBlank(hostsStr)) {
|
||||
logger.info("hosts is empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
final long readInterval = getReadInterval(paramMap);
|
||||
|
||||
final Settings settings =
|
||||
Settings.builder()
|
||||
.putProperties(
|
||||
paramMap.entrySet()
|
||||
.stream()
|
||||
.filter(e -> e.getKey().startsWith(SETTINGS_PREFIX))
|
||||
.collect(
|
||||
Collectors.toMap(e -> e.getKey().replaceFirst("^settings\\.", StringUtil.EMPTY),
|
||||
e -> e.getValue())), s -> s).build();
|
||||
logger.info("Connecting to " + hostsStr + " with [" + settings.toDelimitedString(',') + "]");
|
||||
final TransportAddress[] addresses = split(hostsStr, ",").get(stream -> stream.map(h -> {
|
||||
final String[] values = h.trim().split(":");
|
||||
try {
|
||||
if (values.length == 1) {
|
||||
return new TransportAddress(InetAddress.getByName(values[0]), 9300);
|
||||
} else if (values.length == 2) {
|
||||
return new TransportAddress(InetAddress.getByName(values[0]), Integer.parseInt(values[1]));
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
logger.warn("Failed to parse address: " + h, e);
|
||||
}
|
||||
return null;
|
||||
}).filter(v -> v != null).toArray(n -> new TransportAddress[n]));
|
||||
try (PreBuiltTransportClient client = new PreBuiltTransportClient(settings)) {
|
||||
client.addTransportAddresses(addresses);
|
||||
processData(dataConfig, callback, paramMap, scriptMap, defaultDataMap, readInterval, client);
|
||||
}
|
||||
}
|
||||
|
||||
protected void processData(final DataConfig dataConfig, final IndexUpdateCallback callback, final Map<String, String> paramMap,
|
||||
final Map<String, String> scriptMap, final Map<String, Object> defaultDataMap, final long readInterval, final Client client) {
|
||||
|
||||
final boolean deleteProcessedDoc = paramMap.getOrDefault("delete.processed.doc", Constants.FALSE).equalsIgnoreCase(Constants.TRUE);
|
||||
final String[] indices;
|
||||
if (paramMap.containsKey(INDEX)) {
|
||||
indices = paramMap.get(INDEX).trim().split(",");
|
||||
} else {
|
||||
indices = new String[] { "_all" };
|
||||
}
|
||||
final String scroll = paramMap.containsKey(SCROLL) ? paramMap.get(SCROLL).trim() : "1m";
|
||||
final String timeout = paramMap.containsKey(TIMEOUT) ? paramMap.get(TIMEOUT).trim() : "1m";
|
||||
final SearchRequestBuilder builder = client.prepareSearch(indices);
|
||||
if (paramMap.containsKey(TYPE)) {
|
||||
builder.setTypes(paramMap.get(TYPE).trim().split(","));
|
||||
}
|
||||
if (paramMap.containsKey(SIZE)) {
|
||||
builder.setSize(Integer.parseInt(paramMap.get(SIZE)));
|
||||
}
|
||||
if (paramMap.containsKey(FIELDS)) {
|
||||
builder.setFetchSource(paramMap.get(FIELDS).trim().split(","), null);
|
||||
}
|
||||
builder.setQuery(QueryBuilders.wrapperQuery(paramMap.containsKey(QUERY) ? paramMap.get(QUERY).trim() : "{\"match_all\":{}}"));
|
||||
builder.setScroll(scroll);
|
||||
builder.setPreference(paramMap.containsKey(PREFERENCE) ? paramMap.get(PREFERENCE).trim() : Constants.SEARCH_PREFERENCE_LOCAL);
|
||||
try {
|
||||
SearchResponse response = builder.execute().actionGet(timeout);
|
||||
|
||||
String scrollId = response.getScrollId();
|
||||
while (scrollId != null) {
|
||||
final SearchHits searchHits = response.getHits();
|
||||
final SearchHit[] hits = searchHits.getHits();
|
||||
if (hits.length == 0) {
|
||||
scrollId = null;
|
||||
break;
|
||||
}
|
||||
|
||||
boolean loop = true;
|
||||
final BulkRequestBuilder bulkRequest = deleteProcessedDoc ? client.prepareBulk() : null;
|
||||
for (final SearchHit hit : hits) {
|
||||
if (!alive || !loop) {
|
||||
break;
|
||||
}
|
||||
|
||||
final Map<String, Object> dataMap = new HashMap<>();
|
||||
dataMap.putAll(defaultDataMap);
|
||||
final Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.putAll(paramMap);
|
||||
resultMap.put("index", hit.getIndex());
|
||||
resultMap.put("type", hit.getType());
|
||||
resultMap.put("id", hit.getId());
|
||||
resultMap.put("version", Long.valueOf(hit.getVersion()));
|
||||
resultMap.put("hit", hit);
|
||||
resultMap.put("source", hit.getSourceAsMap());
|
||||
resultMap.put("crawlingConfig", dataConfig);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
for (final Map.Entry<String, Object> entry : resultMap.entrySet()) {
|
||||
logger.debug(entry.getKey() + "=" + entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
final Map<String, Object> crawlingContext = new HashMap<>();
|
||||
crawlingContext.put("doc", dataMap);
|
||||
resultMap.put("crawlingContext", crawlingContext);
|
||||
for (final Map.Entry<String, String> entry : scriptMap.entrySet()) {
|
||||
final Object convertValue = convertValue(entry.getValue(), resultMap);
|
||||
if (convertValue != null) {
|
||||
dataMap.put(entry.getKey(), convertValue);
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
for (final Map.Entry<String, Object> entry : dataMap.entrySet()) {
|
||||
logger.debug(entry.getKey() + "=" + entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
callback.store(paramMap, dataMap);
|
||||
} catch (final CrawlingAccessException e) {
|
||||
logger.warn("Crawling Access Exception at : " + dataMap, e);
|
||||
|
||||
Throwable target = e;
|
||||
if (target instanceof MultipleCrawlingAccessException) {
|
||||
final Throwable[] causes = ((MultipleCrawlingAccessException) target).getCauses();
|
||||
if (causes.length > 0) {
|
||||
target = causes[causes.length - 1];
|
||||
}
|
||||
}
|
||||
|
||||
String errorName;
|
||||
final Throwable cause = target.getCause();
|
||||
if (cause != null) {
|
||||
errorName = cause.getClass().getCanonicalName();
|
||||
} else {
|
||||
errorName = target.getClass().getCanonicalName();
|
||||
}
|
||||
|
||||
String url;
|
||||
if (target instanceof DataStoreCrawlingException) {
|
||||
final DataStoreCrawlingException dce = (DataStoreCrawlingException) target;
|
||||
url = dce.getUrl();
|
||||
if (dce.aborted()) {
|
||||
loop = false;
|
||||
}
|
||||
} else {
|
||||
url = hit.getIndex() + "/" + hit.getType() + "/" + hit.getId();
|
||||
}
|
||||
final FailureUrlService failureUrlService = ComponentUtil.getComponent(FailureUrlService.class);
|
||||
failureUrlService.store(dataConfig, errorName, url, target);
|
||||
} catch (final Throwable t) {
|
||||
logger.warn("Crawling Access Exception at : " + dataMap, t);
|
||||
final String url = hit.getIndex() + "/" + hit.getType() + "/" + hit.getId();
|
||||
final FailureUrlService failureUrlService = ComponentUtil.getComponent(FailureUrlService.class);
|
||||
failureUrlService.store(dataConfig, t.getClass().getCanonicalName(), url, t);
|
||||
}
|
||||
|
||||
if (bulkRequest != null) {
|
||||
bulkRequest.add(client.prepareDelete(hit.getIndex(), hit.getType(), hit.getId()));
|
||||
}
|
||||
|
||||
if (readInterval > 0) {
|
||||
sleep(readInterval);
|
||||
}
|
||||
}
|
||||
|
||||
if (bulkRequest != null && bulkRequest.numberOfActions() > 0) {
|
||||
final BulkResponse bulkResponse = bulkRequest.execute().actionGet(timeout);
|
||||
if (bulkResponse.hasFailures()) {
|
||||
logger.warn(bulkResponse.buildFailureMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if (!alive) {
|
||||
break;
|
||||
}
|
||||
response = client.prepareSearchScroll(scrollId).setScroll(scroll).execute().actionGet(timeout);
|
||||
scrollId = response.getScrollId();
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
throw new DataStoreException("Failed to crawl data when acessing elasticsearch.", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012-2018 CodeLibs Project and the Others.
|
||||
*
|
||||
* 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 org.codelibs.fess.ds.impl;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.codelibs.fess.Constants;
|
||||
import org.codelibs.fess.crawler.client.CrawlerClientFactory;
|
||||
import org.codelibs.fess.ds.IndexUpdateCallback;
|
||||
import org.codelibs.fess.es.config.exentity.DataConfig;
|
||||
import org.codelibs.fess.exception.DataStoreException;
|
||||
import org.codelibs.fess.util.ComponentUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class EsListDataStoreImpl extends EsDataStoreImpl {
|
||||
private static final Logger logger = LoggerFactory.getLogger(EsListDataStoreImpl.class);
|
||||
|
||||
@Override
|
||||
protected void storeData(final DataConfig dataConfig, final IndexUpdateCallback callback, final Map<String, String> paramMap,
|
||||
final Map<String, String> scriptMap, final Map<String, Object> defaultDataMap) {
|
||||
int nThreads = 1;
|
||||
if (paramMap.containsKey(Constants.NUM_OF_THREADS)) {
|
||||
try {
|
||||
nThreads = Integer.parseInt(paramMap.get(Constants.NUM_OF_THREADS));
|
||||
} catch (final NumberFormatException e) {
|
||||
logger.warn(Constants.NUM_OF_THREADS + " is not int value.", e);
|
||||
}
|
||||
}
|
||||
final CrawlerClientFactory crawlerClientFactory = ComponentUtil.getCrawlerClientFactory();
|
||||
dataConfig.initializeClientFactory(crawlerClientFactory);
|
||||
try {
|
||||
final FileListIndexUpdateCallbackImpl fileListIndexUpdateCallback =
|
||||
new FileListIndexUpdateCallbackImpl(callback, crawlerClientFactory, nThreads);
|
||||
super.storeData(dataConfig, fileListIndexUpdateCallback, paramMap, scriptMap, defaultDataMap);
|
||||
fileListIndexUpdateCallback.commit();
|
||||
} catch (final Exception e) {
|
||||
throw new DataStoreException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,481 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012-2018 CodeLibs Project and the Others.
|
||||
*
|
||||
* 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 org.codelibs.fess.ds.impl;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.codelibs.core.lang.StringUtil;
|
||||
import org.codelibs.elasticsearch.runner.net.Curl;
|
||||
import org.codelibs.elasticsearch.runner.net.CurlResponse;
|
||||
import org.codelibs.fess.crawler.client.CrawlerClientFactory;
|
||||
import org.codelibs.fess.crawler.client.http.HcHttpClient;
|
||||
import org.codelibs.fess.crawler.client.http.RequestHeader;
|
||||
import org.codelibs.fess.ds.IndexUpdateCallback;
|
||||
import org.codelibs.fess.es.config.exentity.CrawlingConfig;
|
||||
import org.codelibs.fess.es.config.exentity.CrawlingConfigWrapper;
|
||||
import org.codelibs.fess.es.config.exentity.DataConfig;
|
||||
import org.codelibs.fess.helper.SystemHelper;
|
||||
import org.codelibs.fess.mylasta.direction.FessConfig;
|
||||
import org.codelibs.fess.util.ComponentUtil;
|
||||
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* @author Keiichi Watanabe
|
||||
*/
|
||||
public class GitBucketDataStoreImpl extends AbstractDataStoreImpl {
|
||||
private static final Logger logger = LoggerFactory.getLogger(GitBucketDataStoreImpl.class);
|
||||
|
||||
private static final int MAX_DEPTH = 20;
|
||||
|
||||
protected static final String TOKEN_PARAM = "token";
|
||||
protected static final String GITBUCKET_URL_PARAM = "url";
|
||||
protected static final String PRIVATE_REPOSITORY_PARAM = "is_private";
|
||||
protected static final String COLLABORATORS_PARAM = "collaborators";
|
||||
|
||||
@Override
|
||||
protected void storeData(final DataConfig dataConfig, final IndexUpdateCallback callback, final Map<String, String> paramMap,
|
||||
final Map<String, String> scriptMap, final Map<String, Object> defaultDataMap) {
|
||||
|
||||
final String rootURL = getRootURL(paramMap);
|
||||
final String authToken = getAuthToken(paramMap);
|
||||
final long readInterval = getReadInterval(paramMap);
|
||||
|
||||
// Non-emptiness Check for URL and Token
|
||||
if (rootURL.isEmpty() || authToken.isEmpty()) {
|
||||
logger.warn("parameter \"" + TOKEN_PARAM + "\" and \"" + GITBUCKET_URL_PARAM + "\" are required");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get List of Repositories
|
||||
final List<Map<String, Object>> repositoryList = getRepositoryList(rootURL, authToken);
|
||||
if (repositoryList.isEmpty()) {
|
||||
logger.warn("Token is invalid or no Repository");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get Labels
|
||||
final Map<String, String> pluginInfo = getFessPluginInfo(rootURL, authToken);
|
||||
final String sourceLabel = pluginInfo.get("source_label");
|
||||
final String issueLabel = pluginInfo.get("issue_label");
|
||||
final String wikiLabel = pluginInfo.get("wiki_label");
|
||||
|
||||
final CrawlingConfig crawlingConfig = new CrawlingConfigWrapper(dataConfig) {
|
||||
@Override
|
||||
public Map<String, Object> initializeClientFactory(final CrawlerClientFactory crawlerClientFactory) {
|
||||
final Map<String, Object> paramMap = super.initializeClientFactory(crawlerClientFactory);
|
||||
final List<RequestHeader> headerList = new ArrayList<>();
|
||||
final RequestHeader[] headers = (RequestHeader[]) paramMap.get(HcHttpClient.REQUERT_HEADERS_PROPERTY);
|
||||
if (headers != null) {
|
||||
for (final RequestHeader header : headers) {
|
||||
headerList.add(header);
|
||||
}
|
||||
}
|
||||
headerList.add(new RequestHeader("Authorization", "token " + authToken));
|
||||
headerList.add(new RequestHeader("Accept", "application/vnd.github.v3.raw"));
|
||||
paramMap.put(HcHttpClient.REQUERT_HEADERS_PROPERTY, headerList.toArray(new RequestHeader[headerList.size()]));
|
||||
return paramMap;
|
||||
}
|
||||
};
|
||||
|
||||
// Crawl each repository
|
||||
for (final Map<String, Object> repository : repositoryList) {
|
||||
try {
|
||||
final String owner = (String) repository.get("owner");
|
||||
final String name = (String) repository.get("name");
|
||||
// Since old gitbucket-fess-plugin does not return "branch", it refers instead of "master".
|
||||
final String branch = (String) repository.getOrDefault("branch", "master");
|
||||
final int issueCount = (int) repository.get("issue_count");
|
||||
final int pullCount = (int) repository.get("pull_count");
|
||||
final List<String> roleList = createRoleList(owner, repository);
|
||||
|
||||
// branch is empty when git repository is empty.
|
||||
if (StringUtil.isNotEmpty(branch)) {
|
||||
final String refStr = getGitRef(rootURL, authToken, owner, name, branch);
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Crawl " + owner + "/" + name);
|
||||
}
|
||||
// crawl and store file contents recursively
|
||||
crawlFileContents(
|
||||
rootURL,
|
||||
authToken,
|
||||
owner,
|
||||
name,
|
||||
refStr,
|
||||
StringUtil.EMPTY,
|
||||
0,
|
||||
readInterval,
|
||||
path -> {
|
||||
storeFileContent(rootURL, authToken, sourceLabel, owner, name, refStr, roleList, path, crawlingConfig,
|
||||
callback, paramMap, scriptMap, defaultDataMap);
|
||||
if (readInterval > 0) {
|
||||
sleep(readInterval);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Crawl issues in " + owner + "/" + name);
|
||||
}
|
||||
// store issues
|
||||
for (int issueId = 1; issueId <= issueCount + pullCount; issueId++) {
|
||||
storeIssueById(rootURL, authToken, issueLabel, owner, name, new Integer(issueId), roleList, crawlingConfig, callback,
|
||||
paramMap, scriptMap, defaultDataMap);
|
||||
|
||||
if (readInterval > 0) {
|
||||
sleep(readInterval);
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Crawl Wiki in " + owner + "/" + name);
|
||||
}
|
||||
// crawl Wiki
|
||||
storeWikiContents(rootURL, authToken, wikiLabel, owner, name, roleList, crawlingConfig, callback, paramMap, scriptMap,
|
||||
defaultDataMap, readInterval);
|
||||
|
||||
} catch (final Exception e) {
|
||||
logger.warn("Failed to access to " + repository, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected String getRootURL(final Map<String, String> paramMap) {
|
||||
if (paramMap.containsKey(GITBUCKET_URL_PARAM)) {
|
||||
final String url = paramMap.get(GITBUCKET_URL_PARAM);
|
||||
if (!url.endsWith("/")) {
|
||||
return url + "/";
|
||||
}
|
||||
return url;
|
||||
}
|
||||
return StringUtil.EMPTY;
|
||||
}
|
||||
|
||||
protected String getAuthToken(final Map<String, String> paramMap) {
|
||||
if (paramMap.containsKey(TOKEN_PARAM)) {
|
||||
return paramMap.get(TOKEN_PARAM);
|
||||
}
|
||||
return StringUtil.EMPTY;
|
||||
}
|
||||
|
||||
protected Map<String, String> getFessPluginInfo(final String rootURL, final String authToken) {
|
||||
final FessConfig fessConfig = ComponentUtil.getFessConfig();
|
||||
final String url = rootURL + "api/v3/fess/info";
|
||||
try (CurlResponse curlResponse =
|
||||
Curl.get(url).proxy(fessConfig.getHttpProxy()).header("Authorization", "token " + authToken).execute()) {
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
final Map<String, String> map = (Map) curlResponse.getContentAsMap();
|
||||
assert (map.containsKey("version"));
|
||||
assert (map.containsKey("source_label") && map.containsKey("wiki_label") && map.containsKey("issue_label"));
|
||||
return map;
|
||||
|
||||
} catch (final Exception e) {
|
||||
logger.warn("Failed to access to " + url, e);
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
|
||||
protected List<Map<String, Object>> getRepositoryList(final String rootURL, final String authToken) {
|
||||
final FessConfig fessConfig = ComponentUtil.getFessConfig();
|
||||
final String url = rootURL + "api/v3/fess/repos";
|
||||
int totalCount = -1; // initialize with dummy value
|
||||
final List<Map<String, Object>> repoList = new ArrayList<>();
|
||||
|
||||
do {
|
||||
final String urlWithOffset = url + "?offset=" + repoList.size();
|
||||
|
||||
try (CurlResponse curlResponse =
|
||||
Curl.get(urlWithOffset).proxy(fessConfig.getHttpProxy()).header("Authorization", "token " + authToken).execute()) {
|
||||
final Map<String, Object> map = curlResponse.getContentAsMap();
|
||||
|
||||
assert (map.containsKey("total_count"));
|
||||
assert (map.containsKey("response_count"));
|
||||
assert (map.containsKey("repositories"));
|
||||
|
||||
totalCount = (int) map.get("total_count");
|
||||
final int responseCount = (int) map.get("response_count");
|
||||
if (responseCount == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<Map<String, Object>> repos = (ArrayList<Map<String, Object>>) map.get("repositories");
|
||||
repoList.addAll(repos);
|
||||
} catch (final Exception e) {
|
||||
logger.warn("Failed to access to " + urlWithOffset, e);
|
||||
break;
|
||||
}
|
||||
} while (repoList.size() < totalCount);
|
||||
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("There exist " + repoList.size() + " repositories");
|
||||
}
|
||||
return repoList;
|
||||
}
|
||||
|
||||
protected String getGitRef(final String rootURL, final String authToken, final String owner, final String name, final String branch) {
|
||||
final FessConfig fessConfig = ComponentUtil.getFessConfig();
|
||||
final String url = encode(rootURL, "api/v3/repos/" + owner + "/" + name + "/git/refs/heads/" + branch, null);
|
||||
|
||||
try (CurlResponse curlResponse =
|
||||
Curl.get(url).proxy(fessConfig.getHttpProxy()).header("Authorization", "token " + authToken).execute()) {
|
||||
final Map<String, Object> map = curlResponse.getContentAsMap();
|
||||
assert (map.containsKey("object"));
|
||||
@SuppressWarnings("unchecked")
|
||||
final Map<String, String> objmap = (Map<String, String>) map.get("object");
|
||||
assert (objmap.containsKey("sha"));
|
||||
return objmap.get("sha");
|
||||
} catch (final Exception e) {
|
||||
logger.warn("Failed to access to " + url, e);
|
||||
return branch;
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> createRoleList(final String owner, final Map<String, Object> repository) {
|
||||
Boolean isPrivate = true;
|
||||
if (repository.containsKey(PRIVATE_REPOSITORY_PARAM)) {
|
||||
isPrivate = (Boolean) repository.get(PRIVATE_REPOSITORY_PARAM);
|
||||
}
|
||||
if (!isPrivate) {
|
||||
return Collections.singletonList("Rguest");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<String> collaboratorList = (List<String>) repository.get(COLLABORATORS_PARAM);
|
||||
final SystemHelper systemHelper = ComponentUtil.getSystemHelper();
|
||||
collaboratorList.add(owner);
|
||||
return collaboratorList.stream().map(user -> systemHelper.getSearchRoleByUser(user)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<Object> parseList(final InputStream is) { // TODO This function should be moved to CurlResponse
|
||||
try {
|
||||
return JsonXContent.jsonXContent.createParser(NamedXContentRegistry.EMPTY, is).list();
|
||||
} catch (final Exception e) {
|
||||
logger.warn("Failed to parse a list.", e);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
private void storeFileContent(final String rootURL, final String authToken, final String sourceLabel, final String owner,
|
||||
final String name, final String refStr, final List<String> roleList, final String path, final CrawlingConfig crawlingConfig,
|
||||
final IndexUpdateCallback callback, final Map<String, String> paramMap, final Map<String, String> scriptMap,
|
||||
final Map<String, Object> defaultDataMap) {
|
||||
final String apiUrl = encode(rootURL, "api/v3/repos/" + owner + "/" + name + "/contents/" + path, null);
|
||||
final String viewUrl = encode(rootURL, owner + "/" + name + "/blob/" + refStr + "/" + path, null);
|
||||
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Get a content from " + apiUrl);
|
||||
}
|
||||
final Map<String, Object> dataMap = new HashMap<>();
|
||||
dataMap.putAll(defaultDataMap);
|
||||
dataMap.putAll(ComponentUtil.getDocumentHelper().processRequest(crawlingConfig, paramMap.get("crawlingInfoId"),
|
||||
apiUrl + "?ref=" + refStr + "&large_file=true"));
|
||||
|
||||
dataMap.put("url", viewUrl);
|
||||
dataMap.put("role", roleList);
|
||||
dataMap.put("label", Collections.singletonList(sourceLabel));
|
||||
|
||||
// TODO scriptMap
|
||||
|
||||
callback.store(paramMap, dataMap);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
private void storeIssueById(final String rootURL, final String authToken, final String issueLabel, final String owner,
|
||||
final String name, final Integer issueId, final List<String> roleList, final CrawlingConfig crawlingConfig,
|
||||
final IndexUpdateCallback callback, final Map<String, String> paramMap, final Map<String, String> scriptMap,
|
||||
final Map<String, Object> defaultDataMap) {
|
||||
final FessConfig fessConfig = ComponentUtil.getFessConfig();
|
||||
|
||||
final String issueUrl = rootURL + "api/v3/repos/" + owner + "/" + name + "/issues/" + issueId.toString();
|
||||
final String viewUrl = rootURL + owner + "/" + name + "/issues/" + issueId.toString();
|
||||
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Get a content from " + issueUrl);
|
||||
}
|
||||
|
||||
final Map<String, Object> dataMap = new HashMap<>();
|
||||
String contentStr = "";
|
||||
dataMap.putAll(defaultDataMap);
|
||||
|
||||
// Get issue description
|
||||
// FIXME: Use `ComponentUtil.getDocumentHelper().processRequest` instead of `Curl.get`
|
||||
try (CurlResponse curlResponse =
|
||||
Curl.get(issueUrl).proxy(fessConfig.getHttpProxy()).header("Authorization", "token " + authToken).execute()) {
|
||||
final Map<String, Object> map = curlResponse.getContentAsMap();
|
||||
dataMap.put("title", map.getOrDefault("title", ""));
|
||||
contentStr = (String) map.getOrDefault("body", "");
|
||||
} catch (final Exception e) {
|
||||
logger.warn("Failed to access to " + issueUrl, e);
|
||||
}
|
||||
|
||||
final String commentsStr = String.join("\n", getIssueComments(issueUrl, authToken));
|
||||
contentStr += "\n" + commentsStr;
|
||||
|
||||
dataMap.put("content", contentStr);
|
||||
dataMap.put("url", viewUrl);
|
||||
dataMap.put("role", roleList);
|
||||
dataMap.put("label", Collections.singletonList(issueLabel));
|
||||
|
||||
// TODO scriptMap
|
||||
|
||||
callback.store(paramMap, dataMap);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
private List<String> getIssueComments(final String issueUrl, final String authToken) {
|
||||
final FessConfig fessConfig = ComponentUtil.getFessConfig();
|
||||
final String commentsUrl = issueUrl + "/comments";
|
||||
final List<String> commentList = new ArrayList<>();
|
||||
|
||||
try (CurlResponse curlResponse =
|
||||
Curl.get(commentsUrl).proxy(fessConfig.getHttpProxy()).header("Authorization", "token " + authToken).execute()) {
|
||||
final String commentsJson = curlResponse.getContentAsString();
|
||||
final List<Map<String, Object>> comments =
|
||||
new ObjectMapper().readValue(commentsJson, new TypeReference<List<Map<String, Object>>>() {
|
||||
});
|
||||
|
||||
for (final Map<String, Object> comment : comments) {
|
||||
if (comment.containsKey("body")) {
|
||||
commentList.add((String) comment.get("body"));
|
||||
}
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
logger.warn("Failed to access to " + issueUrl, e);
|
||||
}
|
||||
|
||||
return commentList;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void storeWikiContents(final String rootURL, final String authToken, final String wikiLabel, final String owner,
|
||||
final String name, final List<String> roleList, final CrawlingConfig crawlingConfig, final IndexUpdateCallback callback,
|
||||
final Map<String, String> paramMap, final Map<String, String> scriptMap, final Map<String, Object> defaultDataMap,
|
||||
final long readInterval) {
|
||||
final FessConfig fessConfig = ComponentUtil.getFessConfig();
|
||||
final String wikiUrl = rootURL + "api/v3/fess/" + owner + "/" + name + "/wiki";
|
||||
|
||||
List<String> pageList = Collections.emptyList();
|
||||
|
||||
// Get list of pages
|
||||
try (CurlResponse curlResponse =
|
||||
Curl.get(wikiUrl).proxy(fessConfig.getHttpProxy()).header("Authorization", "token " + authToken).execute()) {
|
||||
final Map<String, Object> map = curlResponse.getContentAsMap();
|
||||
pageList = (List<String>) map.get("pages");
|
||||
} catch (final Exception e) {
|
||||
logger.warn("Failed to access to " + wikiUrl, e);
|
||||
}
|
||||
|
||||
for (final String page : pageList) {
|
||||
final String pageUrl = wikiUrl + "/contents/" + page + ".md";
|
||||
final String viewUrl = rootURL + owner + "/" + name + "/wiki/" + page;
|
||||
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Get a content from " + pageUrl);
|
||||
}
|
||||
|
||||
final Map<String, Object> dataMap = new HashMap<>();
|
||||
dataMap.putAll(defaultDataMap);
|
||||
dataMap.putAll(ComponentUtil.getDocumentHelper().processRequest(crawlingConfig, paramMap.get("crawlingInfoId"),
|
||||
pageUrl.replace("+", "%20")));
|
||||
|
||||
dataMap.put("url", viewUrl);
|
||||
dataMap.put("role", roleList);
|
||||
dataMap.put("label", Collections.singletonList(wikiLabel));
|
||||
|
||||
// TODO scriptMap
|
||||
|
||||
callback.store(paramMap, dataMap);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Stored " + pageUrl);
|
||||
}
|
||||
|
||||
if (readInterval > 0) {
|
||||
sleep(readInterval);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void crawlFileContents(final String rootURL, final String authToken, final String owner, final String name,
|
||||
final String refStr, final String path, final int depth, final long readInterval, final Consumer<String> consumer) {
|
||||
|
||||
if (MAX_DEPTH <= depth) {
|
||||
return;
|
||||
}
|
||||
|
||||
final FessConfig fessConfig = ComponentUtil.getFessConfig();
|
||||
final String url = encode(rootURL, "api/v3/repos/" + owner + "/" + name + "/contents/" + path, "ref=" + refStr);
|
||||
|
||||
try (CurlResponse curlResponse =
|
||||
Curl.get(url).proxy(fessConfig.getHttpProxy()).header("Authorization", "token " + authToken).execute()) {
|
||||
final InputStream iStream = curlResponse.getContentAsStream();
|
||||
final List<Object> fileList = parseList(iStream);
|
||||
|
||||
for (int i = 0; i < fileList.size(); ++i) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Map<String, String> file = (Map<String, String>) fileList.get(i);
|
||||
final String newPath = path.isEmpty() ? file.get("name") : path + "/" + file.get("name");
|
||||
switch (file.get("type")) {
|
||||
case "file":
|
||||
consumer.accept(newPath);
|
||||
break;
|
||||
case "dir":
|
||||
if (readInterval > 0) {
|
||||
sleep(readInterval);
|
||||
}
|
||||
crawlFileContents(rootURL, authToken, owner, name, refStr, newPath, depth + 1, readInterval, consumer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
logger.warn("Failed to access to " + url, e);
|
||||
}
|
||||
}
|
||||
|
||||
protected String encode(final String rootURL, final String path, final String query) {
|
||||
try {
|
||||
final URI rootURI = new URI(rootURL);
|
||||
final URI uri =
|
||||
new URI(rootURI.getScheme(), rootURI.getUserInfo(), rootURI.getHost(), rootURI.getPort(), rootURI.getPath() + path,
|
||||
query, null);
|
||||
return uri.toASCIIString();
|
||||
} catch (final URISyntaxException e) {
|
||||
logger.warn("Failed to parse " + rootURL + path + "?" + query, e);
|
||||
if (StringUtil.isEmpty(query)) {
|
||||
return rootURL + path;
|
||||
}
|
||||
return rootURL + path + "?" + query;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,161 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012-2018 CodeLibs Project and the Others.
|
||||
*
|
||||
* 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 org.codelibs.fess.ds.impl;
|
||||
|
||||
import static org.codelibs.core.stream.StreamUtil.stream;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.codelibs.core.lang.StringUtil;
|
||||
import org.codelibs.fess.Constants;
|
||||
import org.codelibs.fess.ds.IndexUpdateCallback;
|
||||
import org.codelibs.fess.es.config.exentity.DataConfig;
|
||||
import org.codelibs.fess.exception.DataStoreException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
public class JsonDataStoreImpl extends AbstractDataStoreImpl {
|
||||
private static final Logger logger = LoggerFactory.getLogger(JsonDataStoreImpl.class);
|
||||
|
||||
private static final String FILE_ENCODING_PARAM = "fileEncoding";
|
||||
|
||||
private static final String FILES_PARAM = "files";
|
||||
|
||||
private static final String DIRS_PARAM = "directories";
|
||||
|
||||
private String[] fileSuffixes = new String[] { ".json", ".jsonl" };
|
||||
|
||||
@Override
|
||||
protected void storeData(final DataConfig dataConfig, final IndexUpdateCallback callback, final Map<String, String> paramMap,
|
||||
final Map<String, String> scriptMap, final Map<String, Object> defaultDataMap) {
|
||||
final String fileEncoding = getFileEncoding(paramMap);
|
||||
final List<File> fileList = getFileList(paramMap);
|
||||
|
||||
if (fileList.isEmpty()) {
|
||||
logger.warn("No files to process");
|
||||
return;
|
||||
}
|
||||
|
||||
for (final File file : fileList) {
|
||||
processFile(dataConfig, callback, paramMap, scriptMap, defaultDataMap, file, fileEncoding);
|
||||
}
|
||||
}
|
||||
|
||||
private List<File> getFileList(final Map<String, String> paramMap) {
|
||||
String value = paramMap.get(FILES_PARAM);
|
||||
final List<File> fileList = new ArrayList<>();
|
||||
if (StringUtil.isBlank(value)) {
|
||||
value = paramMap.get(DIRS_PARAM);
|
||||
if (StringUtil.isBlank(value)) {
|
||||
throw new DataStoreException(FILES_PARAM + " and " + DIRS_PARAM + " are blank.");
|
||||
}
|
||||
logger.info(DIRS_PARAM + "=" + value);
|
||||
final String[] values = value.split(",");
|
||||
for (final String path : values) {
|
||||
final File dir = new File(path);
|
||||
if (dir.isDirectory()) {
|
||||
stream(dir.listFiles()).of(
|
||||
stream -> stream.filter(f -> isDesiredFile(f.getParentFile(), f.getName()))
|
||||
.sorted((f1, f2) -> (int) (f1.lastModified() - f2.lastModified())).forEach(fileList::add));
|
||||
} else {
|
||||
logger.warn(path + " is not a directory.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.info(FILES_PARAM + "=" + value);
|
||||
final String[] values = value.split(",");
|
||||
for (final String path : values) {
|
||||
final File file = new File(path);
|
||||
if (file.isFile() && isDesiredFile(file.getParentFile(), file.getName())) {
|
||||
fileList.add(file);
|
||||
} else {
|
||||
logger.warn(path + " is not found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fileList.isEmpty() && logger.isDebugEnabled()) {
|
||||
logger.debug("No files in " + value);
|
||||
}
|
||||
return fileList;
|
||||
}
|
||||
|
||||
private boolean isDesiredFile(final File parentFile, final String filename) {
|
||||
final String name = filename.toLowerCase(Locale.ROOT);
|
||||
for (final String suffix : fileSuffixes) {
|
||||
if (name.endsWith(suffix)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private String getFileEncoding(final Map<String, String> paramMap) {
|
||||
final String value = paramMap.get(FILE_ENCODING_PARAM);
|
||||
if (StringUtil.isBlank(value)) {
|
||||
return Constants.UTF_8;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private void processFile(final DataConfig dataConfig, final IndexUpdateCallback callback, final Map<String, String> paramMap,
|
||||
final Map<String, String> scriptMap, final Map<String, Object> defaultDataMap, final File file, final String fileEncoding) {
|
||||
final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
logger.info("Loading " + file.getAbsolutePath());
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), fileEncoding))) {
|
||||
for (String line; (line = br.readLine()) != null;) {
|
||||
final Map<String, Object> source = objectMapper.readValue(line, new TypeReference<Map<String, Object>>() {
|
||||
});
|
||||
final Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
final Map<String, Object> dataMap = new HashMap<>(defaultDataMap);
|
||||
|
||||
resultMap.putAll(paramMap);
|
||||
resultMap.putAll(source);
|
||||
|
||||
for (final Map.Entry<String, String> entry : scriptMap.entrySet()) {
|
||||
final Object convertValue = convertValue(entry.getValue(), resultMap);
|
||||
if (convertValue != null) {
|
||||
dataMap.put(entry.getKey(), convertValue);
|
||||
}
|
||||
}
|
||||
|
||||
callback.store(paramMap, dataMap);
|
||||
}
|
||||
} catch (final FileNotFoundException e) {
|
||||
logger.warn("Source file " + file + " does not exist.", e);
|
||||
} catch (final IOException e) {
|
||||
logger.warn("IO Error occurred while reading source file.", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setFileSuffixes(final String[] fileSuffixes) {
|
||||
this.fileSuffixes = fileSuffixes;
|
||||
}
|
||||
}
|
|
@ -26,7 +26,7 @@ import org.codelibs.fess.Constants;
|
|||
import org.codelibs.fess.app.service.FailureUrlService;
|
||||
import org.codelibs.fess.ds.DataStore;
|
||||
import org.codelibs.fess.ds.DataStoreFactory;
|
||||
import org.codelibs.fess.ds.IndexUpdateCallback;
|
||||
import org.codelibs.fess.ds.callback.IndexUpdateCallback;
|
||||
import org.codelibs.fess.es.client.FessEsClient;
|
||||
import org.codelibs.fess.es.config.exentity.DataConfig;
|
||||
import org.codelibs.fess.mylasta.direction.FessConfig;
|
||||
|
|
|
@ -3,55 +3,7 @@
|
|||
"http://dbflute.org/meta/lastadi10.dtd">
|
||||
<components>
|
||||
<component name="dataStoreFactory" class="org.codelibs.fess.ds.DataStoreFactory">
|
||||
<postConstruct name="add">
|
||||
<arg>"DatabaseDataStore"</arg>
|
||||
<arg>databaseDataStore</arg>
|
||||
</postConstruct>
|
||||
<postConstruct name="add">
|
||||
<arg>"CsvDataStore"</arg>
|
||||
<arg>csvDataStore</arg>
|
||||
</postConstruct>
|
||||
<postConstruct name="add">
|
||||
<arg>"CsvListDataStore"</arg>
|
||||
<arg>csvListDataStore</arg>
|
||||
</postConstruct>
|
||||
<postConstruct name="add">
|
||||
<arg>"EsDataStore"</arg>
|
||||
<arg>esDataStore</arg>
|
||||
</postConstruct>
|
||||
<postConstruct name="add">
|
||||
<arg>"EsListDataStore"</arg>
|
||||
<arg>esListDataStore</arg>
|
||||
</postConstruct>
|
||||
<postConstruct name="add">
|
||||
<arg>"GitBucketDataStore"</arg>
|
||||
<arg>gitBucketDataStore</arg>
|
||||
</postConstruct>
|
||||
<postConstruct name="add">
|
||||
<arg>"JsonDataStore"</arg>
|
||||
<arg>jsonDataStore</arg>
|
||||
</postConstruct>
|
||||
</component>
|
||||
|
||||
<component name="databaseDataStore" class="org.codelibs.fess.ds.impl.DatabaseDataStoreImpl">
|
||||
<component name="indexUpdateCallback" class="org.codelibs.fess.ds.callback.IndexUpdateCallbackImpl" instance="prototype">
|
||||
</component>
|
||||
<component name="csvDataStore" class="org.codelibs.fess.ds.impl.CsvDataStoreImpl">
|
||||
<!--
|
||||
<property name="csvFileSuffixs">new String[] { ".csv", ".tsv" }</property>
|
||||
-->
|
||||
</component>
|
||||
<component name="csvListDataStore" class="org.codelibs.fess.ds.impl.CsvListDataStoreImpl">
|
||||
</component>
|
||||
<component name="esDataStore" class="org.codelibs.fess.ds.impl.EsDataStoreImpl">
|
||||
</component>
|
||||
<component name="esListDataStore" class="org.codelibs.fess.ds.impl.EsListDataStoreImpl">
|
||||
</component>
|
||||
<component name="gitBucketDataStore" class="org.codelibs.fess.ds.impl.GitBucketDataStoreImpl">
|
||||
</component>
|
||||
<component name="jsonDataStore" class="org.codelibs.fess.ds.impl.JsonDataStoreImpl">
|
||||
</component>
|
||||
|
||||
<component name="indexUpdateCallback" class="org.codelibs.fess.ds.impl.IndexUpdateCallbackImpl" instance="prototype">
|
||||
</component>
|
||||
|
||||
</components>
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012-2018 CodeLibs Project and the Others.
|
||||
*
|
||||
* 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 org.codelibs.fess.ds.impl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.codelibs.fess.unit.UnitFessTestCase;
|
||||
|
||||
public class DatabaseDataStoreImplTest extends UnitFessTestCase {
|
||||
public DatabaseDataStoreImpl databaseDataStore;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
databaseDataStore = new DatabaseDataStoreImpl();
|
||||
}
|
||||
|
||||
public void test_convertValue() {
|
||||
String value;
|
||||
final Map<String, Object> paramMap = new HashMap<>();
|
||||
paramMap.put("param1", "PARAM1");
|
||||
paramMap.put("param2", "PARAM2+");
|
||||
paramMap.put("param3", "PARAM3*");
|
||||
|
||||
value = "\"abc\"";
|
||||
assertEquals("abc", databaseDataStore.convertValue(value, paramMap));
|
||||
|
||||
value = "param1";
|
||||
assertEquals("PARAM1", databaseDataStore.convertValue(value, paramMap));
|
||||
|
||||
value = "param2";
|
||||
assertEquals("PARAM2+", databaseDataStore.convertValue(value, paramMap));
|
||||
|
||||
value = "\"123\"+param2+\",\"+param3+\"abc\"";
|
||||
assertEquals("123PARAM2+,PARAM3*abc", databaseDataStore.convertValue(value, paramMap));
|
||||
|
||||
value = null;
|
||||
assertEquals("", databaseDataStore.convertValue(value, paramMap));
|
||||
|
||||
value = "";
|
||||
assertEquals("", databaseDataStore.convertValue(value, paramMap));
|
||||
|
||||
value = " ";
|
||||
assertNull(databaseDataStore.convertValue(value, paramMap));
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012-2018 CodeLibs Project and the Others.
|
||||
*
|
||||
* 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 org.codelibs.fess.ds.impl;
|
||||
|
||||
import org.codelibs.fess.unit.UnitFessTestCase;
|
||||
|
||||
public class GitBucketDataStoreImplTest extends UnitFessTestCase {
|
||||
public GitBucketDataStoreImpl dataStore;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
dataStore = new GitBucketDataStoreImpl();
|
||||
}
|
||||
|
||||
public void test_encode() {
|
||||
String rootURL = "https://gitbucket.com/";
|
||||
String path;
|
||||
String query;
|
||||
|
||||
path = "api/v3/repos/";
|
||||
query = "aaa=111";
|
||||
assertEquals("https://gitbucket.com/api/v3/repos/?aaa=111", dataStore.encode(rootURL, path, query));
|
||||
|
||||
path = "api/v3/repos/AA BB";
|
||||
query = "aaa=11 11";
|
||||
assertEquals("https://gitbucket.com/api/v3/repos/AA%20BB?aaa=11%2011", dataStore.encode(rootURL, path, query));
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue