Compare commits

..

No commits in common. "master" and "14.2.x" have entirely different histories.

1739 changed files with 178571 additions and 190375 deletions

97
.github/workflows/codeql-analysis.yml vendored Normal file
View file

@ -0,0 +1,97 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
name: "CodeQL"
on:
push:
branches:
- master
- "*.x"
pull_request:
branches:
- master
- "*.x"
schedule:
- cron: '36 4 * * 2'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# Override automatic language detection by changing the below list
# Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
language: ['java', 'javascript']
# Learn more...
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2
# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
#- name: Autobuild
# uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- uses: actions/checkout@v2
- name: Set up JDK 17
uses: actions/setup-java@v2
with:
java-version: '17'
distribution: 'temurin'
- name: Cache Maven packages
uses: actions/cache@v2
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Checkout fess-parent
uses: actions/checkout@v2
with:
repository: codelibs/fess-parent
path: fess-parent
- name: Install fess-parent
run: |
cd fess-parent
mvn install
- name: Build with Maven
run: mvn -B package --file pom.xml
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View file

@ -1,96 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
schedule:
- cron: '38 6 * * 1'
jobs:
analyze:
name: Analyze (${{ matrix.language }})
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners (GitHub.com only)
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
permissions:
# required for all workflows
security-events: write
# required to fetch internal or private CodeQL packs
packages: read
# only required for workflows in private repositories
actions: read
contents: read
strategy:
fail-fast: false
matrix:
include:
- language: java-kotlin
build-mode: none # This mode only analyzes Java. Set this to 'autobuild' or 'manual' to analyze Kotlin too.
- language: javascript-typescript
build-mode: none
# CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
# Use `c-cpp` to analyze code written in C, C++ or both
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# If the analyze step fails for one of the languages you are analyzing with
# "We were unable to automatically build your code", modify the matrix above
# to set the build mode to "manual" for that language. Then modify this step
# to build your code.
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- if: matrix.build-mode == 'manual'
shell: bash
run: |
echo 'If you are using a "manual" build mode for one or more of the' \
'languages you are analyzing, replace this with the commands to build' \
'your code, for example:'
echo ' make bootstrap'
echo ' make release'
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"

View file

@ -12,29 +12,38 @@ on:
branches:
- master
- "*.x"
workflow_dispatch:
jobs:
build:
runs-on: macos-14
timeout-minutes: 15
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
- uses: actions/checkout@v2
- name: Set up JDK 17
uses: actions/setup-java@v2
with:
java-version: '21'
java-version: '17'
distribution: 'temurin'
- uses: actions/cache@v4
- uses: actions/cache@v1
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- name: Checkout fess-parent
uses: actions/checkout@v2
with:
repository: codelibs/fess-parent
path: fess-parent
- name: Install fess-parent
run: |
cd fess-parent
mvn install
- name: Download Plugins with Maven
run: mvn -B antrun:run --file pom.xml
- name: Build with Maven
run: mvn -B source:jar javadoc:jar package --file pom.xml
run: mvn -B package --file pom.xml
- name: Run Fess
run: bash src/test/resources/before_script.sh
- name: Run Integration Test

3
.gitignore vendored
View file

@ -6,8 +6,7 @@
/src/main/webapp/WEB-INF/classes/
/src/main/webapp/WEB-INF/lib/
/src/main/webapp/WEB-INF/site/
/src/main/webapp/WEB-INF/plugin/*
!/src/main/webapp/WEB-INF/plugin/.keep
/src/main/webapp/WEB-INF/plugin/
/src/main/webapp/WEB-INF/env/crawler/lib/
/src/main/webapp/WEB-INF/env/suggest/lib/
/src/main/webapp/WEB-INF/env/thumbnail/lib/

View file

@ -1,4 +1,5 @@
# Fess: Enterprise Search Server
Fess Enterprise Search Server [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Fess+is+very+powerful+and+easily+deployable+Enterprise+Search+Server.&url=https://github.com/codelibs/fess)
====
[![Java CI with Maven](https://github.com/codelibs/fess/actions/workflows/maven.yml/badge.svg)](https://github.com/codelibs/fess/actions/workflows/maven.yml)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.codelibs.fess/fess/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.codelibs.fess/fess)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/gitbucket/gitbucket/blob/master/LICENSE)
@ -7,8 +8,8 @@
Fess is a very powerful and easily deployable Enterprise Search Server. You can quickly install and run Fess on any platform where you can run the Java Runtime Environment. Fess is provided under the [Apache License 2.0](LICENSE).
Fess is based on [OpenSearch](https://github.com/opensearch-project/OpenSearch), but knowledge/experience about OpenSearch is _not_ required. Fess provides an easy to use Administration GUI to configure the system via your browser.
Fess also contains a Crawler, which can crawl documents on a [web server](https://fess.codelibs.org/14.18/admin/webconfig-guide.html), [file system](https://fess.codelibs.org/14.18/admin/fileconfig-guide.html), or [Data Store](https://fess.codelibs.org/14.18/admin/dataconfig-guide.html) (such as a CSV or database). Many file formats are supported including (but not limited to): Microsoft Office, PDF, and zip.
Fess is based on [Elasticsearch](https://github.com/elastic/elasticsearch)/[OpenSearch](https://github.com/opensearch-project/OpenSearch), but knowledge/experience about Elasticsearch/OpenSearch is _not_ required. Fess provides an easy to use Administration GUI to configure the system via your browser.
Fess also contains a Crawler, which can crawl documents on a [web server](https://fess.codelibs.org/14.2/admin/webconfig-guide.html), [file system](https://fess.codelibs.org/14.2/admin/fileconfig-guide.html), or [Data Store](https://fess.codelibs.org/14.2/admin/dataconfig-guide.html) (such as a CSV or database). Many file formats are supported including (but not limited to): Microsoft Office, PDF, and zip.
*[Fess Site Search](https://github.com/codelibs/fess-site-search)* is a free alternative to [Google Site Search](https://enterprise.google.com/search/products/gss.html). For more details, see the [FSS JS Generator documentation](https://fss-generator.codelibs.org/docs/manual).
@ -26,15 +27,15 @@ There are 2 ways to try Fess. The first is to download and install yourself. The
### Download and Install/Run
Fess 14.18 is now available and can be downloaded on the [Releases page](https://github.com/codelibs/fess/releases "download"). Downloads come in 3 flavors: deb, rpm, zip.
Fess 14.2 is now available and can be downloaded on the [Releases page](https://github.com/codelibs/fess/releases "download"). Downloads come in 3 flavors: deb, rpm, zip.
The following commands show how to use the zip download:
$ unzip fess-14.18.x.zip
$ cd fess-14.18.x
$ unzip fess-14.2.x.zip
$ cd fess-14.2.x
$ ./bin/fess
For more details, see the [Installation Guide](https://fess.codelibs.org/14.18/install/index.html).
For more details, see the [Installation Guide](https://fess.codelibs.org/14.2/install/index.html).
### Docker
@ -50,7 +51,7 @@ We provide Docker images on [ghcr.io](https://github.com/orgs/codelibs/packages)
![Admin UI](https://fess.codelibs.org/_images/fess_admin_dashboard.png)
You can register crawling targets in the Admin UI on the (Web, File, Data Store) crawler configuration pages, and then start the Crawler manually on the [Scheduler page](https://fess.codelibs.org/14.18/admin/scheduler-guide.html).
You can register crawling targets in the Admin UI on the (Web, File, Data Store) crawler configuration pages, and then start the Crawler manually on the [Scheduler page](https://fess.codelibs.org/14.2/admin/scheduler-guide.html).
## Migration from another search provider
@ -58,7 +59,7 @@ Please see [MIGRATION.md](MIGRATION.md).
## Data Store
Currently, Fess supports crawling the following [storage locations and APIs](https://fess.codelibs.org/14.18/admin/dataconfig-guide.html):
Currently, Fess supports crawling the following [storage locations and APIs](https://fess.codelibs.org/14.2/admin/dataconfig-guide.html):
- [Confluence/Jira](https://github.com/codelibs/fess-ds-atlassian)
- [Box](https://github.com/codelibs/fess-ds-box)
@ -91,6 +92,16 @@ Currently, Fess supports crawling the following [storage locations and APIs](htt
- [Groovy](https://github.com/codelibs/fess-script-groovy)
- [OGNL](https://github.com/codelibs/fess-script-ognl)
## Localization
### Japanese
- [Website](https://fess.codelibs.org/ja/)
### Korean
- [Forum](https://github.com/nocode2k/fess-kr-forum)
## Development Information
### Get Source Code
@ -103,7 +114,7 @@ Currently, Fess supports crawling the following [storage locations and APIs](htt
2. Import the cloned repository as a [Maven](https://maven.apache.org/) project on [Eclipse](https://www.eclipse.org/eclipseide/) or another IDE.
### Setup for OpenSearch Plugins
### Setup for Elasticsearch Plugins
Run antrun:run to download plugins into the plugins directory:
@ -131,11 +142,11 @@ Run the `package` goal and then the release file will be created in target/relea
Launch Fess Server and run the following command:
$ mvn test -P integrationTests -Dtest.fess.url="http://localhost:8080" -Dtest.search_engine.url="http://localhost:9201"
$ mvn test -P integrationTests -Dtest.fess.url="http://localhost:8080" -Dtest.es.url="http://localhost:9201"
To run a single test case, you can use:
$ mvn test -P integrationTests -Dtest.fess.url="http://localhost:8080" -Dtest.search_engine.url="http://localhost:9201" -Dtest=SearchApiTests
$ mvn test -P integrationTests -Dtest.fess.url="http://localhost:8080" -Dtest.es.url="http://localhost:9201" -Dtest=SearchApiTests
### Translate In Your Language
@ -146,24 +157,14 @@ If you want to add labels/messages for your language, please translate propertie
* [fess_label_en.properties](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_label_en.properties)
* [fess_message_en.properties](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_message_en.properties)
For search/index analyzer, if [doc.json](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_indices/fess/doc.json) contains lang\_[lang] for your language, please modify the analyzer for your language. For more details about Analyzers, see the [OpenSearch documentation](https://opensearch.org/docs/latest/analyzers/search-analyzers/).
For search/index analyzer, if [doc.json](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_indices/fess/doc.json) contains lang\_[lang] for your language, please modify the analyzer for your language. For more details about Analyzers, see the [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-analyzers.html).
We welcome pull requests for your language.
### Translations
- [日本語 (Japanese)](docs/ja/README.md)
- [简体中文 (Simplified Chinese)](docs/zh-CN/README.md)
- [Español (Spanish)](docs/es/README.md)
- [Português (Brazilian Portuguese)](docs/pt-BR/README.md)
- [Français (French)](docs/fr/README.md)
- [Deutsch (German)](docs/de/README.md)
- [한국어 (Korean)](docs/ko/README.md)
## Powered By
* [Lasta Di](https://github.com/lastaflute/lasta-di "Lasta Di"): DI Container
* [LastaFlute](https://github.com/lastaflute/lastaflute "LastaFlute"): Web Framework
* [Lasta Job](https://github.com/lastaflute/lasta-job "Lasta Job"): Job Scheduler
* [Fess Crawler](https://github.com/codelibs/fess-crawler "Fess Crawler"): Web Crawler
* [OpenSearch](https://opensearch.org/ "OpenSearch"): Search Engine
* [Elasticsearch](https://github.com/elastic/elasticsearch "Elasticsearch"): Search Engine

View file

@ -2,7 +2,7 @@
<project name="dbflute" basedir=".">
<property name="mydbflute.dir" value="${basedir}/mydbflute" />
<property name="target.dir" value="${basedir}/target" />
<property name="branch.name" value="fess-14.17" />
<property name="branch.name" value="fess-14.0" />
<property name="mydbflute.url" value="https://github.com/lastaflute/lastaflute-example-waterfront/archive/${branch.name}.zip" />
<target name="mydbflute.check">

View file

@ -1,6 +1,6 @@
map:{
# base package of generated classes
; basePackage = org.codelibs.fess.opensearch
; basePackage = org.codelibs.fess.es
# base path to JSON resource, URL or relative path
; basePath = ../src/main/config/es

View file

@ -16,19 +16,21 @@
<mkdir dir="${target.dir}" />
<delete dir="${webinf.dir}/lib" />
<mkdir dir="${webinf.dir}/lib" />
<delete dir="${webinf.dir}/plugin" />
<mkdir dir="${webinf.dir}/plugin" />
<delete dir="${crawler.dir}/lib" />
<mkdir dir="${crawler.dir}/lib" />
<delete dir="${suggest.dir}/lib" />
<mkdir dir="${suggest.dir}/lib" />
<delete dir="${thumbnail.dir}/lib" />
<mkdir dir="${thumbnail.dir}/lib" />
<!-- annotation-api -->
<!-- javax.annotation-api -->
<antcall target="install.env.jar">
<param name="repo.url" value="${maven.release.repo.url}" />
<param name="jar.groupId" value="jakarta/annotation" />
<param name="jar.artifactId" value="jakarta.annotation-api" />
<param name="jar.version" value="2.1.1" />
<param name="file.version" value="2.1.1" />
<param name="jar.groupId" value="javax/annotation" />
<param name="jar.artifactId" value="javax.annotation-api" />
<param name="jar.version" value="1.3.2" />
<param name="file.version" value="1.3.2" />
</antcall>
<!-- kopf -->
<get dest="${target.dir}/kopf.zip">
@ -41,11 +43,30 @@
</patternset>
<cutdirsmapper dirs="2" />
</unzip>
<delete>
<fileset dir="${webinf.dir}/plugin">
<include name="**/*.jar" />
</fileset>
</delete>
<!-- fess-ds-csv -->
<antcall target="install.plugin.jar">
<param name="repo.url" value="${maven.release.repo.url}" />
<param name="jar.groupId" value="org/codelibs/fess" />
<param name="jar.artifactId" value="fess-ds-csv" />
<param name="jar.version" value="14.2.0" />
<param name="file.version" value="14.2.0" />
</antcall>
<!-- fess-ds-db -->
<antcall target="install.plugin.jar">
<param name="repo.url" value="${maven.release.repo.url}" />
<param name="jar.groupId" value="org/codelibs/fess" />
<param name="jar.artifactId" value="fess-ds-db" />
<param name="jar.version" value="14.2.0" />
<param name="file.version" value="14.2.0" />
</antcall>
<!-- fess-script-groovy -->
<antcall target="install.plugin.jar">
<param name="repo.url" value="${maven.release.repo.url}" />
<param name="jar.groupId" value="org/codelibs/fess" />
<param name="jar.artifactId" value="fess-script-groovy" />
<param name="jar.version" value="14.2.0" />
<param name="file.version" value="14.2.0" />
</antcall>
</target>
<target name="install.env.jar">
@ -59,4 +80,12 @@
<copy file="${target.dir}/${jar.artifactId}-${file.version}.jar"
todir="${thumbnail.dir}/lib"/>
</target>
<target name="install.plugin.jar">
<get dest="${target.dir}">
<url url="${repo.url}/${jar.groupId}/${jar.artifactId}/${jar.version}/${jar.artifactId}-${file.version}.jar" />
</get>
<copy file="${target.dir}/${jar.artifactId}-${file.version}.jar"
todir="${webinf.dir}/plugin"/>
</target>
</project>

View file

@ -1,159 +0,0 @@
# Fess: Enterprise-Suchserver
[![Java CI with Maven](https://github.com/codelibs/fess/actions/workflows/maven.yml/badge.svg)](https://github.com/codelibs/fess/actions/workflows/maven.yml)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.codelibs.fess/fess/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.codelibs.fess/fess)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/gitbucket/gitbucket/blob/master/LICENSE)
## Übersicht
Fess ist ein sehr leistungsstarker und einfach zu implementierender Enterprise-Suchserver. Sie können Fess schnell auf jeder Plattform installieren und ausführen, auf der die Java-Laufzeitumgebung (JRE) läuft. Fess wird unter der [Apache-Lizenz 2.0](LICENSE) bereitgestellt.
Fess basiert auf [OpenSearch](https://github.com/opensearch-project/OpenSearch), aber es ist kein Wissen oder Erfahrung mit OpenSearch erforderlich. Fess bietet eine einfach zu bedienende Administrations-GUI zur Konfiguration des Systems über Ihren Browser.
Fess enthält auch einen Crawler, der Dokumente auf einem [Webserver](https://fess.codelibs.org/14.17/admin/webconfig-guide.html), [Dateisystem](https://fess.codelibs.org/14.17/admin/fileconfig-guide.html) oder [Datenspeicher](https://fess.codelibs.org/14.17/admin/dataconfig-guide.html) (wie CSV oder Datenbank) durchsuchen kann. Viele Dateiformate werden unterstützt, einschließlich (aber nicht beschränkt auf): Microsoft Office, PDF und zip.
*[Fess Site Search](https://github.com/codelibs/fess-site-search)* ist eine kostenlose Alternative zur [Google Site Search](https://enterprise.google.com/search/products/gss.html). Weitere Details finden Sie in der [Dokumentation des FSS JS Generators](https://fss-generator.codelibs.org/docs/manual).
## Website
[fess.codelibs.org](https://fess.codelibs.org/)
## Probleme/Fragen
[discuss.codelibs.org](https://discuss.codelibs.org/c/FessEN/)
## Erste Schritte
Es gibt zwei Möglichkeiten, Fess auszuprobieren. Die erste besteht darin, es selbst herunterzuladen und zu installieren. Die zweite besteht darin, [Docker](https://www.docker.com/products/docker-engine) zu verwenden.
### Herunterladen und Installieren/Ausführen
Fess 14.17 ist jetzt verfügbar und kann auf der [Release-Seite](https://github.com/codelibs/fess/releases "download") heruntergeladen werden. Downloads gibt es in drei Formaten: deb, rpm, zip.
Die folgenden Befehle zeigen, wie der Zip-Download verwendet wird:
$ unzip fess-14.17.x.zip
$ cd fess-14.17.x
$ ./bin/fess
Weitere Informationen finden Sie im [Installationshandbuch](https://fess.codelibs.org/14.17/install/index.html).
### Docker
Wir bieten Docker-Images auf [ghcr.io](https://github.com/orgs/codelibs/packages) an. Wir stellen auch eine Docker Compose (YAML)-Datei in [diesem Repository](https://github.com/codelibs/docker-fess/tree/master/compose) bereit.
### Browser-Benutzeroberfläche
- Suchoberfläche: http://localhost:8080/
![Suchoberfläche](https://fess.codelibs.org/_images/fess_search_result1.png)
- Administrationsoberfläche: http://localhost:8080/admin/ (Standard-Benutzername/Passwort ist admin/admin)
![Administrationsoberfläche](https://fess.codelibs.org/_images/fess_admin_dashboard.png)
Sie können in der Administrationsoberfläche (Web, Datei, Datenspeicher) Crawling-Ziele in den Crawler-Konfigurationsseiten registrieren und den Crawler manuell auf der [Scheduler-Seite](https://fess.codelibs.org/14.17/admin/scheduler-guide.html) starten.
## Migration von einem anderen Suchanbieter
Bitte lesen Sie [MIGRATION.md](MIGRATION.md).
## Datenspeicher
Derzeit unterstützt Fess das Crawlen der folgenden [Speicherorte und APIs](https://fess.codelibs.org/14.17/admin/dataconfig-guide.html):
- [Confluence/Jira](https://github.com/codelibs/fess-ds-atlassian)
- [Box](https://github.com/codelibs/fess-ds-box)
- [CSV](https://github.com/codelibs/fess-ds-csv)
- [Datenbank](https://github.com/codelibs/fess-ds-db)
- [Dropbox](https://github.com/codelibs/fess-ds-dropbox)
- [Elasticsearch](https://github.com/codelibs/fess-ds-elasticsearch)
- [Git](https://github.com/codelibs/fess-ds-git)
- [Gitbucket](https://github.com/codelibs/fess-ds-gitbucket)
- [G Suite](https://github.com/codelibs/fess-ds-gsuite)
- [JSON](https://github.com/codelibs/fess-ds-json)
- [Office 365](https://github.com/codelibs/fess-ds-office365)
- [S3](https://github.com/codelibs/fess-ds-s3)
- [Salesforce](https://github.com/codelibs/fess-ds-salesforce)
- [SharePoint](https://github.com/codelibs/fess-ds-sharepoint)
- [Slack](https://github.com/codelibs/fess-ds-slack)
## Themen
- [Simple](https://github.com/codelibs/fess-theme-simple)
- [Classic](https://github.com/codelibs/fess-theme-classic)
## Ingest
- [Logger](https://github.com/codelibs/fess-ingest-logger)
- [NDJSON](https://github.com/codelibs/fess-ingest-ndjson)
## Skript
- [Groovy](https://github.com/codelibs/fess-script-groovy)
- [OGNL](https://github.com/codelibs/fess-script-ognl)
## Entwicklungsinformationen
### Quellcode abrufen
1. Klonen Sie das Fess-Repository:
```
$ cd ~/workspace
$ git clone https://github.com/codelibs/fess.git
```
2. Importieren Sie das geklonte Repository als ein [Maven](https://maven.apache.org/) Projekt in [Eclipse](https://www.eclipse.org/eclipseide/) oder einer anderen IDE.
### Einrichten von OpenSearch-Plugins
Führen Sie antrun:run aus, um Plugins in das Plugins-Verzeichnis herunterzuladen:
$ mvn antrun:run
### Fess ausführen
Führen Sie `org.codelibs.fess.FessBoot` in Ihrer IDE aus oder debuggen Sie es und greifen Sie dann auf http://localhost:8080/ zu.
### Paket erstellen
Führen Sie das `package`-Ziel aus, und dann wird die Release-Datei im Verzeichnis target/releases erstellt.
$ mvn package
$ mvn rpm:rpm # .rpm-Paket
$ mvn jdeb:jdeb # .deb-Paket
### Quellcode generieren
$ mvn dbflute:download # (einmaliger Befehl)
$ mvn dbflute:freegen
$ mvn license:format
### Integrationstests
Starten Sie den Fess-Server und führen Sie den folgenden Befehl aus:
$ mvn test -P integrationTests -Dtest.fess.url="http://localhost:8080" -Dtest.search_engine.url="http://localhost:9201"
Um einen einzelnen Testfall auszuführen, können Sie verwenden:
$ mvn test -P integrationTests -Dtest.fess.url="http://localhost:8080" -Dtest.search_engine.url="http://localhost:9201" -Dtest=SearchApiTests
### In Ihre Sprache übersetzen
Fess ist eine internationalisierte Software.
Wenn Sie Labels/Nachrichten für Ihre Sprache hinzufügen möchten, übersetzen Sie bitte die Eigenschaftendatei und benennen Sie sie in fess\_\*\_[lang].properties um.
* [fess_label_en.properties](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_label_en.properties)
* [fess_message_en.properties](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_message_en.properties)
Für den Such-/Index-Analyser: Wenn [doc.json](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_indices/fess/doc.json) lang\_[lang] für Ihre Sprache enthält, passen Sie bitte den Analyser für Ihre Sprache an. Weitere Informationen zu Analysatoren finden Sie in der [OpenSearch-Dokumentation](https://opensearch.org/docs/latest/analyzers/search-analyzers/).
Wir begrüßen Pull-Requests für Ihre Sprache.
## Unterstützt von
* [Lasta Di](https://github.com/lastaflute/lasta-di "Lasta Di"): DI-Container
* [LastaFlute](https://github.com/lastaflute/lastaflute "LastaFlute"): Web-Framework
* [Lasta Job](https://github.com/lastaflute/lasta-job "Lasta Job"): Job-Scheduler
* [Fess Crawler](https://github.com/codelibs/fess-crawler "Fess Crawler"): Web-Crawler
* [OpenSearch](https://opensearch.org/ "OpenSearch"): Suchmaschine

View file

@ -1,159 +0,0 @@
# Fess: Servidor de Búsqueda Empresarial
[![Java CI with Maven](https://github.com/codelibs/fess/actions/workflows/maven.yml/badge.svg)](https://github.com/codelibs/fess/actions/workflows/maven.yml)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.codelibs.fess/fess/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.codelibs.fess/fess)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/gitbucket/gitbucket/blob/master/LICENSE)
## Resumen
Fess es un servidor de búsqueda empresarial muy potente y fácil de desplegar. Puedes instalar y ejecutar Fess rápidamente en cualquier plataforma que sea capaz de ejecutar el entorno de ejecución de Java (Java Runtime Environment). Fess se distribuye bajo la [Licencia Apache 2.0](LICENSE).
Fess está basado en [OpenSearch](https://github.com/opensearch-project/OpenSearch), pero no se requiere conocimiento o experiencia en OpenSearch. Fess proporciona una GUI de administración fácil de usar para configurar el sistema a través de tu navegador.
Fess también incluye un rastreador (crawler), que puede rastrear documentos en un [servidor web](https://fess.codelibs.org/14.17/admin/webconfig-guide.html), [sistema de archivos](https://fess.codelibs.org/14.17/admin/fileconfig-guide.html), o [almacenamiento de datos](https://fess.codelibs.org/14.17/admin/dataconfig-guide.html) (como un archivo CSV o base de datos). Se admiten muchos formatos de archivos, incluidos (pero no limitados a): Microsoft Office, PDF y zip.
*[Fess Site Search](https://github.com/codelibs/fess-site-search)* es una alternativa gratuita a [Google Site Search](https://enterprise.google.com/search/products/gss.html). Para más detalles, consulta la [documentación de FSS JS Generator](https://fss-generator.codelibs.org/docs/manual).
## Sitio web
[fess.codelibs.org](https://fess.codelibs.org/)
## Problemas/Preguntas
[discuss.codelibs.org](https://discuss.codelibs.org/c/FessEN/)
## Cómo Empezar
Hay dos maneras de probar Fess. La primera es descargar e instalarlo tú mismo. La segunda es usar [Docker](https://www.docker.com/products/docker-engine).
### Descargar e Instalar/Ejecutar
Fess 14.17 ya está disponible y se puede descargar en la [página de lanzamientos](https://github.com/codelibs/fess/releases "download"). Las descargas están disponibles en 3 formatos: deb, rpm y zip.
Los siguientes comandos muestran cómo usar la descarga en formato zip:
$ unzip fess-14.17.x.zip
$ cd fess-14.17.x
$ ./bin/fess
Para más detalles, consulta la [Guía de Instalación](https://fess.codelibs.org/14.17/install/index.html).
### Docker
Proporcionamos imágenes de Docker en [ghcr.io](https://github.com/orgs/codelibs/packages). También proporcionamos un archivo Docker Compose (YAML) en [este repositorio](https://github.com/codelibs/docker-fess/tree/master/compose).
### Interfaz de Usuario en el Navegador
- Interfaz de búsqueda: http://localhost:8080/
![Interfaz de Búsqueda](https://fess.codelibs.org/_images/fess_search_result1.png)
- Interfaz de administración: http://localhost:8080/admin/ (el nombre de usuario/contraseña por defecto es admin/admin)
![Interfaz de Administración](https://fess.codelibs.org/_images/fess_admin_dashboard.png)
Puedes registrar los objetivos de rastreo en la interfaz de administración en las páginas de configuración del rastreador (Web, Archivo, Almacenamiento de Datos), y luego iniciar el rastreador manualmente en la [página del Programador](https://fess.codelibs.org/14.17/admin/scheduler-guide.html).
## Migración desde otro proveedor de búsqueda
Consulta [MIGRATION.md](MIGRATION.md).
## Almacenamiento de Datos
Actualmente, Fess admite el rastreo de las siguientes [ubicaciones de almacenamiento y APIs](https://fess.codelibs.org/14.17/admin/dataconfig-guide.html):
- [Confluence/Jira](https://github.com/codelibs/fess-ds-atlassian)
- [Box](https://github.com/codelibs/fess-ds-box)
- [CSV](https://github.com/codelibs/fess-ds-csv)
- [Database](https://github.com/codelibs/fess-ds-db)
- [Dropbox](https://github.com/codelibs/fess-ds-dropbox)
- [Elasticsearch](https://github.com/codelibs/fess-ds-elasticsearch)
- [Git](https://github.com/codelibs/fess-ds-git)
- [Gitbucket](https://github.com/codelibs/fess-ds-gitbucket)
- [G Suite](https://github.com/codelibs/fess-ds-gsuite)
- [JSON](https://github.com/codelibs/fess-ds-json)
- [Office 365](https://github.com/codelibs/fess-ds-office365)
- [S3](https://github.com/codelibs/fess-ds-s3)
- [Salesforce](https://github.com/codelibs/fess-ds-salesforce)
- [SharePoint](https://github.com/codelibs/fess-ds-sharepoint)
- [Slack](https://github.com/codelibs/fess-ds-slack)
## Tema
- [Simple](https://github.com/codelibs/fess-theme-simple)
- [Classic](https://github.com/codelibs/fess-theme-classic)
## Ingesta
- [Logger](https://github.com/codelibs/fess-ingest-logger)
- [NDJSON](https://github.com/codelibs/fess-ingest-ndjson)
## Script
- [Groovy](https://github.com/codelibs/fess-script-groovy)
- [OGNL](https://github.com/codelibs/fess-script-ognl)
## Información de Desarrollo
### Obtener el Código Fuente
1. Clona el repositorio de Fess:
```
$ cd ~/workspace
$ git clone https://github.com/codelibs/fess.git
```
2. Importa el repositorio clonado como un proyecto [Maven](https://maven.apache.org/) en [Eclipse](https://www.eclipse.org/eclipseide/) u otro IDE.
### Configuración de Plugins para OpenSearch
Ejecuta antrun:run para descargar los plugins en el directorio de plugins:
$ mvn antrun:run
### Ejecutar Fess
Ejecuta o depura `org.codelibs.fess.FessBoot` en tu IDE, y luego accede a http://localhost:8080/
### Construir el Paquete
Ejecuta el objetivo `package` y luego se creará el archivo de lanzamiento en target/releases.
$ mvn package
$ mvn rpm:rpm # Paquete .rpm
$ mvn jdeb:jdeb # Paquete .deb
### Generar Código Fuente
$ mvn dbflute:download # (comando ejecutado una sola vez)
$ mvn dbflute:freegen
$ mvn license:format
### Pruebas de Integración
Inicia el servidor Fess y ejecuta el siguiente comando:
$ mvn test -P integrationTests -Dtest.fess.url="http://localhost:8080" -Dtest.search_engine.url="http://localhost:9201"
Para ejecutar un único caso de prueba, puedes usar:
$ mvn test -P integrationTests -Dtest.fess.url="http://localhost:8080" -Dtest.search_engine.url="http://localhost:9201" -Dtest=SearchApiTests
### Traducir a Tu Idioma
Fess es un software internacionalizado.
Si deseas agregar etiquetas/mensajes para tu idioma, por favor traduce el archivo de propiedades y renómbralo a fess\_\*\_[lang].properties.
* [fess_label_en.properties](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_label_en.properties)
* [fess_message_en.properties](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_message_en.properties)
Para el analizador de búsqueda/índices, si [doc.json](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_indices/fess/doc.json) contiene lang\_[lang] para tu idioma, por favor modifica el analizador para tu idioma. Para más detalles sobre los analizadores, consulta la [documentación de OpenSearch](https://opensearch.org/docs/latest/analyzers/search-analyzers/).
Damos la bienvenida a pull requests para tu idioma.
## Impulsado por
* [Lasta Di](https://github.com/lastaflute/lasta-di "Lasta Di"): Contenedor DI
* [LastaFlute](https://github.com/lastaflute/lastaflute "LastaFlute"): Framework Web
* [Lasta Job](https://github.com/lastaflute/lasta-job "Lasta Job"): Programador de Tareas
* [Fess Crawler](https://github.com/codelibs/fess-crawler "Fess Crawler"): Rastreador Web
* [OpenSearch](https://opensearch.org/ "OpenSearch"): Motor de Búsqueda

View file

@ -1,169 +0,0 @@
# Fess : Serveur de recherche pour entreprises
[![Java CI with Maven](https://github.com/codelibs/fess/actions/workflows/maven.yml/badge.svg)](https://github.com/codelibs/fess/actions/workflows/maven.yml)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.codelibs.fess/fess/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.codelibs.fess/fess)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/gitbucket/gitbucket/blob/master/LICENSE)
## Vue d'ensemble
Fess est un serveur de recherche très puissant et facilement déployable pour les entreprises. Vous pouvez rapidement installer et exécuter Fess sur toute plateforme où vous pouvez exécuter l'environnement d'exécution Java. Fess est fourni sous la licence [Apache License 2.0](LICENSE).
Fess est basé sur [OpenSearch](https://github.com/opensearch-project/OpenSearch), mais aucune connaissance ni expérience d'OpenSearch n'est _nécessaire_. Fess fournit une interface d'administration facile à utiliser pour configurer le système via votre navigateur.
Fess comprend également un Crawler, capable d'explorer les documents sur un [serveur web](https://fess.codelibs.org/14.17/admin/webconfig-guide.html), un [système de fichiers](https://fess.codelibs.org/14.17/admin/fileconfig-guide.html), ou un [Data Store](https://fess.codelibs.org/14.17/admin/dataconfig-guide.html) (comme un fichier CSV ou une base de données). De nombreux formats de fichiers sont pris en charge, y compris (mais sans s'y limiter) : Microsoft Office, PDF, et zip.
*[Fess Site Search](https://github.com/codelibs/fess-site-search)* est une alternative gratuite à [Google Site Search](https://enterprise.google.com/search/products/gss.html). Pour plus de détails, consultez la [documentation FSS JS Generator](https://fss-generator.codelibs.org/docs/manual).
## Site Web
[fess.codelibs.org](https://fess.codelibs.org/)
## Problèmes/Questions
[discuss.codelibs.org](https://discuss.codelibs.org/c/FessEN/)
## Démarrage rapide
Il existe 2 manières d'essayer Fess. La première est de le télécharger et l'installer vous-même. La seconde est d'utiliser [Docker](https://www.docker.com/products/docker-engine).
### Télécharger et Installer/Exécuter
Fess 14.17 est désormais disponible et peut être téléchargé sur la [page de Releases](https://github.com/codelibs/fess/releases "download"). Les téléchargements sont disponibles en 3 formats : deb, rpm, zip.
Les commandes suivantes montrent comment utiliser le téléchargement zip :
$ unzip fess-14.17.x.zip
$ cd fess-14.17.x
$ ./bin/fess
Pour plus de détails, consultez le [guide d'installation](https://fess.codelibs.org/14.17/install/index.html).
### Docker
Nous fournissons des images Docker sur [ghcr.io](https://github.com/orgs/codelibs/packages). Nous fournissons également un fichier Docker Compose (YAML) dans [ce dépôt](https://github.com/codelibs/docker-fess/tree/master/compose).
### Interface Web
- Interface de recherche : http://localhost:8080/
![Search UI](https://fess.codelibs.org/_images/fess_search_result1.png)
- Interface d'administration : http://localhost:8080/admin/ (nom d'utilisateur/mot de passe par défaut : admin/admin)
![Admin UI](https://fess.codelibs.org/_images/fess_admin_dashboard.png)
Vous pouvez enregistrer des cibles à explorer dans l'interface d'administration sur les pages de configuration des crawlers (Web, Fichiers, Data Store), puis démarrer manuellement le Crawler sur la [page du Planificateur](https://fess.codelibs.org/14.17/admin/scheduler-guide.html).
## Migration depuis un autre fournisseur de recherche
Veuillez consulter [MIGRATION.md](MIGRATION.md).
## Data Store
Actuellement, Fess prend en charge le parcours des [emplacements de stockage et API](https://fess.codelibs.org/14.17/admin/dataconfig-guide.html) suivants :
- [Confluence/Jira](https://github.com/codelibs/fess-ds-atlassian)
- [Box](https://github.com/codelibs/fess-ds-box)
- [CSV](https://github.com/codelibs/fess-ds-csv)
- [Base de données](https://github.com/codelibs/fess-ds-db)
- [Dropbox](https://github.com/codelibs/fess-ds-dropbox)
- [Elasticsearch](https://github.com/codelibs/fess-ds-elasticsearch)
- [Git](https://github.com/codelibs/fess-ds-git)
- [Gitbucket](https://github.com/codelibs/fess-ds-gitbucket)
- [G Suite](https://github.com/codelibs/fess-ds-gsuite)
- [JSON](https://github.com/codelibs/fess-ds-json)
- [Office 365](https://github.com/codelibs/fess-ds-office365)
- [S3](https://github.com/codelibs/fess-ds-s3)
- [Salesforce](https://github.com/codelibs/fess-ds-salesforce)
- [SharePoint](https://github.com/codelibs/fess-ds-sharepoint)
- [Slack](https://github.com/codelibs/fess-ds-slack)
## Thèmes
- [Simple](https://github.com/codelibs/fess-theme-simple)
- [Classique](https://github.com/codelibs/fess-theme-classic)
## Ingest
- [Logger](https://github.com/codelibs/fess-ingest-logger)
- [NDJSON](https://github.com/codelibs/fess-ingest-ndjson)
## Scripts
- [Groovy](https://github.com/codelibs/fess-script-groovy)
- [OGNL](https://github.com/codelibs/fess-script-ognl)
## Localisation
### Japonais
- [Site Web](https://fess.codelibs.org/ja/)
### Coréen
- [Forum](https://github.com/nocode2k/fess-kr-forum)
## Informations de Développement
### Récupérer le Code Source
1. Clonez le dépôt Fess :
```
$ cd ~/workspace
$ git clone https://github.com/codelibs/fess.git
```
2. Importez le dépôt cloné en tant que projet [Maven](https://maven.apache.org/) sur [Eclipse](https://www.eclipse.org/eclipseide/) ou un autre IDE.
### Configuration pour les Plugins OpenSearch
Exécutez antrun:run pour télécharger les plugins dans le répertoire plugins :
$ mvn antrun:run
### Exécuter Fess
Exécutez ou déboguez org.codelibs.fess.FessBoot dans votre IDE, puis accédez à http://localhost:8080/
### Créer un Package
Exécutez la commande `package` et le fichier de release sera créé dans target/releases.
$ mvn package
$ mvn rpm:rpm # package .rpm
$ mvn jdeb:jdeb # package .deb
### Générer le Code Source
$ mvn dbflute:download # (commande unique)
$ mvn dbflute:freegen
$ mvn license:format
### Tests d'Intégration
Lancez le serveur Fess et exécutez la commande suivante :
$ mvn test -P integrationTests -Dtest.fess.url="http://localhost:8080" -Dtest.search_engine.url="http://localhost:9201"
Pour exécuter un seul cas de test, vous pouvez utiliser :
$ mvn test -P integrationTests -Dtest.fess.url="http://localhost:8080" -Dtest.search_engine.url="http://localhost:9201" -Dtest=SearchApiTests
### Traduire dans Votre Langue
Fess est un logiciel internationalisé.
Si vous souhaitez ajouter des libellés/messages pour votre langue, veuillez traduire le fichier de propriétés et le renommer en fess\_\*\_[lang].properties.
* [fess_label_en.properties](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_label_en.properties)
* [fess_message_en.properties](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_message_en.properties)
Pour l'analyseur de recherche/index, si [doc.json](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_indices/fess/doc.json) contient lang\_[lang] pour votre langue, veuillez modifier l'analyseur pour votre langue. Pour plus de détails sur les analyseurs, consultez la [documentation OpenSearch](https://opensearch.org/docs/latest/analyzers/search-analyzers/).
Nous accueillons les pull requests pour votre langue.
## Alimenté par
* [Lasta Di](https://github.com/lastaflute/lasta-di "Lasta Di") : Conteneur DI
* [LastaFlute](https://github.com/lastaflute/lastaflute "LastaFlute") : Framework Web
* [Lasta Job](https://github.com/lastaflute/lasta-job "Lasta Job") : Planificateur de tâches
* [Fess Crawler](https://github.com/codelibs/fess-crawler "Fess Crawler") : Crawler Web
* [OpenSearch](https://opensearch.org/ "OpenSearch") : Moteur de recherche

View file

@ -1,158 +0,0 @@
# Fess: エンタープライズ検索サーバー
[![Java CI with Maven](https://github.com/codelibs/fess/actions/workflows/maven.yml/badge.svg)](https://github.com/codelibs/fess/actions/workflows/maven.yml)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.codelibs.fess/fess/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.codelibs.fess/fess)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/gitbucket/gitbucket/blob/master/LICENSE)
## 概要
Fessは非常に強力で、簡単に導入できるエンタープライズ検索サーバーです。FessはJavaランタイム環境が動作する任意のプラットフォーム上で簡単にインストールして実行できます。Fessは[Apache License 2.0](LICENSE)の下で提供されています。
Fessは[OpenSearch](https://github.com/opensearch-project/OpenSearch)をベースにしていますが、OpenSearchに関する知識や経験は**不要**です。Fessは、ブラウザを介してシステムを簡単に設定できる管理者向けのGUIを提供しています。Fessにはクローラも含まれており、[Webサーバー](https://fess.codelibs.org/14.17/admin/webconfig-guide.html)、[ファイルシステム](https://fess.codelibs.org/14.17/admin/fileconfig-guide.html)、または[データストア](https://fess.codelibs.org/14.17/admin/dataconfig-guide.html)CSVやデータベースなどのドキュメントをクロールできます。Microsoft Office、PDF、zipなど、多くのファイル形式に対応しています。
*[Fess Site Search](https://github.com/codelibs/fess-site-search)*は、[Google Site Search](https://enterprise.google.com/search/products/gss.html)の無料代替です。詳細については、[FSS JS Generatorのドキュメント](https://fss-generator.codelibs.org/docs/manual)を参照してください。
## 公式サイト
[fess.codelibs.org](https://fess.codelibs.org/)
## 問題や質問
[discuss.codelibs.org](https://discuss.codelibs.org/c/FessEN/)
## はじめに
Fessを試す方法は2つあります。1つは自分でダウンロードしてインストールする方法、もう1つは[Docker](https://www.docker.com/products/docker-engine)を使用する方法です。
### ダウンロードおよびインストール/実行
Fess 14.17が利用可能で、[リリースページ](https://github.com/codelibs/fess/releases "download")からダウンロードできます。ダウンロードには、deb、rpm、zipの3つの形式があります。
以下のコマンドは、zipファイルを使用する例です
$ unzip fess-14.17.x.zip
$ cd fess-14.17.x
$ ./bin/fess
詳細については、[インストールガイド](https://fess.codelibs.org/14.17/install/index.html)を参照してください。
### Docker
[ghcr.io](https://github.com/orgs/codelibs/packages)にDockerイメージを提供しています。また、このリポジトリにはDocker ComposeYAMLファイルも用意されています。[こちらのリポジトリ](https://github.com/codelibs/docker-fess/tree/master/compose)で確認できます。
### ブラウザUI
- 検索UI: http://localhost:8080/
![Search UI](https://fess.codelibs.org/_images/fess_search_result1.png)
- 管理者UI: http://localhost:8080/admin/ (デフォルトのユーザー名/パスワードはadmin/adminです
![Admin UI](https://fess.codelibs.org/_images/fess_admin_dashboard.png)
管理者UIでは、Web、ファイル、データストアクローラの設定ページでクロール対象を登録し、[スケジューラページ](https://fess.codelibs.org/14.17/admin/scheduler-guide.html)から手動でクローラを開始できます。
## 他の検索プロバイダーからの移行
[MIGRATION.md](MIGRATION.md)を参照してください。
## データストア
現在、Fessは以下の[ストレージロケーションとAPI](https://fess.codelibs.org/14.17/admin/dataconfig-guide.html)のクロールをサポートしています:
- [Confluence/Jira](https://github.com/codelibs/fess-ds-atlassian)
- [Box](https://github.com/codelibs/fess-ds-box)
- [CSV](https://github.com/codelibs/fess-ds-csv)
- [Database](https://github.com/codelibs/fess-ds-db)
- [Dropbox](https://github.com/codelibs/fess-ds-dropbox)
- [Elasticsearch](https://github.com/codelibs/fess-ds-elasticsearch)
- [Git](https://github.com/codelibs/fess-ds-git)
- [Gitbucket](https://github.com/codelibs/fess-ds-gitbucket)
- [G Suite](https://github.com/codelibs/fess-ds-gsuite)
- [JSON](https://github.com/codelibs/fess-ds-json)
- [Office 365](https://github.com/codelibs/fess-ds-office365)
- [S3](https://github.com/codelibs/fess-ds-s3)
- [Salesforce](https://github.com/codelibs/fess-ds-salesforce)
- [SharePoint](https://github.com/codelibs/fess-ds-sharepoint)
- [Slack](https://github.com/codelibs/fess-ds-slack)
## テーマ
- [Simple](https://github.com/codelibs/fess-theme-simple)
- [Classic](https://github.com/codelibs/fess-theme-classic)
## Ingest
- [Logger](https://github.com/codelibs/fess-ingest-logger)
- [NDJSON](https://github.com/codelibs/fess-ingest-ndjson)
## スクリプト
- [Groovy](https://github.com/codelibs/fess-script-groovy)
- [OGNL](https://github.com/codelibs/fess-script-ognl)
## 開発情報
### ソースコードの取得
1. Fessのリポジトリをクローンします
```
$ cd ~/workspace
$ git clone https://github.com/codelibs/fess.git
```
2. クローンしたリポジトリを、[Maven](https://maven.apache.org/)プロジェクトとして[Eclipse](https://www.eclipse.org/eclipseide/)や他のIDEにインポートします。
### OpenSearchプラグインのセットアップ
antrun:runを実行して、プラグインをpluginsディレクトリにダウンロードします
$ mvn antrun:run
### Fessの実行
IDE上で`org.codelibs.fess.FessBoot`を実行またはデバッグし、http://localhost:8080/ にアクセスします。
### パッケージのビルド
`package`ゴールを実行すると、releaseファイルがtarget/releasesディレクトリに作成されます。
$ mvn package
$ mvn rpm:rpm # .rpmパッケージ
$ mvn jdeb:jdeb # .debパッケージ
### ソースコードの生成
$ mvn dbflute:download # (一度だけ実行)
$ mvn dbflute:freegen
$ mvn license:format
### 統合テスト
Fessサーバーを起動し、以下のコマンドを実行します
$ mvn test -P integrationTests -Dtest.fess.url="http://localhost:8080" -Dtest.search_engine.url="http://localhost:9201"
単一のテストケースを実行するには、以下のコマンドを使用できます:
$ mvn test -P integrationTests -Dtest.fess.url="http://localhost:8080" -Dtest.search_engine.url="http://localhost:9201" -Dtest=SearchApiTests
### あなたの言語への翻訳
Fessは国際化対応ソフトウェアです。
ラベルやメッセージをあなたの言語に追加したい場合、プロパティファイルを翻訳してから`fess\_\*\_[lang].properties`という名前に変更してください。
* [fess_label_en.properties](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_label_en.properties)
* [fess_message_en.properties](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_message_en.properties)
検索/インデックスアナライザーの設定については、[doc.json](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_indices/fess/doc.json)に言語別の`lang\_[lang]`が含まれているか確認し、その言語に合わせてアナライザーを修正してください。アナライザーに関する詳細は、[OpenSearchのドキュメント](https://opensearch.org/docs/latest/analyzers/search-analyzers/)を参照してください。
私たちは、あなたの言語でのプルリクエストを歓迎します。
## Powered By
* [Lasta Di](https://github.com/lastaflute/lasta-di "Lasta Di"): DIコンテナ
* [LastaFlute](https://github.com/lastaflute/lastaflute "LastaFlute"): Webフレームワーク
* [Lasta Job](https://github.com/lastaflute/lasta-job "Lasta Job"): ジョブスケジューラ
* [Fess Crawler](https://github.com/codelibs/fess-crawler "Fess Crawler"): Webクローラ
* [OpenSearch](https://opensearch.org/ "OpenSearch"): 検索エンジン

View file

@ -1,158 +0,0 @@
# Fess: 엔터프라이즈 검색 서버
[![Java CI with Maven](https://github.com/codelibs/fess/actions/workflows/maven.yml/badge.svg)](https://github.com/codelibs/fess/actions/workflows/maven.yml)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.codelibs.fess/fess/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.codelibs.fess/fess)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/gitbucket/gitbucket/blob/master/LICENSE)
## 개요
Fess는 매우 강력하고 쉽게 배포 가능한 엔터프라이즈 검색 서버입니다. 자바 런타임 환경(Java Runtime Environment)을 실행할 수 있는 모든 플랫폼에서 Fess를 빠르게 설치하고 실행할 수 있습니다. Fess는 [Apache License 2.0](LICENSE)에 따라 제공됩니다.
Fess는 [OpenSearch](https://github.com/opensearch-project/OpenSearch)를 기반으로 하지만, OpenSearch에 대한 지식이나 경험은 필요하지 않습니다. Fess는 브라우저를 통해 시스템을 구성할 수 있는 사용하기 쉬운 관리 GUI를 제공합니다. 또한 Fess는 [웹 서버](https://fess.codelibs.org/14.17/admin/webconfig-guide.html), [파일 시스템](https://fess.codelibs.org/14.17/admin/fileconfig-guide.html), 또는 [데이터 저장소](https://fess.codelibs.org/14.17/admin/dataconfig-guide.html)에서 문서를 크롤링할 수 있는 크롤러도 포함하고 있습니다(CSV 또는 데이터베이스와 같은). Microsoft Office, PDF, zip을 포함한 다양한 파일 형식을 지원합니다.
*[Fess 사이트 검색](https://github.com/codelibs/fess-site-search)*은 [Google 사이트 검색](https://enterprise.google.com/search/products/gss.html)의 무료 대안입니다. 자세한 내용은 [FSS JS 생성기 문서](https://fss-generator.codelibs.org/docs/manual)를 참조하십시오.
## 웹사이트
[fess.codelibs.org](https://fess.codelibs.org/)
## 문제/질문
[discuss.codelibs.org](https://discuss.codelibs.org/c/FessEN/)
## 시작하기
Fess를 사용해보는 방법은 두 가지가 있습니다. 첫 번째는 직접 다운로드하여 설치하는 방법이며, 두 번째는 [Docker](https://www.docker.com/products/docker-engine)를 사용하는 방법입니다.
### 다운로드 및 설치/실행
Fess 14.17이 현재 사용 가능하며, [릴리스 페이지](https://github.com/codelibs/fess/releases "download")에서 다운로드할 수 있습니다. 다운로드는 deb, rpm, zip의 세 가지 형식으로 제공됩니다.
다음 명령은 zip 다운로드 사용 방법을 보여줍니다:
$ unzip fess-14.17.x.zip
$ cd fess-14.17.x
$ ./bin/fess
자세한 내용은 [설치 가이드](https://fess.codelibs.org/14.17/install/index.html)를 참조하십시오.
### Docker
우리는 [ghcr.io](https://github.com/orgs/codelibs/packages)에서 Docker 이미지를 제공합니다. 또한 [이 리포지토리](https://github.com/codelibs/docker-fess/tree/master/compose)에 Docker Compose (YAML) 파일도 제공합니다.
### 브라우저 UI
- 검색 UI: http://localhost:8080/
![검색 UI](https://fess.codelibs.org/_images/fess_search_result1.png)
- 관리자 UI: http://localhost:8080/admin/ (기본 사용자 이름/비밀번호는 admin/admin입니다)
![관리자 UI](https://fess.codelibs.org/_images/fess_admin_dashboard.png)
관리자 UI에서는 (웹, 파일, 데이터 저장소) 크롤러 구성 페이지에서 크롤링 대상을 등록한 다음, [스케줄러 페이지](https://fess.codelibs.org/14.17/admin/scheduler-guide.html)에서 크롤러를 수동으로 시작할 수 있습니다.
## 다른 검색 제공자에서의 마이그레이션
[MIGRATION.md](MIGRATION.md)를 참조하십시오.
## 데이터 저장소
현재 Fess는 다음 [저장소 위치 및 API](https://fess.codelibs.org/14.17/admin/dataconfig-guide.html)를 크롤링할 수 있습니다:
- [Confluence/Jira](https://github.com/codelibs/fess-ds-atlassian)
- [Box](https://github.com/codelibs/fess-ds-box)
- [CSV](https://github.com/codelibs/fess-ds-csv)
- [Database](https://github.com/codelibs/fess-ds-db)
- [Dropbox](https://github.com/codelibs/fess-ds-dropbox)
- [Elasticsearch](https://github.com/codelibs/fess-ds-elasticsearch)
- [Git](https://github.com/codelibs/fess-ds-git)
- [Gitbucket](https://github.com/codelibs/fess-ds-gitbucket)
- [G Suite](https://github.com/codelibs/fess-ds-gsuite)
- [JSON](https://github.com/codelibs/fess-ds-json)
- [Office 365](https://github.com/codelibs/fess-ds-office365)
- [S3](https://github.com/codelibs/fess-ds-s3)
- [Salesforce](https://github.com/codelibs/fess-ds-salesforce)
- [SharePoint](https://github.com/codelibs/fess-ds-sharepoint)
- [Slack](https://github.com/codelibs/fess-ds-slack)
## 테마
- [Simple](https://github.com/codelibs/fess-theme-simple)
- [Classic](https://github.com/codelibs/fess-theme-classic)
## 인게스트
- [Logger](https://github.com/codelibs/fess-ingest-logger)
- [NDJSON](https://github.com/codelibs/fess-ingest-ndjson)
## 스크립트
- [Groovy](https://github.com/codelibs/fess-script-groovy)
- [OGNL](https://github.com/codelibs/fess-script-ognl)
## 개발 정보
### 소스 코드 얻기
1. Fess 리포지토리를 클론합니다:
```
$ cd ~/workspace
$ git clone https://github.com/codelibs/fess.git
```
2. 클론한 리포지토리를 [Maven](https://maven.apache.org/) 프로젝트로 [Eclipse](https://www.eclipse.org/eclipseide/) 또는 다른 IDE에서 가져옵니다.
### OpenSearch 플러그인 설정
antrun:run을 실행하여 플러그인을 플러그인 디렉토리에 다운로드합니다:
$ mvn antrun:run
### Fess 실행
IDE에서 `org.codelibs.fess.FessBoot`을 실행하거나 디버그하고 http://localhost:8080/에 접속합니다.
### 패키지 빌드
`package` 목표를 실행하면 릴리스 파일이 target/releases 디렉토리에 생성됩니다.
$ mvn package
$ mvn rpm:rpm # .rpm 패키지
$ mvn jdeb:jdeb # .deb 패키지
### 소스 코드 생성
$ mvn dbflute:download # (한 번만 실행)
$ mvn dbflute:freegen
$ mvn license:format
### 통합 테스트
Fess 서버를 시작하고 다음 명령을 실행합니다:
$ mvn test -P integrationTests -Dtest.fess.url="http://localhost:8080" -Dtest.search_engine.url="http://localhost:9201"
단일 테스트 케이스를 실행하려면 다음을 사용할 수 있습니다:
$ mvn test -P integrationTests -Dtest.fess.url="http://localhost:8080" -Dtest.search_engine.url="http://localhost:9201" -Dtest=SearchApiTests
### 언어 번역
Fess는 국제화된 소프트웨어입니다.
귀하의 언어로 라벨/메시지를 추가하려면 속성 파일을 번역한 후 fess\_\*\_[lang].properties로 이름을 바꾸십시오.
* [fess_label_en.properties](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_label_en.properties)
* [fess_message_en.properties](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_message_en.properties)
검색/인덱스 분석기와 관련해서, [doc.json](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_indices/fess/doc.json)이 귀하의 언어에 대한 lang\_[lang]을 포함하는 경우, 해당 언어에 맞게 분석기를 수정하십시오. 분석기에 대한 자세한 내용은 [OpenSearch 문서](https://opensearch.org/docs/latest/analyzers/search-analyzers/)를 참조하십시오.
귀하의 언어로 된 풀 리퀘스트를 환영합니다.
## 제공된 기술
* [Lasta Di](https://github.com/lastaflute/lasta-di "Lasta Di"): DI 컨테이너
* [LastaFlute](https://github.com/lastaflute/lastaflute "LastaFlute"): 웹 프레임워크
* [Lasta Job](https://github.com/lastaflute/lasta-job "Lasta Job"): 작업 스케줄러
* [Fess Crawler](https://github.com/codelibs/fess-crawler "Fess Crawler"): 웹 크롤러
* [OpenSearch](https://opensearch.org/ "OpenSearch"): 검색 엔진

View file

@ -1,159 +0,0 @@
# Fess: Servidor de Busca Empresarial
[![Java CI with Maven](https://github.com/codelibs/fess/actions/workflows/maven.yml/badge.svg)](https://github.com/codelibs/fess/actions/workflows/maven.yml)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.codelibs.fess/fess/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.codelibs.fess/fess)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/gitbucket/gitbucket/blob/master/LICENSE)
## Visão Geral
Fess é um servidor de busca empresarial muito poderoso e fácil de implantar. Você pode instalar e executar o Fess rapidamente em qualquer plataforma que suporte o Java Runtime Environment. O Fess é fornecido sob a [Licença Apache 2.0](LICENSE).
O Fess é baseado no [OpenSearch](https://github.com/opensearch-project/OpenSearch), mas não é necessário ter conhecimento ou experiência com OpenSearch. O Fess fornece uma interface de administração fácil de usar, que permite configurar o sistema através do seu navegador.
O Fess também inclui um rastreador (Crawler), que pode rastrear documentos em um [servidor web](https://fess.codelibs.org/14.17/admin/webconfig-guide.html), [sistema de arquivos](https://fess.codelibs.org/14.17/admin/fileconfig-guide.html) ou [Data Store](https://fess.codelibs.org/14.17/admin/dataconfig-guide.html) (como CSV ou banco de dados). Muitos formatos de arquivos são suportados, incluindo (mas não limitado a): Microsoft Office, PDF e zip.
*[Fess Site Search](https://github.com/codelibs/fess-site-search)* é uma alternativa gratuita ao [Google Site Search](https://enterprise.google.com/search/products/gss.html). Para mais detalhes, veja a [documentação do FSS JS Generator](https://fss-generator.codelibs.org/docs/manual).
## Site
[fess.codelibs.org](https://fess.codelibs.org/)
## Problemas/Perguntas
[discuss.codelibs.org](https://discuss.codelibs.org/c/FessEN/)
## Como Começar
Existem duas maneiras de testar o Fess. A primeira é baixar e instalar você mesmo. A segunda é usar [Docker](https://www.docker.com/products/docker-engine).
### Baixar e Instalar/Executar
O Fess 14.17 já está disponível e pode ser baixado na [página de lançamentos](https://github.com/codelibs/fess/releases "download"). As opções de download incluem: deb, rpm, zip.
Os comandos a seguir mostram como usar o download em formato zip:
$ unzip fess-14.17.x.zip
$ cd fess-14.17.x
$ ./bin/fess
Para mais detalhes, veja o [Guia de Instalação](https://fess.codelibs.org/14.17/install/index.html).
### Docker
Nós fornecemos imagens Docker em [ghcr.io](https://github.com/orgs/codelibs/packages). Também fornecemos um arquivo Docker Compose (YAML) neste [repositório](https://github.com/codelibs/docker-fess/tree/master/compose).
### Interface do Navegador
- Interface de Busca: http://localhost:8080/
![Interface de Busca](https://fess.codelibs.org/_images/fess_search_result1.png)
- Interface de Administração: http://localhost:8080/admin/ (o nome de usuário/senha padrão é admin/admin)
![Interface de Administração](https://fess.codelibs.org/_images/fess_admin_dashboard.png)
Você pode registrar alvos de rastreamento na interface de administração nas páginas de configuração do rastreador (Web, Arquivo, Data Store), e iniciar manualmente o rastreador na [página do Agendador](https://fess.codelibs.org/14.17/admin/scheduler-guide.html).
## Migração de Outro Provedor de Busca
Consulte [MIGRATION.md](MIGRATION.md).
## Data Store
Atualmente, o Fess suporta o rastreamento dos seguintes [locais de armazenamento e APIs](https://fess.codelibs.org/14.17/admin/dataconfig-guide.html):
- [Confluence/Jira](https://github.com/codelibs/fess-ds-atlassian)
- [Box](https://github.com/codelibs/fess-ds-box)
- [CSV](https://github.com/codelibs/fess-ds-csv)
- [Database](https://github.com/codelibs/fess-ds-db)
- [Dropbox](https://github.com/codelibs/fess-ds-dropbox)
- [Elasticsearch](https://github.com/codelibs/fess-ds-elasticsearch)
- [Git](https://github.com/codelibs/fess-ds-git)
- [Gitbucket](https://github.com/codelibs/fess-ds-gitbucket)
- [G Suite](https://github.com/codelibs/fess-ds-gsuite)
- [JSON](https://github.com/codelibs/fess-ds-json)
- [Office 365](https://github.com/codelibs/fess-ds-office365)
- [S3](https://github.com/codelibs/fess-ds-s3)
- [Salesforce](https://github.com/codelibs/fess-ds-salesforce)
- [SharePoint](https://github.com/codelibs/fess-ds-sharepoint)
- [Slack](https://github.com/codelibs/fess-ds-slack)
## Temas
- [Simple](https://github.com/codelibs/fess-theme-simple)
- [Classic](https://github.com/codelibs/fess-theme-classic)
## Ingestão
- [Logger](https://github.com/codelibs/fess-ingest-logger)
- [NDJSON](https://github.com/codelibs/fess-ingest-ndjson)
## Scripts
- [Groovy](https://github.com/codelibs/fess-script-groovy)
- [OGNL](https://github.com/codelibs/fess-script-ognl)
## Informações de Desenvolvimento
### Obter Código Fonte
1. Clone o repositório do Fess:
```
$ cd ~/workspace
$ git clone https://github.com/codelibs/fess.git
```
2. Importe o repositório clonado como um projeto [Maven](https://maven.apache.org/) no [Eclipse](https://www.eclipse.org/eclipseide/) ou em outro IDE.
### Configuração de Plugins para OpenSearch
Execute antrun:run para baixar os plugins no diretório de plugins:
$ mvn antrun:run
### Executar o Fess
Execute ou depure `org.codelibs.fess.FessBoot` no seu IDE, e depois acesse http://localhost:8080/
### Criar Pacote
Execute o objetivo `package` e o arquivo de lançamento será criado em target/releases.
$ mvn package
$ mvn rpm:rpm # pacote .rpm
$ mvn jdeb:jdeb # pacote .deb
### Gerar Código Fonte
$ mvn dbflute:download # (comando executado uma vez)
$ mvn dbflute:freegen
$ mvn license:format
### Testes de Integração
Inicie o servidor Fess e execute o seguinte comando:
$ mvn test -P integrationTests -Dtest.fess.url="http://localhost:8080" -Dtest.search_engine.url="http://localhost:9201"
Para executar um único caso de teste, você pode usar:
$ mvn test -P integrationTests -Dtest.fess.url="http://localhost:8080" -Dtest.search_engine.url="http://localhost:9201" -Dtest=SearchApiTests
### Traduzir para o Seu Idioma
Fess é um software internacionalizado.
Se você quiser adicionar rótulos/mensagens para o seu idioma, por favor, traduza o arquivo de propriedades e renomeie-o para fess\_\*\_[lang].properties.
* [fess_label_en.properties](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_label_en.properties)
* [fess_message_en.properties](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_message_en.properties)
Para o analisador de busca/índice, se [doc.json](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_indices/fess/doc.json) contiver lang\_[lang] para o seu idioma, por favor, modifique o analisador para o seu idioma. Para mais detalhes sobre Analisadores, veja a [documentação do OpenSearch](https://opensearch.org/docs/latest/analyzers/search-analyzers/).
Aceitamos pull requests para o seu idioma.
## Desenvolvido por
* [Lasta Di](https://github.com/lastaflute/lasta-di "Lasta Di"): Contêiner DI
* [LastaFlute](https://github.com/lastaflute/lastaflute "LastaFlute"): Framework Web
* [Lasta Job](https://github.com/lastaflute/lasta-job "Lasta Job"): Agendador de Tarefas
* [Fess Crawler](https://github.com/codelibs/fess-crawler "Fess Crawler"): Rastreador Web
* [OpenSearch](https://opensearch.org/ "OpenSearch"): Motor de Busca

View file

@ -1,158 +0,0 @@
# Fess: 企业搜索服务器
[![Java CI with Maven](https://github.com/codelibs/fess/actions/workflows/maven.yml/badge.svg)](https://github.com/codelibs/fess/actions/workflows/maven.yml)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.codelibs.fess/fess/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.codelibs.fess/fess)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/gitbucket/gitbucket/blob/master/LICENSE)
## 概述
Fess 是一个功能强大且易于部署的企业搜索服务器。您可以在任何可以运行 Java 运行时环境的平台上快速安装和运行 Fess。Fess 根据 [Apache 许可证 2.0](LICENSE) 提供。
Fess 基于 [OpenSearch](https://github.com/opensearch-project/OpenSearch),但不需要 OpenSearch 的知识或经验。Fess 提供了一个易于使用的管理 GUI您可以通过浏览器配置系统。Fess 还包含一个爬虫,能够抓取 [Web 服务器](https://fess.codelibs.org/14.17/admin/webconfig-guide.html)、[文件系统](https://fess.codelibs.org/14.17/admin/fileconfig-guide.html)或[数据存储](https://fess.codelibs.org/14.17/admin/dataconfig-guide.html)(如 CSV 或数据库中的文档。Fess 支持多种文件格式包括但不限于Microsoft Office、PDF 和 zip。
*[Fess 网站搜索](https://github.com/codelibs/fess-site-search)* 是 [Google 网站搜索](https://enterprise.google.com/search/products/gss.html)的免费替代品。更多详情请参阅 [FSS JS 生成器文档](https://fss-generator.codelibs.org/docs/manual)。
## 官网
[fess.codelibs.org](https://fess.codelibs.org/)
## 问题/疑问
[discuss.codelibs.org](https://discuss.codelibs.org/c/FessEN/)
## 入门
您可以通过两种方式尝试 Fess。第一种是自行下载并安装第二种是使用 [Docker](https://www.docker.com/products/docker-engine)。
### 下载并安装/运行
Fess 14.17 现已发布,可在 [发布页面](https://github.com/codelibs/fess/releases "download") 下载。提供三种下载形式deb、rpm、zip。
以下命令展示了如何使用 zip 下载:
$ unzip fess-14.17.x.zip
$ cd fess-14.17.x
$ ./bin/fess
更多详情请参阅 [安装指南](https://fess.codelibs.org/14.17/install/index.html)。
### Docker
我们在 [ghcr.io](https://github.com/orgs/codelibs/packages) 上提供了 Docker 镜像。我们还在[此存储库](https://github.com/codelibs/docker-fess/tree/master/compose)中提供了 Docker Compose (YAML) 文件。
### 浏览器 UI
- 搜索 UI: http://localhost:8080/
![Search UI](https://fess.codelibs.org/_images/fess_search_result1.png)
- 管理 UI: http://localhost:8080/admin/ (默认用户名/密码为 admin/admin
![Admin UI](https://fess.codelibs.org/_images/fess_admin_dashboard.png)
您可以在管理 UI 的 (Web、文件、数据存储) 爬虫配置页面中注册爬取目标,然后在 [调度器页面](https://fess.codelibs.org/14.17/admin/scheduler-guide.html)手动启动爬虫。
## 从其他搜索提供商迁移
请参阅 [MIGRATION.md](MIGRATION.md)。
## 数据存储
当前Fess 支持抓取以下[存储位置和 API](https://fess.codelibs.org/14.17/admin/dataconfig-guide.html)
- [Confluence/Jira](https://github.com/codelibs/fess-ds-atlassian)
- [Box](https://github.com/codelibs/fess-ds-box)
- [CSV](https://github.com/codelibs/fess-ds-csv)
- [Database](https://github.com/codelibs/fess-ds-db)
- [Dropbox](https://github.com/codelibs/fess-ds-dropbox)
- [Elasticsearch](https://github.com/codelibs/fess-ds-elasticsearch)
- [Git](https://github.com/codelibs/fess-ds-git)
- [Gitbucket](https://github.com/codelibs/fess-ds-gitbucket)
- [G Suite](https://github.com/codelibs/fess-ds-gsuite)
- [JSON](https://github.com/codelibs/fess-ds-json)
- [Office 365](https://github.com/codelibs/fess-ds-office365)
- [S3](https://github.com/codelibs/fess-ds-s3)
- [Salesforce](https://github.com/codelibs/fess-ds-salesforce)
- [SharePoint](https://github.com/codelibs/fess-ds-sharepoint)
- [Slack](https://github.com/codelibs/fess-ds-slack)
## 主题
- [Simple](https://github.com/codelibs/fess-theme-simple)
- [Classic](https://github.com/codelibs/fess-theme-classic)
## 数据处理
- [Logger](https://github.com/codelibs/fess-ingest-logger)
- [NDJSON](https://github.com/codelibs/fess-ingest-ndjson)
## 脚本
- [Groovy](https://github.com/codelibs/fess-script-groovy)
- [OGNL](https://github.com/codelibs/fess-script-ognl)
## 开发信息
### 获取源代码
1. 克隆 Fess 的存储库:
```
$ cd ~/workspace
$ git clone https://github.com/codelibs/fess.git
```
2. 将克隆的存储库作为 [Maven](https://maven.apache.org/) 项目导入 [Eclipse](https://www.eclipse.org/eclipseide/) 或其他 IDE。
### 设置 OpenSearch 插件
运行 antrun:run 将插件下载到插件目录:
$ mvn antrun:run
### 运行 Fess
在您的 IDE 上运行或调试 `org.codelibs.fess.FessBoot`,然后访问 http://localhost:8080/
### 构建包
运行 `package` 目标,然后在 target/releases 中创建发布文件。
$ mvn package
$ mvn rpm:rpm # .rpm 包
$ mvn jdeb:jdeb # .deb 包
### 生成源代码
$ mvn dbflute:download # (仅运行一次)
$ mvn dbflute:freegen
$ mvn license:format
### 集成测试
启动 Fess 服务器并运行以下命令:
$ mvn test -P integrationTests -Dtest.fess.url="http://localhost:8080" -Dtest.search_engine.url="http://localhost:9201"
要运行单个测试用例,您可以使用:
$ mvn test -P integrationTests -Dtest.fess.url="http://localhost:8080" -Dtest.search_engine.url="http://localhost:9201" -Dtest=SearchApiTests
### 翻译为您的语言
Fess 是国际化软件。
如果您想为您的语言添加标签/消息,请翻译属性文件,然后将其重命名为 fess\_\*\_[lang].properties。
* [fess_label_en.properties](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_label_en.properties)
* [fess_message_en.properties](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_message_en.properties)
对于搜索/索引分析器,如果 [doc.json](https://github.com/codelibs/fess/blob/master/src/main/resources/fess_indices/fess/doc.json) 包含您语言的 lang\_[lang],请为您的语言修改分析器。有关分析器的更多详细信息,请参阅 [OpenSearch 文档](https://opensearch.org/docs/latest/analyzers/search-analyzers/)。
我们欢迎您的语言的 Pull Request。
## 技术支持
* [Lasta Di](https://github.com/lastaflute/lasta-di "Lasta Di"): DI 容器
* [LastaFlute](https://github.com/lastaflute/lastaflute "LastaFlute"): Web 框架
* [Lasta Job](https://github.com/lastaflute/lasta-job "Lasta Job"): 任务调度器
* [Fess Crawler](https://github.com/codelibs/fess-crawler "Fess Crawler"): Web 爬虫
* [OpenSearch](https://opensearch.org/ "OpenSearch"): 搜索引擎

View file

@ -6,7 +6,7 @@
<!-- Maven Repository -->
<property name="maven.snapshot.repo.url" value="https://maven.codelibs.org/" />
<property name="maven.release.repo.url" value="https://maven.codelibs.org/" />
<property name="opensearch.version" value="2.18.0" />
<property name="opensearch.version" value="1.3.2" />
<target name="install.modules">
<mkdir dir="${target.dir}" />

View file

@ -17,8 +17,8 @@
<param name="plugin.groupId" value="org/codelibs/opensearch" />
<param name="plugin.name.prefix" value="opensearch-" />
<param name="plugin.name" value="analysis-extension" />
<param name="plugin.version" value="2.18.0" />
<param name="plugin.zip.version" value="2.18.0" />
<param name="plugin.version" value="1.3.0" />
<param name="plugin.zip.version" value="1.3.0" />
</antcall>
<!-- analysis-fess -->
<antcall target="install.plugin">
@ -26,8 +26,8 @@
<param name="plugin.groupId" value="org/codelibs/opensearch" />
<param name="plugin.name.prefix" value="opensearch-" />
<param name="plugin.name" value="analysis-fess" />
<param name="plugin.version" value="2.18.0" />
<param name="plugin.zip.version" value="2.18.0" />
<param name="plugin.version" value="1.3.0" />
<param name="plugin.zip.version" value="1.3.0" />
</antcall>
<!-- configsync -->
<antcall target="install.plugin">
@ -35,8 +35,8 @@
<param name="plugin.groupId" value="org/codelibs/opensearch" />
<param name="plugin.name.prefix" value="opensearch-" />
<param name="plugin.name" value="configsync" />
<param name="plugin.version" value="2.18.0" />
<param name="plugin.zip.version" value="2.18.0" />
<param name="plugin.version" value="1.3.0" />
<param name="plugin.zip.version" value="1.3.0" />
</antcall>
<!-- minhash -->
<antcall target="install.plugin">
@ -44,8 +44,8 @@
<param name="plugin.groupId" value="org/codelibs/opensearch" />
<param name="plugin.name.prefix" value="opensearch-" />
<param name="plugin.name" value="minhash" />
<param name="plugin.version" value="2.18.0" />
<param name="plugin.zip.version" value="2.18.0" />
<param name="plugin.version" value="1.3.0" />
<param name="plugin.zip.version" value="1.3.0" />
</antcall>
<antcall target="remove.jars" />

155
pom.xml
View file

@ -2,7 +2,7 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>fess</artifactId>
<version>15.0.0-SNAPSHOT</version>
<version>14.2.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>Fess</name>
<description>Fess is Full tExt Search System.</description>
@ -30,7 +30,7 @@
<parent>
<groupId>org.codelibs.fess</groupId>
<artifactId>fess-parent</artifactId>
<version>15.0.0-SNAPSHOT</version>
<version>14.2.0</version>
<relativePath />
</parent>
<properties>
@ -67,7 +67,6 @@
<id>integrationTests</id>
<properties>
<test.include.path>**/*Tests.java</test.include.path>
<test.command.args />
</properties>
</profile>
</profiles>
@ -109,7 +108,6 @@
<directory>${project.build.directory}/${project.build.finalName}-compress</directory>
</resource>
</webResources>
<packagingExcludes>**/*.min.map,**/*.min.css.map,**/*.min.js.map</packagingExcludes>
</configuration>
</plugin>
<plugin>
@ -137,14 +135,10 @@
<includes>
<include>${test.include.path}</include>
</includes>
<argLine>@{argLine} ${test.command.args}</argLine>
<argLine>${test.command.args}</argLine>
<useSystemClassLoader>false</useSystemClassLoader>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
</plugin>
@ -508,8 +502,8 @@
</paths>
<mapper>
<type>perm</type>
<user>opensearch</user>
<group>opensearch</group>
<user>elasticsearch</user>
<group>elasticsearch</group>
</mapper>
</data>
<!-- Add elasicsearch modules directory -->
@ -763,8 +757,8 @@
<mapping>
<directory>${packaging.fess.dictionary.dir}</directory>
<filemode>755</filemode>
<username>opensearch</username>
<groupname>opensearch</groupname>
<username>elasticsearch</username>
<groupname>elasticsearch</groupname>
</mapping>
<!-- es/modules -->
<mapping>
@ -906,18 +900,6 @@
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>snapshots.oss.sonatype.org</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<!-- lastaflute -->
<dependency>
@ -945,31 +927,16 @@
<!-- J2EE -->
<dependency>
<groupId>jakarta.servlet.jsp.jstl</groupId>
<artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
<version>${jakarta.jstl.api.version}</version>
<!-- <scope>provided</scope> -->
<exclusions>
<exclusion>
<groupId>jakarta.el</groupId>
<artifactId>jakarta.el-api</artifactId>
</exclusion>
<exclusion>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>jakarta.servlet.jsp.jstl</artifactId>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
<!-- contains taglibs.standard -->
<version>${jakarta.jstl.version}</version>
<!-- <scope>provided</scope> -->
</dependency>
<dependency>
<groupId>jakarta.transaction</groupId>
<artifactId>jakarta.transaction-api</artifactId>
<version>${jakarta.transaction.api.version}</version>
<groupId>javax.transaction</groupId>
<artifactId>javax.transaction-api</artifactId>
<version>${javax.transaction.api.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
@ -1029,23 +996,12 @@
<artifactId>log4j-jul</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>co.elastic.logging</groupId>
<artifactId>log4j2-ecs-layout</artifactId>
<version>${log4j.ecs.version}</version>
</dependency>
<!-- opensearch -->
<dependency>
<groupId>org.opensearch</groupId>
<artifactId>opensearch</artifactId>
<version>${opensearch.version}</version>
<exclusions>
<exclusion>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.codelibs.opensearch</groupId>
@ -1128,10 +1084,6 @@
<groupId>org.opensearch.plugin</groupId>
<artifactId>analysis-common</artifactId>
</exclusion>
<exclusion>
<groupId>org.opensearch.plugin</groupId>
<artifactId>opensearch-scripting-painless-spi</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
@ -1187,16 +1139,22 @@
<groupId>com.google.oauth-client</groupId>
<artifactId>google-oauth-client</artifactId>
<version>${google.oauth.client.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client</artifactId>
<version>${google.http.client.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
@ -1323,10 +1281,6 @@
<groupId>stax</groupId>
<artifactId>stax-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
@ -1335,7 +1289,7 @@
<version>${okhttp.version}</version>
</dependency>
<dependency>
<groupId>org.codelibs</groupId>
<groupId>com.onelogin</groupId>
<artifactId>java-saml</artifactId>
<version>${java.saml.version}</version>
<exclusions>
@ -1345,21 +1299,6 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcmail-jdk18on</artifactId>
<version>${bouncycastle.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>${bouncycastle.version}</version>
</dependency>
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
<version>${kryo.version}</version>
</dependency>
<!-- suggest library -->
<dependency>
@ -1370,8 +1309,8 @@
<!-- fileupload -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-fileupload2-jakarta-servlet6</artifactId>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>${commons.fileupload.version}</version>
</dependency>
@ -1434,26 +1373,13 @@
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bcmail-jdk15on</artifactId>
</exclusion>
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.codelibs.fess</groupId>
<artifactId>fess-crawler-opensearch</artifactId>
<artifactId>fess-crawler-es</artifactId>
<version>${crawler.version}</version>
</dependency>
<dependency>
<groupId>org.codelibs.fess</groupId>
<artifactId>fess-crawler-playwright</artifactId>
<version>${crawler.playwright.version}</version>
</dependency>
<dependency>
<groupId>args4j</groupId>
<artifactId>args4j</artifactId>
@ -1532,13 +1458,6 @@
<scope>provided</scope>
</dependency>
<!-- groovy -->
<dependency>
<groupId>org.apache.groovy</groupId>
<artifactId>groovy</artifactId>
<version>${groovy.version}</version>
</dependency>
<!-- test -->
<dependency>
<groupId>junit</groupId>
@ -1573,7 +1492,23 @@
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>5.5.0</version>
<version>4.3.2</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</exclusion>
<exclusion>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>${groovy.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

View file

@ -106,10 +106,10 @@ launch_service()
if [ "x$daemonized" = "x" ]; then
fess_parms="$fess_parms -Dfess.foreground=yes"
exec "$JAVA" $FESS_JAVA_OPTS $fess_parms -Dfess.es.dir="$SEARCH_ENGINE_HOME" -cp "$FESS_CLASSPATH" $props \
exec "$JAVA" $FESS_JAVA_OPTS $fess_parms -Dfess.es.dir="$ES_HOME" -cp "$FESS_CLASSPATH" $props \
org.codelibs.fess.FessBoot $FESS_OPTS > /dev/null
else
exec "$JAVA" $FESS_JAVA_OPTS $fess_parms -Dfess.es.dir="$SEARCH_ENGINE_HOME" -cp "$FESS_CLASSPATH" $props \
exec "$JAVA" $FESS_JAVA_OPTS $fess_parms -Dfess.es.dir="$ES_HOME" -cp "$FESS_CLASSPATH" $props \
org.codelibs.fess.FessBoot $FESS_OPTS <&- > /dev/null &
if [ x"$pidfile" != "x" ] ; then
echo $! > $pidfile

View file

@ -87,7 +87,7 @@ set FESS_JAVA_OPTS=%FESS_JAVA_OPTS% -Dfile.encoding=UTF-8
REM Application Configuration
set APP_NAME=fess
set SEARCH_ENGINE_HOME=%FESS_HOME%/es
set ES_HOME=%FESS_HOME%/es
if NOT "%FESS_USE_GC_LOGGING%" == "" set FESS_JAVA_OPTS=%FESS_JAVA_OPTS% -Xlog:gc*,gc+age=trace,safepoint:file=%FESS_HOME%/logs/gc-%APP_NAME%.log:utctime,pid,tags:filecount=5,filesize=64m
@ -95,7 +95,7 @@ set FESS_CLASSPATH=%FESS_HOME%\lib\classes
set FESS_JAVA_OPTS=%FESS_JAVA_OPTS% -Dfess
set FESS_JAVA_OPTS=%FESS_JAVA_OPTS% -Des-foreground=yes
set FESS_JAVA_OPTS=%FESS_JAVA_OPTS% -Dfess.home="%FESS_HOME%"
set FESS_JAVA_OPTS=%FESS_JAVA_OPTS% -Dfess.es.dir="%SEARCH_ENGINE_HOME%"
set FESS_JAVA_OPTS=%FESS_JAVA_OPTS% -Dfess.es.dir="%ES_HOME%"
set FESS_JAVA_OPTS=%FESS_JAVA_OPTS% -Dfess.context.path=/
set FESS_JAVA_OPTS=%FESS_JAVA_OPTS% -Dfess.port=8080
set FESS_JAVA_OPTS=%FESS_JAVA_OPTS% -Dfess.webapp.path=%FESS_HOME%\app
@ -106,8 +106,8 @@ set FESS_JAVA_OPTS=%FESS_JAVA_OPTS% -Dfess.log.level=warn
set FESS_JAVA_OPTS=%FESS_JAVA_OPTS% -Dlasta.env=web
set FESS_JAVA_OPTS=%FESS_JAVA_OPTS% -Dtomcat.config.path=tomcat_config.properties
REM External opensearch cluster
REM set FESS_JAVA_OPTS=%FESS_JAVA_OPTS% -Dfess.search_engine.http_address=http://localhost:9200
REM set FESS_JAVA_OPTS=%FESS_JAVA_OPTS% -Dfess.dictionary.path=%SEARCH_ENGINE_HOME%/config/
REM External elasticsearch cluster
REM set FESS_JAVA_OPTS=%FESS_JAVA_OPTS% -Dfess.es.http_address=http://localhost:9200
REM set FESS_JAVA_OPTS=%FESS_JAVA_OPTS% -Dfess.dictionary.path=%ES_HOME%/config/
set GROOVY_TURN_OFF_JAVA_WARNINGS=true

View file

@ -20,9 +20,9 @@ if [ "x$FESS_HEAP_SIZE" != "x" ]; then
FESS_MAX_MEM=$FESS_HEAP_SIZE
fi
# External opensearch cluster
#SEARCH_ENGINE_HTTP_URL=http://localhost:9200
#FESS_DICTIONARY_PATH=/var/lib/opensearch/config/
# External elasticsearch cluster
#ES_HTTP_URL=http://localhost:9200
#FESS_DICTIONARY_PATH=/var/lib/elasticsearch/config/
# SSL truststore for certificate validation over https
#FESS_JAVA_OPTS="$FESS_JAVA_OPTS -Djavax.net.ssl.trustStore=/tech/elastic/config/truststore.jks"
@ -83,8 +83,8 @@ FESS_JAVA_OPTS="$FESS_JAVA_OPTS -Dfile.encoding=UTF-8"
if [ "x$APP_NAME" = "x" ]; then
APP_NAME=fess
fi
if [ "x$SEARCH_ENGINE_HOME" = "x" ]; then
SEARCH_ENGINE_HOME=$FESS_HOME/es
if [ "x$ES_HOME" = "x" ]; then
ES_HOME=$FESS_HOME/es
fi
if [ "x$FESS_TEMP_PATH" = "x" ]; then
FESS_TEMP_PATH=$FESS_HOME/temp
@ -120,8 +120,8 @@ fi
if [ "x$FESS_VAR_PATH" != "x" ]; then
FESS_JAVA_OPTS="$FESS_JAVA_OPTS -Dfess.var.path=$FESS_VAR_PATH"
fi
if [ "x$SEARCH_ENGINE_HTTP_URL" != "x" ]; then
FESS_JAVA_OPTS="$FESS_JAVA_OPTS -Dfess.search_engine.http_address=$SEARCH_ENGINE_HTTP_URL"
if [ "x$ES_HTTP_URL" != "x" ]; then
FESS_JAVA_OPTS="$FESS_JAVA_OPTS -Dfess.es.http_address=$ES_HTTP_URL"
fi
if [ "x$FESS_DICTIONARY_PATH" != "x" ]; then
FESS_JAVA_OPTS="$FESS_JAVA_OPTS -Dfess.dictionary.path=$FESS_DICTIONARY_PATH"

View file

@ -3,7 +3,7 @@
cmd_type=$1
url=$2
output_file=$3
image_size=100x100
image_size=100x100!
target_file=$(echo "$url" | sed -e "s#^file:/*#/#g")
check_command() {
@ -30,28 +30,28 @@ if [[ x"${cmd_type}" = "xmsoffice" ]] ; then
exit 1
fi
tmp_png_prefix=/tmp/thumbnail.png.$$
pdftoppm -png -singlefile ${tmp_pdf_file} ${tmp_png_prefix}
tmp_png_file="${tmp_png_prefix}.png"
rm -f ${tmp_pdf_file}
pdftoppm -png -l 1 ${tmp_pdf_file} ${tmp_png_prefix}
tmp_png_file="${tmp_png_prefix}-1.png"
rm ${tmp_pdf_file}
if [[ ! -f ${tmp_png_file} ]] ; then
echo "pdftoppm does not work."
exit 1
fi
convert -thumbnail ${image_size} ${tmp_png_file} "${output_file}"
rm -f ${tmp_png_prefix}*png
rm ${tmp_png_prefix}*png
elif [[ x"${cmd_type}" = "xpdf" ]] ; then
check_command convert
check_command pdftoppm
target_file=$(echo "$url" | sed -e "s#^file:/*#/#g")
tmp_png_prefix=/tmp/thumbnail.png.$$
pdftoppm -png -singlefile "${target_file}" ${tmp_png_prefix}
tmp_png_file="${tmp_png_prefix}.png"
pdftoppm -png -l 1 "${target_file}" ${tmp_png_prefix}
tmp_png_file="${tmp_png_prefix}-1.png"
if [[ ! -f ${tmp_png_file} ]] ; then
echo "pdftoppm does not work."
exit 1
fi
convert -thumbnail ${image_size} ${tmp_png_file} "${output_file}"
rm -f ${tmp_png_prefix}*png
rm ${tmp_png_prefix}*png
elif [[ x"${cmd_type}" = "xps" ]] ; then
check_command convert
check_command pdftoppm
@ -64,15 +64,15 @@ elif [[ x"${cmd_type}" = "xps" ]] ; then
exit 1
fi
tmp_png_prefix=/tmp/thumbnail.png.$$
pdftoppm -png -singlefile ${tmp_pdf_file} ${tmp_png_prefix}
tmp_png_file="${tmp_png_prefix}.png"
rm -f ${tmp_pdf_file}
pdftoppm -png -l 1 ${tmp_pdf_file} ${tmp_png_prefix}
tmp_png_file="${tmp_png_prefix}-1.png"
rm ${tmp_pdf_file}
if [[ ! -f ${tmp_png_file} ]] ; then
echo "pdftoppm does not work."
exit 1
fi
convert -thumbnail ${image_size} ${tmp_png_file} "${output_file}"
rm -f ${tmp_png_prefix}*png
rm ${tmp_png_prefix}*png
elif [[ x"${cmd_type}" = "ximage" ]] ; then
check_command convert
target_file=$(echo "$url" | sed -e "s#^file:/*#/#g")

View file

@ -141,7 +141,7 @@ CALL "%FESS_HOME%\bin\fess.in.bat"
rem thread stack size
set JVM_SS=256
set FESS_PARAMS=-Dfess;-Dfess.home="%FESS_HOME%";-Dfess.es.dir="%SEARCH_ENGINE_HOME%";-Dfess.home="%FESS_HOME%";-Dfess.context.path="/";-Dfess.port=8080;-Dfess.webapp.path="%FESS_HOME%\app";-Dfess.temp.path="%FESS_HOME%\temp";-Dfess.log.name="%APP_NAME%";-Dfess.log.path="%FESS_HOME%\logs";-Dfess.log.level=warn;-Dlasta.env=web;-Dtomcat.config.path=tomcat_config.properties
set FESS_PARAMS=-Dfess;-Dfess.home="%FESS_HOME%";-Dfess.es.dir="%ES_HOME%";-Dfess.home="%FESS_HOME%";-Dfess.context.path="/";-Dfess.port=8080;-Dfess.webapp.path="%FESS_HOME%\app";-Dfess.temp.path="%FESS_HOME%\temp";-Dfess.log.name="%APP_NAME%";-Dfess.log.path="%FESS_HOME%\logs";-Dfess.log.level=warn;-Dlasta.env=web;-Dtomcat.config.path=tomcat_config.properties
set JVM_OPTS=-XX:+UseG1GC%FESS_JAVA_OPTS: =;%

View file

@ -1,730 +0,0 @@
openapi: 3.0.3
info:
title: Fess - User API
description: |-
This is a Fess Server based on the OpenAPI 3.0 specification.
license:
name: Apache 2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html
version: 14.8.0
externalDocs:
description: API Documentation
url: https://fess.codelibs.org/14.8/api/
servers:
- url: http://localhost:8080/api/v1
tags:
- name: search
description: Search operations
- name: popularword
description: Popular word operations
- name: monitor
description: Monitoring operations
- name: suggest
description: Suggest operations
- name: favorite
description: Favorite operations
paths:
/documents:
get:
tags:
- search
summary: Finds documents by query
description: Finds documents by search conditions
operationId: searchDocuments
parameters:
- name: q
in: query
description: Search words
required: false
schema:
type: string
example: Fess
- name: start
in: query
description: Start position
required: false
schema:
type: integer
minimum: 0
exclusiveMinimum: false
default: 0
example: 0
- name: offset
in: query
description: Offset from a start position
required: false
schema:
type: integer
minimum: 0
exclusiveMinimum: false
default: 0
example: 0
- name: num
in: query
description: The number of returned documents as a search result
required: false
schema:
type: integer
minimum: 0
exclusiveMinimum: false
maximum: 100
exclusiveMaximum: false
default: 20
example: 20
- name: sort
in: query
description: Sorted field name
required: false
schema:
type: string
example: score
- name: fields.label
in: query
description: Filtered label name
required: false
style: form
explode: true
schema:
type: array
items:
type: string
example: [name]
- name: facet.field
in: query
description: Facet field name
required: false
style: form
explode: true
schema:
type: array
items:
type: string
example: [label]
- name: facet.query
in: query
description: Facet query
required: false
style: form
explode: true
schema:
type: array
items:
type: string
example: ["timestamp:[now/d-1d TO *]"]
- name: facet.size
in: query
description: Item size in facets returned by facet.field
required: false
schema:
type: integer
minimum: 0
exclusiveMinimum: false
default: 10
example: 10
- name: facet.minDocCount
in: query
description: Minumum document size in facets
required: false
schema:
type: integer
minimum: 0
exclusiveMinimum: false
default: 0
example: 0
- name: geo.location.point
in: query
description: Latitude and Longitude for Geo search
required: false
schema:
type: string
example: 35.0,139.0
- name: geo.location.distance
in: query
description: Distance for Geo search
required: false
schema:
type: string
example: 10km
- name: lang
in: query
description: Language
required: false
schema:
type: string
example: en
- name: preference
in: query
description: String to specify a shard for searching
required: false
schema:
type: string
example: abc
- name: callback
in: query
description: Callback name for using JSONP
required: false
schema:
type: string
responses:
'200':
description: Successful operation
content:
application/json:
schema:
type: object
properties:
q:
type: string
example: Fess
query_id:
type: string
example: bd60f9579a494dfd8c03db7c8aa905b0
exec_time:
type: number
example: 0.21
query_time:
type: integer
format: int64
example: 0
page_size:
type: integer
example: 20
page_number:
type: integer
example: 1
record_count:
type: integer
format: int64
example: 31625
page_count:
type: integer
example: 1
highlight_params:
type: string
example: "&hq=n2sm&hq=Fess"
next_page:
type: boolean
example: true
prev_page:
type: boolean
example: false
start_record_number:
type: integer
example: 1
end_record_number:
type: integer
example: 20
page_numbers:
type: array
items:
type: string
example: ["1", "2", "3", "4", "5"]
partial:
type: boolean
example: false
search_query:
type: string
example: "(Fess OR n2sm)"
requested_time:
type: integer
format: int64
example: 1507822131845
related_query:
type: array
items:
type: string
example: ["aaa"]
related_contents:
type: array
items:
type: string
example: []
data:
type: array
items:
type: object
properties:
filetype:
type: string
example: html
title:
type: string
example: "Open Source Enterprise Search Server: Fess — Fess 11.0 documentation"
content_title:
type: string
example: "Open Source Enterprise Search Server: Fess — Fe..."
digest:
type: string
example: "Docs » Open Source Enterprise Search Server: Fess Commercial Support Open Source Enterprise Search Server: Fess What is Fess ? Fess is very powerful and easily deployable Enterprise Search Server. ..."
host:
type: string
format: hostname
example: "fess.codelibs.org"
last_modified:
type: string
format: date-time
example: "2017-10-09T22:28:56.000Z"
content_length:
type: string
example: "29624"
timestamp:
type: string
format: date-time
example: "2017-10-09T22:28:56.000Z"
url_link:
type: string
example: "https://fess.codelibs.org/"
created:
type: string
format: date-time
example: "2017-10-10T15:00:48.609Z"
site_path:
type: string
example: "fess.codelibs.org/"
doc_id:
type: string
example: "e79fbfdfb09d4bffb58ec230c68f6f7e"
url:
type: string
format: uri
example: "https://fess.codelibs.org/"
content_description:
type: string
example: "Enterprise Search Server: <strong>Fess</strong> Commercial Support Open...Search Server: <strong>Fess</strong> What is <strong>Fess</strong> ? <strong>Fess</strong> is very powerful...You can install and run <strong>Fess</strong> quickly on any platforms...Java runtime environment. <strong>Fess</strong> is provided under Apache...Apache license. Demo <strong>Fess</strong> is Elasticsearch-based search"
site:
type: string
example: "fess.codelibs.org/"
boost:
type: string
example: "10.0"
mimetype:
type: string
example: "text/html"
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
/documents/all:
get:
tags:
- search
summary: Finds all documents by query
description: Finds all documents by search conditions
operationId: searchAllDocuments
parameters:
- name: q
in: query
description: Search words
required: false
schema:
type: string
example: Fess
- name: num
in: query
description: The number of returned documents as a search result
required: false
schema:
type: integer
minimum: 0
exclusiveMinimum: false
maximum: 100
exclusiveMaximum: false
default: 20
example: 20
- name: sort
in: query
description: Sorted field name
required: false
schema:
type: string
example: score
responses:
'200':
description: Successful operation
content:
application/x-ndjson:
schema:
type: string
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
/labels:
get:
tags:
- search
summary: List labels
description: Returns available labels
operationId: listLabels
responses:
'200':
description: Successful operation
content:
application/json:
schema:
type: object
properties:
record_count:
type: integer
example: 9
data:
type: array
items:
type: object
properties:
label:
type: string
example: AWS
value:
type: string
example: aws
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
/favorites:
get:
tags:
- favorite
summary: List favorites
description: Returns favorited document IDs
operationId: listFavorites
parameters:
- name: queryId
in: query
description: Query ID where the document is contained
required: true
schema:
type: string
example: queryid
responses:
'200':
description: Successful operation
content:
application/json:
schema:
type: object
properties:
record_count:
type: integer
example: 9
data:
type: array
items:
type: object
properties:
doc_id:
type: string
example: "e79fbfdfb09d4bffb58ec230c68f6f7e"
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
/documents/{docId}/favorite:
post:
tags:
- favorite
summary: Set a favorite mark
description: Set a favorite mark to the document
operationId: setFavorite
parameters:
- name: docId
in: path
description: Document ID to be favorited
required: true
schema:
type: string
example: documentid
- name: queryId
in: query
description: Query ID where the document is contained
required: true
schema:
type: string
example: queryid
responses:
'201':
description: Successful operation
content:
application/json:
schema:
type: object
properties:
result:
type: string
example: created
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
/popular-words:
get:
tags:
- popularword
summary: List popular words
description: Returns available labels
operationId: listPopularWords
parameters:
- name: seed
in: query
description: Random seed to return popular words
required: false
schema:
type: string
example: 123
- name: label
in: query
description: Filtered label name
required: false
style: form
explode: true
schema:
type: array
items:
type: string
example: [label]
- name: field
in: query
description: Field name to generate suggest words
required: false
style: form
explode: true
schema:
type: array
items:
type: string
example: [python]
responses:
'200':
description: Successful operation
content:
application/json:
schema:
type: object
properties:
record_count:
type: integer
example: 9
data:
type: array
items:
type: string
example: ["python"]
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
/health:
get:
tags:
- monitor
summary: Check a server status
description: Returns status
operationId: ping
responses:
'200':
description: Successful operation
content:
application/json:
schema:
type: object
properties:
data:
type: object
properties:
status:
type: string
example: green
timed_out:
type: boolean
example: false
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
'503':
description: Service unavailable
content:
application/json:
schema:
type: object
properties:
data:
type: object
properties:
status:
type: string
example: green
timed_out:
type: boolean
example: false
/suggest-words:
get:
tags:
- suggest
summary: Finds suggest words
description: Returns words for suggest
operationId: findSuggestWords
parameters:
- name: q
in: query
description: Inputting characters for search
required: true
schema:
type: string
example: fe
- name: num
in: query
description: The number of suggest words
required: false
schema:
type: integer
minimum: 0
exclusiveMinimum: false
example: 10
default: 10
- name: label
in: query
description: Filtered label name
required: false
style: form
explode: true
schema:
type: array
items:
type: string
example: [label]
- name: field
in: query
description: Field name to generate suggest words
required: false
style: form
explode: true
schema:
type: array
items:
type: string
example: [python]
- name: lang
in: query
description: Target language
required: false
style: form
explode: true
schema:
type: array
items:
type: string
example: [en]
responses:
'200':
description: Successful operation
content:
application/json:
schema:
type: object
properties:
query_time:
type: integer
format: int64
example: 18
record_count:
type: integer
example: 355
page_size:
type: integer
example: 10
data:
type: array
items:
type: object
properties:
text:
type: string
example: fess
labels:
type: array
items:
type: string
example: [java, python]
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
components:
responses:
BadRequest:
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Unauthorized:
description: Unauthorized request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
NotFound:
description: Page not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
InternalServerError:
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
schemas:
Error:
type: object
properties:
error_code:
type: string
example: "bd6b0bd6-0144-40bc-9567-c5751dd8eecb"
message:
type: string
example: "This is an error message."

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -37,8 +37,6 @@ public class Constants extends CoreLibConstants {
public static final String SCORE = "score";
public static final String SEARCHER = "searcher";
public static final String ON = "on";
public static final String READY = "ready";
@ -53,10 +51,6 @@ public class Constants extends CoreLibConstants {
public static final String STOP = "stop";
public static final String AUTO = "auto";
public static final String NONE = "none";
public static final String ITEM_LABEL = "label";
public static final String ITEM_VALUE = "value";
@ -83,12 +77,6 @@ public class Constants extends CoreLibConstants {
public static final long DEFAULT_CRAWLING_EXECUTION_INTERVAL = 5000L;
public static final String CRAWLING_USER_AGENT_PREFIX = "Mozilla/5.0 (compatible; Fess/";
public static final String CRAWLING_USER_AGENT_SUFFIX = "; +http://fess.codelibs.org/bot.html)";
public static final String DOCUMENT_INDEX_SUFFIX_PATTERN = "yyyyMMddHHmmssSSS";
// fess properties
public static final String USER_INFO_PROPERTY = "user.info";
@ -164,8 +152,6 @@ public class Constants extends CoreLibConstants {
public static final String LTR_WINDOW_SIZE_PROPERTY = "ltr.window.size";
public static final String SSO_TYPE_PROPERTY = "sso.type";
public static final String REQUEST_QUERIES = "fess.Queries";
public static final String HIGHLIGHT_QUERIES = "fess.HighlightQueries";
@ -252,8 +238,6 @@ public class Constants extends CoreLibConstants {
public static final Pattern LUCENE_RANGE_FIELD_RESERVED_PATTERN = Pattern.compile("([!\\(\\){}\\[\\]\"~\\\\:\\p{Zs}]|(&&)|(\\|\\|))");
public static final String DEFAULT_QUERY_OPERATOR = "fess.DefaultQueryOperator";
public static final String SEARCH_LOG_ACCESS_TYPE = "searchLogAccessType";
public static final String SEARCH_LOG_ACCESS_TYPE_JSON = "json";
@ -322,11 +306,8 @@ public class Constants extends CoreLibConstants {
public static final String MATCHES_ALL_QUERY = "*:*";
@Deprecated
public static final String FESS_ES_HTTP_ADDRESS = "fess.es.http_address";
public static final String FESS_SEARCH_ENGINE_HTTP_ADDRESS = "fess.search_engine.http_address";
public static final int DEFAULT_PAGE_SIZE = 20;
public static final int DEFAULT_START_COUNT = 0;
@ -359,7 +340,7 @@ public class Constants extends CoreLibConstants {
public static final String USER_INFO = "LoginInfo";
public static final String SEARCH_ENGINE_API_ACCESS_TOKEN = "searchEngineApiAccessToken";
public static final String ES_API_ACCESS_TOKEN = "esApiAccessToken";
public static final String DEFAULT_FIELD = "_default";
@ -419,8 +400,6 @@ public class Constants extends CoreLibConstants {
public static final String REQUEST_LANGUAGES = "requestLanguages";
public static final String REQUEST_PAGE_SIZE = "requestPageSize";
public static final String SEARCH_PREFERENCE_LOCAL = "_local";
public static final String GSA_API_VERSION = "3.2";

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -30,7 +30,6 @@ import org.apache.catalina.startup.Tomcat;
import org.apache.tomcat.util.http.CookieProcessorBase;
import org.apache.tomcat.util.http.Rfc6265CookieProcessor;
import org.apache.tomcat.util.net.SSLHostConfig;
import org.apache.tomcat.util.net.SSLHostConfigCertificate;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.tomcat.valve.SuppressErrorReportValve;
import org.codelibs.fess.tomcat.webresources.FessWebResourceRoot;
@ -172,22 +171,18 @@ public class FessBoot extends TomcatBoot {
connector.setProperty("SSLEnabled", "true");
final SSLHostConfig sslHostConfig = new SSLHostConfig();
sslHostConfig.setHostName("_default_");
final SSLHostConfigCertificate certificate =
new SSLHostConfigCertificate(sslHostConfig, SSLHostConfigCertificate.Type.UNDEFINED);
doSetupServerConfig(logger, props, "certificateKeystoreFile", v -> certificate.setCertificateKeystoreFile(v));
doSetupServerConfig(logger, props, "certificateKeystorePassword", v -> certificate.setCertificateKeystorePassword(v));
doSetupServerConfig(logger, props, "certificateKeyAlias", v -> certificate.setCertificateKeyAlias(v));
doSetupServerConfig(logger, props, "certificateKeystoreFile", v -> sslHostConfig.setCertificateKeystoreFile(v));
doSetupServerConfig(logger, props, "certificateKeystorePassword", v -> sslHostConfig.setCertificateKeystorePassword(v));
doSetupServerConfig(logger, props, "certificateKeyAlias", v -> sslHostConfig.setCertificateKeyAlias(v));
doSetupServerConfig(logger, props, "sslProtocol", v -> sslHostConfig.setSslProtocol(v));
doSetupServerConfig(logger, props, "enabledProtocols", v -> sslHostConfig.setEnabledProtocols(v.trim().split(",")));
sslHostConfig.addCertificate(certificate);
connector.addSslHostConfig(sslHostConfig);
}
});
doSetupServerConfig(logger, props, "sameSiteCookies", value -> {
for (final Container container : server.getHost().findChildren()) {
if (container instanceof final Context context
&& context.getCookieProcessor() instanceof final CookieProcessorBase cookieProcessor) {
if ((container instanceof final Context context)
&& (context.getCookieProcessor() instanceof final CookieProcessorBase cookieProcessor)) {
cookieProcessor.setSameSiteCookies(value);
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -20,14 +20,14 @@ import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.codelibs.core.exception.IORuntimeException;
import org.codelibs.fess.Constants;
import org.lastaflute.web.util.LaRequestUtil;
import org.lastaflute.web.util.LaResponseUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
public abstract class BaseApiManager implements WebApiManager {
private static final String API_FORMAT_TYPE = "apiFormatType";
@ -35,7 +35,7 @@ public abstract class BaseApiManager implements WebApiManager {
protected String pathPrefix;
protected enum FormatType {
SEARCH, LABEL, POPULARWORD, FAVORITE, FAVORITES, PING, SCROLL, SUGGEST, OTHER;
SEARCH, LABEL, POPULARWORD, FAVORITE, FAVORITES, OTHER, PING, SCROLL;
}
public String getPathPrefix() {
@ -51,13 +51,6 @@ public abstract class BaseApiManager implements WebApiManager {
if (formatType != null) {
return formatType;
}
formatType = detectFormatType(request);
request.setAttribute(API_FORMAT_TYPE, formatType);
return formatType;
}
protected FormatType detectFormatType(final HttpServletRequest request) {
String value = request.getParameter("type");
if (value == null) {
final String servletPath = request.getServletPath();
@ -67,36 +60,30 @@ public abstract class BaseApiManager implements WebApiManager {
}
}
if (value == null) {
return FormatType.SEARCH;
formatType = FormatType.SEARCH;
} else {
final String type = value.toUpperCase(Locale.ROOT);
if (FormatType.SEARCH.name().equals(type)) {
formatType = FormatType.SEARCH;
} else if (FormatType.LABEL.name().equals(type)) {
formatType = FormatType.LABEL;
} else if (FormatType.POPULARWORD.name().equals(type)) {
formatType = FormatType.POPULARWORD;
} else if (FormatType.FAVORITE.name().equals(type)) {
formatType = FormatType.FAVORITE;
} else if (FormatType.FAVORITES.name().equals(type)) {
formatType = FormatType.FAVORITES;
} else if (FormatType.PING.name().equals(type)) {
formatType = FormatType.PING;
} else if (FormatType.SCROLL.name().equals(type)) {
formatType = FormatType.SCROLL;
} else {
// default
formatType = FormatType.OTHER;
}
}
final String type = value.toUpperCase(Locale.ROOT);
if (FormatType.SEARCH.name().equals(type)) {
return FormatType.SEARCH;
}
if (FormatType.LABEL.name().equals(type)) {
return FormatType.LABEL;
}
if (FormatType.POPULARWORD.name().equals(type)) {
return FormatType.POPULARWORD;
}
if (FormatType.FAVORITE.name().equals(type)) {
return FormatType.FAVORITE;
}
if (FormatType.FAVORITES.name().equals(type)) {
return FormatType.FAVORITES;
}
if (FormatType.PING.name().equals(type)) {
return FormatType.PING;
}
if (FormatType.SCROLL.name().equals(type)) {
return FormatType.SCROLL;
}
if (FormatType.SUGGEST.name().equals(type)) {
return FormatType.SUGGEST;
}
// default
return FormatType.OTHER;
request.setAttribute(API_FORMAT_TYPE, formatType);
return formatType;
}
protected void write(final String text, final String contentType, final String encoding) {
@ -109,7 +96,11 @@ public abstract class BaseApiManager implements WebApiManager {
buf.append("; charset=");
final String enc;
if (encoding == null) {
enc = LaRequestUtil.getOptionalRequest().map(HttpServletRequest::getCharacterEncoding).orElse(Constants.UTF_8);
if (LaRequestUtil.getRequest().getCharacterEncoding() == null) {
enc = Constants.UTF_8;
} else {
enc = LaRequestUtil.getRequest().getCharacterEncoding();
}
} else {
enc = encoding;
}

View file

@ -0,0 +1,172 @@
/*
* Copyright 2012-2022 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.api;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.text.StringEscapeUtils;
import org.codelibs.core.CoreLibConstants;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.exception.InvalidAccessTokenException;
import org.codelibs.fess.util.ComponentUtil;
import org.lastaflute.web.util.LaRequestUtil;
import org.lastaflute.web.util.LaResponseUtil;
public abstract class BaseJsonApiManager extends BaseApiManager {
protected String mimeType = "application/json";
protected void writeJsonResponse(final int status, final String body, final Throwable t) {
if (t == null) {
writeJsonResponse(status, body, (String) null);
return;
}
if (t instanceof final InvalidAccessTokenException e) {
final HttpServletResponse response = LaResponseUtil.getResponse();
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setHeader("WWW-Authenticate", "Bearer error=\"" + e.getType() + "\"");
}
final StringBuilder sb = new StringBuilder();
if (StringUtil.isBlank(t.getMessage())) {
sb.append(t.getClass().getName());
} else {
sb.append(t.getMessage());
}
final StringWriter sw = new StringWriter();
t.printStackTrace(new PrintWriter(sw));
sb.append(" [ ").append(sw.toString()).append(" ]");
try {
sw.close();
} catch (final IOException ignore) {}
writeJsonResponse(status, body, sb.toString());
}
protected void writeJsonResponse(final int status, final String body, final String errMsg) {
String content = null;
if (status == 0) {
if (StringUtil.isNotBlank(body)) {
content = body;
}
} else {
content = "\"message\":" + escapeJson(errMsg);
}
writeJsonResponse(status, content);
}
protected void writeJsonResponse(final int status, final String body) {
final String callback = LaRequestUtil.getRequest().getParameter("callback");
final boolean isJsonp = ComponentUtil.getFessConfig().isApiJsonpEnabled() && StringUtil.isNotBlank(callback);
final StringBuilder buf = new StringBuilder(1000);
if (isJsonp) {
buf.append(escapeCallbackName(callback));
buf.append('(');
}
buf.append("{\"response\":");
buf.append("{\"version\":\"");
buf.append(ComponentUtil.getSystemHelper().getProductVersion());
buf.append("\",");
buf.append("\"status\":");
buf.append(status);
if (StringUtil.isNotBlank(body)) {
buf.append(',');
buf.append(body);
}
buf.append('}');
buf.append('}');
if (isJsonp) {
buf.append(')');
}
write(buf.toString(), mimeType, Constants.UTF_8);
}
protected String escapeCallbackName(final String callbackName) {
return "/**/" + callbackName.replaceAll("[^0-9a-zA-Z_\\$\\.]", StringUtil.EMPTY);
}
protected String escapeJson(final Object obj) {
if (obj == null) {
return "null";
}
final StringBuilder buf = new StringBuilder(255);
if (obj instanceof String[]) {
buf.append('[');
boolean first = true;
for (final Object child : (String[]) obj) {
if (first) {
first = false;
} else {
buf.append(',');
}
buf.append(escapeJson(child));
}
buf.append(']');
} else if (obj instanceof List<?>) {
buf.append('[');
boolean first = true;
for (final Object child : (List<?>) obj) {
if (first) {
first = false;
} else {
buf.append(',');
}
buf.append(escapeJson(child));
}
buf.append(']');
} else if (obj instanceof Map<?, ?>) {
buf.append('{');
boolean first = true;
for (final Map.Entry<?, ?> entry : ((Map<?, ?>) obj).entrySet()) {
if (first) {
first = false;
} else {
buf.append(',');
}
buf.append(escapeJson(entry.getKey())).append(':').append(escapeJson(entry.getValue()));
}
buf.append('}');
} else if ((obj instanceof Integer) || (obj instanceof Long) || (obj instanceof Float) || (obj instanceof Double)) {
buf.append((obj));
} else if (obj instanceof Boolean) {
buf.append(obj.toString());
} else if (obj instanceof Date) {
final SimpleDateFormat sdf = new SimpleDateFormat(CoreLibConstants.DATE_FORMAT_ISO_8601_EXTEND, Locale.ROOT);
buf.append('\"').append(StringEscapeUtils.escapeJson(sdf.format(obj))).append('\"');
} else {
buf.append('\"').append(StringEscapeUtils.escapeJson(obj.toString())).append('\"');
}
return buf.toString();
}
public void setMimeType(final String mimeType) {
this.mimeType = mimeType;
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -17,10 +17,10 @@ package org.codelibs.fess.api;
import java.io.IOException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface WebApiManager {

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -19,7 +19,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import jakarta.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequest;
public class WebApiManagerFactory {

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -15,8 +15,8 @@
*/
package org.codelibs.fess.api;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class WebApiRequest extends HttpServletRequestWrapper {
protected String servletPath;

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -18,10 +18,10 @@ package org.codelibs.fess.api;
import java.io.IOException;
import java.io.PrintWriter;
import org.apache.commons.io.output.ByteArrayOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletResponseWrapper;
import org.apache.commons.io.output.ByteArrayOutputStream;
public class WebApiResponse extends HttpServletResponseWrapper {

View file

@ -1,252 +0,0 @@
/*
* Copyright 2012-2024 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.api.engine;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Locale;
import java.util.UUID;
import org.apache.catalina.connector.ClientAbortException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.codelibs.core.io.CopyUtil;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.curl.Curl.Method;
import org.codelibs.curl.CurlRequest;
import org.codelibs.curl.CurlResponse;
import org.codelibs.fess.Constants;
import org.codelibs.fess.api.BaseApiManager;
import org.codelibs.fess.exception.FessSystemException;
import org.codelibs.fess.exception.WebApiException;
import org.codelibs.fess.mylasta.action.FessUserBean;
import org.codelibs.fess.util.ComponentUtil;
import org.codelibs.fess.util.ResourceUtil;
import org.lastaflute.web.servlet.request.RequestManager;
import org.lastaflute.web.servlet.session.SessionManager;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
public class SearchEngineApiManager extends BaseApiManager {
private static final String ADMIN_SERVER = "/admin/server_";
private static final Logger logger = LogManager.getLogger(SearchEngineApiManager.class);
protected String[] acceptedRoles = { "admin" };
public SearchEngineApiManager() {
setPathPrefix(ADMIN_SERVER);
}
@PostConstruct
public void register() {
if (logger.isInfoEnabled()) {
logger.info("Load {}", this.getClass().getSimpleName());
}
ComponentUtil.getWebApiManagerFactory().add(this);
}
@Override
public boolean matches(final HttpServletRequest request) {
final String servletPath = request.getServletPath();
return servletPath.startsWith(pathPrefix);
}
@Override
public void process(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain)
throws IOException, ServletException {
final RequestManager requestManager = ComponentUtil.getRequestManager();
if (!requestManager.findUserBean(FessUserBean.class).map(user -> user.hasRoles(acceptedRoles)).orElse(Boolean.FALSE)) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized access: " + request.getServletPath());
return;
}
try {
getSessionManager().getAttribute(Constants.SEARCH_ENGINE_API_ACCESS_TOKEN, String.class).ifPresent(token -> {
final String servletPath = request.getServletPath();
final String pathPrefix = ADMIN_SERVER + token;
if (!servletPath.startsWith(pathPrefix)) {
throw new WebApiException(HttpServletResponse.SC_FORBIDDEN, "Invalid access token.");
}
final String path;
final String value = servletPath.substring(pathPrefix.length());
if (!value.startsWith("/")) {
path = "/" + value;
} else {
path = value;
}
processRequest(request, response, path);
}).orElse(() -> {
throw new WebApiException(HttpServletResponse.SC_FORBIDDEN, "Invalid session.");
});
} catch (final WebApiException e) {
String message;
if (Constants.TRUE.equalsIgnoreCase(ComponentUtil.getFessConfig().getApiJsonResponseExceptionIncluded())) {
logger.warn("Failed to access to Web API.", e);
message = e.getMessage();
} else {
final String errorCode = UUID.randomUUID().toString();
message = "[" + errorCode + "] Failed to access to Web API.";
logger.warn(message, e);
}
response.sendError(e.getStatusCode(), message);
}
}
protected void processRequest(final HttpServletRequest request, final HttpServletResponse response, final String path) {
if ("/_plugin".equals(path) || path.startsWith("/_plugin/")) {
processPluginRequest(request, response, path.replaceFirst("^/_plugin", StringUtil.EMPTY));
return;
}
final Method httpMethod = Method.valueOf(request.getMethod().toUpperCase(Locale.ROOT));
final CurlRequest curlRequest = ComponentUtil.getCurlHelper().request(httpMethod, path);
final String contentType = request.getHeader("Content-Type");
if (StringUtil.isNotEmpty(contentType)) {
curlRequest.header("Content-Type", contentType);
}
request.getParameterMap().entrySet().stream().forEach(entry -> {
if (entry.getValue().length > 1) {
curlRequest.param(entry.getKey(), String.join(",", entry.getValue()));
} else if (entry.getValue().length == 1) {
curlRequest.param(entry.getKey(), entry.getValue()[0]);
}
});
try (final CurlResponse curlResponse = curlRequest.onConnect((req, con) -> {
con.setDoOutput(true);
if (httpMethod != Method.GET && request.getContentLength() > 2) {
try (ServletInputStream in = request.getInputStream(); OutputStream out = con.getOutputStream()) {
CopyUtil.copy(in, out);
} catch (final IOException e) {
throw new WebApiException(HttpServletResponse.SC_BAD_REQUEST, e);
}
}
}).execute()) {
try (ServletOutputStream out = response.getOutputStream(); InputStream in = curlResponse.getContentAsStream()) {
response.setStatus(curlResponse.getHttpStatusCode());
writeHeaders(response);
final String responseContentType = curlResponse.getHeaderValue("Content-Type");
if (StringUtil.isBlank(responseContentType)) {
response.setHeader("Content-Type", "application/json");
} else {
response.setHeader("Content-Type", responseContentType);
}
CopyUtil.copy(in, out);
} catch (final ClientAbortException e) {
logger.debug("Client aborts this request.", e);
}
} catch (final Exception e) {
if (!(e.getCause() instanceof ClientAbortException)) {
throw new WebApiException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
}
logger.debug("Client aborts this request.", e);
}
}
protected void processPluginRequest(final HttpServletRequest request, final HttpServletResponse response, final String path) {
if (StringUtil.isNotBlank(path)) {
final String lowerPath = path.toLowerCase(Locale.ROOT);
if (lowerPath.endsWith(".html")) {
response.setContentType("text/html;charset=utf-8");
} else if (lowerPath.endsWith(".css")) {
response.setContentType("text/css");
} else if (lowerPath.endsWith(".eot")) {
response.setContentType("application/vnd.ms-fontobject");
} else if (lowerPath.endsWith(".ico")) {
response.setContentType("image/vnd.microsoft.icon");
} else if (lowerPath.endsWith(".js")) {
response.setContentType("text/javascript");
} else if (lowerPath.endsWith(".json")) {
response.setContentType("application/json");
} else if (lowerPath.endsWith(".otf")) {
response.setContentType("font/otf");
} else if (lowerPath.endsWith(".svg")) {
response.setContentType("image/svg+xml");
} else if (lowerPath.endsWith(".ttf")) {
response.setContentType("font/ttf");
} else if (lowerPath.endsWith(".txt")) {
response.setContentType("text/plain");
} else if (lowerPath.endsWith(".woff")) {
response.setContentType("font/woff");
} else if (lowerPath.endsWith(".woff2")) {
response.setContentType("font/woff2");
} else if (lowerPath.endsWith("/")) {
response.setContentType("text/html;charset=utf-8");
}
}
Path filePath = ResourceUtil.getSitePath(path.replaceAll("\\.\\.+", StringUtil.EMPTY).replaceAll("/+", "/").split("/"));
if (Files.isDirectory(filePath)) {
filePath = filePath.resolve("index.html");
}
if (Files.exists(filePath)) {
try (InputStream in = Files.newInputStream(filePath); ServletOutputStream out = response.getOutputStream()) {
response.setStatus(HttpServletResponse.SC_OK);
writeHeaders(response);
CopyUtil.copy(in, out);
} catch (final ClientAbortException e) {
logger.debug("Client aborts this request.", e);
} catch (final IOException e) {
logger.error("Failed to read {} from {}", path, filePath);
throw new WebApiException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
}
} else {
try {
writeHeaders(response);
response.sendError(HttpServletResponse.SC_NOT_FOUND, path + " is not found.");
} catch (final ClientAbortException e) {
logger.debug("Client aborts this request.", e);
} catch (final IOException e) {
logger.error("Failed to read {} from {}", path, filePath);
throw new WebApiException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
}
}
}
public void setAcceptedRoles(final String[] acceptedRoles) {
this.acceptedRoles = acceptedRoles;
}
public String getServerPath() {
return getSessionManager().getAttribute(Constants.SEARCH_ENGINE_API_ACCESS_TOKEN, String.class).map(token -> ADMIN_SERVER + token)
.orElseThrow(() -> new FessSystemException("Cannot create an access token."));
}
public void saveToken() {
getSessionManager().setAttribute(Constants.SEARCH_ENGINE_API_ACCESS_TOKEN, UUID.randomUUID().toString().replace("-", ""));
}
private SessionManager getSessionManager() {
return ComponentUtil.getComponent(SessionManager.class);
}
@Override
protected void writeHeaders(final HttpServletResponse response) {
ComponentUtil.getFessConfig().getApiDashboardResponseHeaderList().forEach(e -> response.setHeader(e.getFirst(), e.getSecond()));
}
}

View file

@ -0,0 +1,218 @@
/*
* Copyright 2012-2022 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.api.es;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Locale;
import java.util.UUID;
import javax.annotation.PostConstruct;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.connector.ClientAbortException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.codelibs.core.io.CopyUtil;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.curl.Curl.Method;
import org.codelibs.curl.CurlRequest;
import org.codelibs.curl.CurlResponse;
import org.codelibs.fess.Constants;
import org.codelibs.fess.api.BaseApiManager;
import org.codelibs.fess.exception.FessSystemException;
import org.codelibs.fess.exception.WebApiException;
import org.codelibs.fess.mylasta.action.FessUserBean;
import org.codelibs.fess.util.ComponentUtil;
import org.codelibs.fess.util.ResourceUtil;
import org.lastaflute.web.servlet.request.RequestManager;
import org.lastaflute.web.servlet.session.SessionManager;
public class EsApiManager extends BaseApiManager {
private static final String ADMIN_SERVER = "/admin/server_";
private static final Logger logger = LogManager.getLogger(EsApiManager.class);
protected String[] acceptedRoles = { "admin" };
public EsApiManager() {
setPathPrefix(ADMIN_SERVER);
}
@PostConstruct
public void register() {
if (logger.isInfoEnabled()) {
logger.info("Load {}", this.getClass().getSimpleName());
}
ComponentUtil.getWebApiManagerFactory().add(this);
}
@Override
public boolean matches(final HttpServletRequest request) {
final String servletPath = request.getServletPath();
return servletPath.startsWith(pathPrefix);
}
@Override
public void process(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain)
throws IOException, ServletException {
final RequestManager requestManager = ComponentUtil.getRequestManager();
if (!requestManager.findUserBean(FessUserBean.class).map(user -> user.hasRoles(acceptedRoles)).orElse(Boolean.FALSE)) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized access: " + request.getServletPath());
return;
}
try {
getSessionManager().getAttribute(Constants.ES_API_ACCESS_TOKEN, String.class).ifPresent(token -> {
final String servletPath = request.getServletPath();
final String pathPrefix = ADMIN_SERVER + token;
if (!servletPath.startsWith(pathPrefix)) {
throw new WebApiException(HttpServletResponse.SC_FORBIDDEN, "Invalid access token.");
}
final String path;
final String value = servletPath.substring(pathPrefix.length());
if (!value.startsWith("/")) {
path = "/" + value;
} else {
path = value;
}
processRequest(request, response, path);
}).orElse(() -> {
throw new WebApiException(HttpServletResponse.SC_FORBIDDEN, "Invalid session.");
});
} catch (final WebApiException e) {
logger.debug("Failed to access to Web API.", e);
response.sendError(e.getStatusCode(), e.getMessage());
}
}
protected void processRequest(final HttpServletRequest request, final HttpServletResponse response, final String path) {
if (StringUtil.isNotBlank(path)) {
final String lowerPath = path.toLowerCase(Locale.ROOT);
if (lowerPath.endsWith(".html")) {
response.setContentType("text/html;charset=utf-8");
} else if (lowerPath.endsWith(".txt")) {
response.setContentType("text/plain");
} else if (lowerPath.endsWith(".css")) {
response.setContentType("text/css");
}
}
if ("/_plugin".equals(path) || path.startsWith("/_plugin/")) {
processPluginRequest(request, response, path.replaceFirst("^/_plugin", StringUtil.EMPTY));
return;
}
final Method httpMethod = Method.valueOf(request.getMethod().toUpperCase(Locale.ROOT));
final CurlRequest curlRequest = ComponentUtil.getCurlHelper().request(httpMethod, path);
final String contentType = request.getHeader("Content-Type");
if (StringUtil.isNotEmpty(contentType)) {
curlRequest.header("Content-Type", contentType);
}
request.getParameterMap().entrySet().stream().forEach(entry -> {
if (entry.getValue().length > 1) {
curlRequest.param(entry.getKey(), String.join(",", entry.getValue()));
} else if (entry.getValue().length == 1) {
curlRequest.param(entry.getKey(), entry.getValue()[0]);
}
});
try (final CurlResponse curlResponse = curlRequest.onConnect((req, con) -> {
con.setDoOutput(true);
if (httpMethod != Method.GET && request.getContentLength() > 2) {
try (ServletInputStream in = request.getInputStream(); OutputStream out = con.getOutputStream()) {
CopyUtil.copy(in, out);
} catch (final IOException e) {
throw new WebApiException(HttpServletResponse.SC_BAD_REQUEST, e);
}
}
}).execute()) {
try (ServletOutputStream out = response.getOutputStream(); InputStream in = curlResponse.getContentAsStream()) {
response.setStatus(curlResponse.getHttpStatusCode());
writeHeaders(response);
CopyUtil.copy(in, out);
} catch (final ClientAbortException e) {
logger.debug("Client aborts this request.", e);
}
} catch (final Exception e) {
if (!(e.getCause() instanceof ClientAbortException)) {
throw new WebApiException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
}
logger.debug("Client aborts this request.", e);
}
}
protected void processPluginRequest(final HttpServletRequest request, final HttpServletResponse response, final String path) {
Path filePath = ResourceUtil.getSitePath(path.replaceAll("\\.\\.+", StringUtil.EMPTY).replaceAll("/+", "/").split("/"));
if (Files.isDirectory(filePath)) {
filePath = filePath.resolve("index.html");
}
if (Files.exists(filePath)) {
try (InputStream in = Files.newInputStream(filePath); ServletOutputStream out = response.getOutputStream()) {
response.setStatus(HttpServletResponse.SC_OK);
writeHeaders(response);
CopyUtil.copy(in, out);
} catch (final ClientAbortException e) {
logger.debug("Client aborts this request.", e);
} catch (final IOException e) {
logger.error("Failed to read {} from {}", path, filePath);
throw new WebApiException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
}
} else {
try {
writeHeaders(response);
response.sendError(HttpServletResponse.SC_NOT_FOUND, path + " is not found.");
} catch (final ClientAbortException e) {
logger.debug("Client aborts this request.", e);
} catch (final IOException e) {
logger.error("Failed to read {} from {}", path, filePath);
throw new WebApiException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
}
}
}
public void setAcceptedRoles(final String[] acceptedRoles) {
this.acceptedRoles = acceptedRoles;
}
public String getServerPath() {
return getSessionManager().getAttribute(Constants.ES_API_ACCESS_TOKEN, String.class).map(token -> ADMIN_SERVER + token)
.orElseThrow(() -> new FessSystemException("Cannot create an access token."));
}
public void saveToken() {
getSessionManager().setAttribute(Constants.ES_API_ACCESS_TOKEN, UUID.randomUUID().toString().replace("-", ""));
}
private SessionManager getSessionManager() {
return ComponentUtil.getComponent(SessionManager.class);
}
@Override
protected void writeHeaders(final HttpServletResponse response) {
ComponentUtil.getFessConfig().getApiDashboardResponseHeaderList().forEach(e -> response.setHeader(e.getFirst(), e.getSecond()));
}
}

View file

@ -0,0 +1,645 @@
/*
* Copyright 2012-2022 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.api.gsa;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.PostConstruct;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.text.StringEscapeUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.codelibs.core.CoreLibConstants;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.api.BaseApiManager;
import org.codelibs.fess.api.WebApiRequest;
import org.codelibs.fess.entity.FacetInfo;
import org.codelibs.fess.entity.GeoInfo;
import org.codelibs.fess.entity.HighlightInfo;
import org.codelibs.fess.entity.SearchRenderData;
import org.codelibs.fess.entity.SearchRequestParams;
import org.codelibs.fess.exception.InvalidAccessTokenException;
import org.codelibs.fess.helper.SearchHelper;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.util.ComponentUtil;
import org.codelibs.fess.util.DocumentUtil;
import org.dbflute.optional.OptionalThing;
public class GsaApiManager extends BaseApiManager {
private static final Logger logger = LogManager.getLogger(GsaApiManager.class);
private static final String OUTPUT_XML = "xml"; // or xml_no_dtd
// http://www.google.com/google.dtd.
protected String gsaPathPrefix = "/gsa";
@PostConstruct
public void register() {
if (logger.isInfoEnabled()) {
logger.info("Load {}", this.getClass().getSimpleName());
}
ComponentUtil.getWebApiManagerFactory().add(this);
}
@Override
public boolean matches(final HttpServletRequest request) {
final FessConfig fessConfig = ComponentUtil.getFessConfig();
if (!fessConfig.isWebApiGsa()) {
return false;
}
final String servletPath = request.getServletPath();
return servletPath.startsWith(gsaPathPrefix);
}
@Override
public void process(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain)
throws IOException, ServletException {
switch (getFormatType(request)) {
case SEARCH:
processSearchRequest(request, response, chain);
break;
default:
writeXmlResponse(99, false, StringUtil.EMPTY, "Not found.");
break;
}
}
protected void appendParam(final StringBuilder buf, final String name, final String value) throws UnsupportedEncodingException {
appendParam(buf, name, value, URLEncoder.encode(value, Constants.UTF_8));
}
protected void appendParam(final StringBuilder buf, final String name, final String value, final String original) {
buf.append("<PARAM name=\"");
buf.append(escapeXml(name));
buf.append("\" value=\"");
buf.append(escapeXml(value));
buf.append("\" original_value=\"");
buf.append(escapeXml(original));
buf.append("\"/>");
}
protected void processSearchRequest(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) {
final SearchHelper searchHelper = ComponentUtil.getSearchHelper();
final FessConfig fessConfig = ComponentUtil.getFessConfig();
final boolean xmlDtd = OUTPUT_XML.equals(request.getParameter("output"));
if (!fessConfig.isAcceptedSearchReferer(request.getHeader("referer"))) {
writeXmlResponse(99, xmlDtd, StringUtil.EMPTY, "Referer is invalid.");
return;
}
int status = 0;
String errMsg = StringUtil.EMPTY;
String query = null;
final StringBuilder buf = new StringBuilder(1000);
request.setAttribute(Constants.SEARCH_LOG_ACCESS_TYPE, Constants.SEARCH_LOG_ACCESS_TYPE_GSA);
try {
final SearchRenderData data = new SearchRenderData();
final GsaRequestParams params = new GsaRequestParams(request, fessConfig);
query = params.getQuery();
searchHelper.search(params, data, OptionalThing.empty());
final String execTime = data.getExecTime();
final long allRecordCount = data.getAllRecordCount();
final List<Map<String, Object>> documentItems = data.getDocumentItems();
final List<String> getFields = new ArrayList<>();
// meta tags should be returned
final String getFieldsParam = request.getParameter("getfields");
if (StringUtil.isNotBlank(getFieldsParam)) {
getFields.addAll(Arrays.asList(getFieldsParam.split("\\.")));
}
final StringBuilder requestUri = new StringBuilder(request.getRequestURI());
if (request.getQueryString() != null) {
requestUri.append("?").append(request.getQueryString());
}
final String uriQueryString = requestUri.toString();
// Input/Output encoding
final String ie = request.getCharacterEncoding();
final String oe = "UTF-8";
// IP address
final String ip = ComponentUtil.getViewHelper().getClientIp(request);
buf.append("<TM>");
buf.append(execTime);
buf.append("</TM>");
buf.append("<Q>");
buf.append(escapeXml(query));
buf.append("</Q>");
for (final Entry<String, String[]> entry : request.getParameterMap().entrySet()) {
final String[] values = entry.getValue();
if (values == null) {
continue;
}
final String key = entry.getKey();
if ("sort".equals(key)) {
continue;
}
for (final String value : values) {
appendParam(buf, key, value);
}
}
appendParam(buf, "ie", ie);
if (request.getParameter("oe") == null) {
appendParam(buf, "oe", oe);
}
final String[] langs = params.getLanguages();
if (langs.length > 0) {
appendParam(buf, "inlang", langs[0]);
appendParam(buf, "ulang", langs[0]);
}
appendParam(buf, "ip", ip);
appendParam(buf, "access", "p");
appendParam(buf, "sort", params.getSortParam(), params.getSortParam());
appendParam(buf, "entqr", "3");
appendParam(buf, "entqrm", "0");
appendParam(buf, "wc", "200");
appendParam(buf, "wc_mc", "1");
if (!documentItems.isEmpty()) {
buf.append("<RES SN=\"");
buf.append(data.getCurrentStartRecordNumber());
buf.append("\" EN=\"");
buf.append(data.getCurrentEndRecordNumber());
buf.append("\">");
buf.append("<M>");
buf.append(allRecordCount);
buf.append("</M>");
if (data.isExistPrevPage() || data.isExistNextPage()) {
buf.append("<NB>");
if (data.isExistPrevPage()) {
long s = data.getCurrentStartRecordNumber() - data.getPageSize() - 1;
if (s < 0) {
s = 0;
}
buf.append("<PU>");
buf.append(escapeXml(uriQueryString.replaceFirst("start=([0-9]+)", "start=" + s)));
buf.append("</PU>");
}
if (data.isExistNextPage()) {
buf.append("<NU>");
buf.append(escapeXml(uriQueryString.replaceFirst("start=([0-9]+)", "start=" + data.getCurrentEndRecordNumber())));
buf.append("</NU>");
}
buf.append("</NB>");
}
long recordNumber = data.getCurrentStartRecordNumber();
for (final Map<String, Object> document : documentItems) {
buf.append("<R N=\"");
buf.append(recordNumber);
buf.append("\">");
final String url = DocumentUtil.getValue(document, fessConfig.getIndexFieldUrl(), String.class);
document.put("UE", url);
document.put("U", URLDecoder.decode(url, Constants.UTF_8));
document.put("T", DocumentUtil.getValue(document, fessConfig.getResponseFieldContentTitle(), String.class));
final float score = DocumentUtil.getValue(document, Constants.SCORE, Float.class, Float.NaN);
int rk = 10;
if (!Float.isNaN(score)) {
if (score < 0.0) {
rk = 0;
} else if (score > 1.0) {
rk = 10;
} else {
rk = (int) (score * 10.0);
}
}
document.put("RK", rk);
document.put("S", DocumentUtil.getValue(document, fessConfig.getResponseFieldContentDescription(), String.class,
StringUtil.EMPTY));
final String lang = DocumentUtil.getValue(document, fessConfig.getIndexFieldLang(), String.class);
if (StringUtil.isNotBlank(lang)) {
document.put("LANG", lang);
document.remove(fessConfig.getIndexFieldLang());
}
final String gsaMetaPrefix = fessConfig.getQueryGsaMetaPrefix();
for (final Map.Entry<String, Object> entry : document.entrySet()) {
final String name = entry.getKey();
if (StringUtil.isNotBlank(name) && entry.getValue() != null && fessConfig.isGsaResponseFields(name)) {
if (name.startsWith(gsaMetaPrefix)) {
final String tagName = name.replaceFirst("^" + gsaMetaPrefix, StringUtil.EMPTY);
if (getFields.contains(tagName)) {
buf.append("<MT N=\"");
buf.append(tagName);
buf.append("\" V=\"");
buf.append(escapeXml(entry.getValue()));
buf.append("\"/>");
}
} else {
final String tagName = name;
buf.append('<');
buf.append(tagName);
buf.append('>');
buf.append(escapeXml(entry.getValue()));
buf.append("</");
buf.append(tagName);
buf.append('>');
}
}
}
buf.append("<ENT_SOURCE>").append(escapeXml("FESS")).append("</ENT_SOURCE>");
String lastModified = DocumentUtil.getValue(document, fessConfig.getIndexFieldLastModified(), String.class);
if (StringUtil.isBlank(lastModified)) {
lastModified = StringUtil.EMPTY;
}
lastModified = lastModified.split("T")[0];
buf.append("<FS NAME=\"date\" VALUE=\"").append(escapeXml(lastModified)).append("\"/>");
buf.append("<HAS>");
buf.append("<L/>");
buf.append("<C SZ=\"");
buf.append(DocumentUtil.getValue(document, fessConfig.getIndexFieldContentLength(), Long.class, (long) 0).longValue()
/ 1000);
document.remove(fessConfig.getIndexFieldContentLength());
buf.append("k\" CID=\"");
buf.append(DocumentUtil.getValue(document, fessConfig.getIndexFieldDocId(), String.class));
document.remove(fessConfig.getIndexFieldDocId());
buf.append("\" ENC=\"");
final String charsetField = fessConfig.getQueryGsaIndexFieldCharset();
String charset = DocumentUtil.getValue(document, charsetField, String.class);
document.remove(charsetField);
if (StringUtil.isBlank(charset)) {
final String contentTypeField = fessConfig.getQueryGsaIndexFieldContentType();
charset = DocumentUtil.getValue(document, contentTypeField, String.class);
document.remove(contentTypeField);
if (StringUtil.isNotBlank(charset)) {
final Matcher m = Pattern.compile(".*;\\s*charset=(.+)").matcher(charset);
if (m.matches()) {
charset = m.group(1);
}
}
if (StringUtil.isBlank(charset)) {
charset = Constants.UTF_8;
}
}
buf.append(charset);
buf.append("\"/>");
buf.append("</HAS>");
buf.append("</R>");
recordNumber++;
}
buf.append("</RES>");
}
} catch (final Exception e) {
status = 1;
errMsg = e.getMessage();
if (errMsg == null) {
errMsg = e.getClass().getName();
}
if (logger.isDebugEnabled()) {
logger.debug("Failed to process a search request.", e);
}
if (e instanceof final InvalidAccessTokenException iate) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setHeader("WWW-Authenticate", "Bearer error=\"" + iate.getType() + "\"");
}
}
writeXmlResponse(status, xmlDtd, buf.toString(), errMsg);
}
protected void writeXmlResponse(final int status, final boolean xmlDtd, final String body, final String errMsg) {
final StringBuilder buf = new StringBuilder(1000);
buf.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>");
if (xmlDtd) {
buf.append("<!DOCTYPE GSP SYSTEM \"google.dtd\">");
}
buf.append("<GSP VER=\"");
buf.append(Constants.GSA_API_VERSION);
buf.append("\">");
if (status == 0) {
buf.append(body);
} else {
buf.append("<message>");
buf.append(escapeXml(errMsg));
buf.append("</message>");
}
buf.append("</GSP>");
write(buf.toString(), "text/xml", Constants.UTF_8);
}
protected String escapeXml(final Object obj) {
final StringBuilder buf = new StringBuilder(255);
if (obj instanceof List<?>) {
buf.append("<list>");
for (final Object child : (List<?>) obj) {
buf.append("<item>").append(escapeXml(child)).append("</item>");
}
buf.append("</list>");
} else if (obj instanceof Map<?, ?>) {
buf.append("<data>");
for (final Map.Entry<?, ?> entry : ((Map<?, ?>) obj).entrySet()) {
buf.append("<name>").append(escapeXml(entry.getKey())).append("</name><value>").append(escapeXml(entry.getValue()))
.append("</value>");
}
buf.append("</data>");
} else if (obj instanceof Date) {
final SimpleDateFormat sdf = new SimpleDateFormat(CoreLibConstants.DATE_FORMAT_ISO_8601_EXTEND);
buf.append(StringEscapeUtils.escapeXml10(sdf.format(obj)));
} else if (obj != null) {
buf.append(StringEscapeUtils.escapeXml10(obj.toString()));
}
return buf.toString();
}
public String getXmlPathPrefix() {
return gsaPathPrefix;
}
public void setXmlPathPrefix(final String xmlPathPrefix) {
this.gsaPathPrefix = xmlPathPrefix;
}
static class WrappedWebApiRequest extends WebApiRequest {
private Map<String, String[]> parameters;
private final Map<String, String[]> extraParameters;
public WrappedWebApiRequest(final HttpServletRequest request, final String servletPath, final Map<String, String[]> extraParams) {
super(request, servletPath);
extraParameters = extraParams;
}
@Override
public String getParameter(final String name) {
final String[] values = getParameterMap().get(name);
if (values != null) {
return values[0];
}
return super.getParameter(name);
}
@Override
public Map<String, String[]> getParameterMap() {
if (parameters == null) {
parameters = new HashMap<>();
parameters.putAll(super.getParameterMap());
// Parameter of the same key will be overwritten
parameters.putAll(extraParameters);
}
return Collections.unmodifiableMap(parameters);
}
@Override
public Enumeration<String> getParameterNames() {
return Collections.enumeration(getParameterMap().keySet());
}
@Override
public String[] getParameterValues(final String name) {
return getParameterMap().get(name);
}
}
protected static class GsaRequestParams extends SearchRequestParams {
private final HttpServletRequest request;
private final FessConfig fessConfig;
private int startPosition = -1;
private int pageSize = -1;
private String sortParam;
protected GsaRequestParams(final HttpServletRequest request, final FessConfig fessConfig) {
this.request = request;
this.fessConfig = fessConfig;
this.sortParam = request.getParameter("sort");
if (this.sortParam == null) {
this.sortParam = fessConfig.getQueryGsaDefaultSort();
}
}
@Override
public String getTrackTotalHits() {
return request.getParameter(Constants.TRACK_TOTAL_HITS);
}
@Override
public String getQuery() {
return request.getParameter("q");
}
@Override
public String[] getExtraQueries() {
final List<String> queryList = new ArrayList<>();
for (final String s : getParamValueArray(request, "ex_q")) {
queryList.add(s.trim());
}
final String gsaMetaPrefix = fessConfig.getQueryGsaMetaPrefix();
final String requiredFields = request.getParameter("requiredfields");
if (StringUtil.isNotBlank(requiredFields)) {
queryList.add(gsaMetaPrefix + requiredFields.replace(".", " AND " + gsaMetaPrefix).replace("|", " OR " + gsaMetaPrefix));
}
return queryList.toArray(new String[queryList.size()]);
}
@Override
public Map<String, String[]> getFields() {
final Map<String, String[]> fields = new HashMap<>();
for (final Map.Entry<String, String[]> entry : request.getParameterMap().entrySet()) {
final String key = entry.getKey();
if (key.startsWith("fields.")) {
final String[] value = simplifyArray(entry.getValue());
fields.put(key.substring("fields.".length()), value);
} else if ("site".equals(key)) {
final String[] value = simplifyArray(entry.getValue());
fields.put("label", value);
}
}
return fields;
}
@Override
public Map<String, String[]> getConditions() {
final Map<String, String[]> conditions = new HashMap<>();
for (final Map.Entry<String, String[]> entry : request.getParameterMap().entrySet()) {
final String key = entry.getKey();
if (key.startsWith("as_")) {
final String[] value = simplifyArray(entry.getValue());
conditions.put(key.substring("as_".length()), value);
}
}
return conditions;
}
@Override
public String[] getLanguages() {
final String[] langs = getParamValueArray(request, "ulang");
if (langs.length > 0) {
return langs;
}
if (request.getHeader("Accept-Language") != null) {
return Collections.list(request.getLocales()).stream().map(Locale::getLanguage).toArray(n -> new String[n]);
}
return new String[] { fessConfig.getQueryGsaDefaultLang() };
}
@Override
public GeoInfo getGeoInfo() {
return createGeoInfo(request);
}
@Override
public FacetInfo getFacetInfo() {
return createFacetInfo(request);
}
public String getSortParam() {
return sortParam;
}
@Override
public String getSort() {
// Sort By Relevance (Default)
// Sort By Date: date:<direction>:<mode>:<format>
// Sort by Metadata: meta:<name>:<direction>:<mode>:<language>:<case>:<numeric>
if (StringUtil.isBlank(sortParam)) {
return null;
}
final String[] values = sortParam.split(":");
if (values.length > 0) {
if ("date".equals(values[0])) {
final StringBuilder buf = new StringBuilder();
buf.append(fessConfig.getIndexFieldTimestamp());
if (values.length > 1) {
if ("A".equals(values[1])) {
buf.append(".asc");
} else if ("D".equals(values[1])) {
buf.append(".desc");
}
}
buf.append(",score.desc");
return buf.toString();
}
if ("meta".equals(values[0]) && values.length > 1) {
final StringBuilder buf = new StringBuilder();
buf.append(fessConfig.getQueryGsaMetaPrefix() + values[1]);
if (values.length > 2) {
if ("A".equals(values[2])) {
buf.append(".asc");
} else if ("D".equals(values[2])) {
buf.append(".desc");
}
}
buf.append(",score.desc");
return buf.toString();
}
}
sortParam = "";
return null;
}
@Override
public int getStartPosition() {
if (startPosition != -1) {
return startPosition;
}
final String start = request.getParameter("start");
if (StringUtil.isBlank(start)) {
startPosition = fessConfig.getPagingSearchPageStartAsInteger();
} else {
try {
startPosition = Integer.parseInt(start);
} catch (final NumberFormatException e) {
startPosition = fessConfig.getPagingSearchPageStartAsInteger();
}
}
return startPosition;
}
@Override
public int getPageSize() {
if (pageSize != -1) {
return pageSize;
}
final String num = request.getParameter("num");
if (StringUtil.isBlank(num)) {
pageSize = fessConfig.getPagingSearchPageSizeAsInteger();
} else {
try {
pageSize = Integer.parseInt(num);
if (pageSize > fessConfig.getPagingSearchPageMaxSizeAsInteger().intValue() || pageSize <= 0) {
pageSize = fessConfig.getPagingSearchPageMaxSizeAsInteger();
}
} catch (final NumberFormatException e) {
pageSize = fessConfig.getPagingSearchPageSizeAsInteger();
}
}
return pageSize;
}
@Override
public Object getAttribute(final String name) {
return request.getAttribute(name);
}
@Override
public Locale getLocale() {
return Locale.ROOT;
}
@Override
public SearchRequestType getType() {
return SearchRequestType.GSA;
}
@Override
public String getSimilarDocHash() {
return request.getParameter("sdh");
}
@Override
public HighlightInfo getHighlightInfo() {
return ComponentUtil.getViewHelper().createHighlightInfo();
}
}
public void setGsaPathPrefix(final String gsaPathPrefix) {
this.gsaPathPrefix = gsaPathPrefix;
}
@Override
protected void writeHeaders(final HttpServletResponse response) {
ComponentUtil.getFessConfig().getApiGsaResponseHeaderList().forEach(e -> response.setHeader(e.getFirst(), e.getSecond()));
}
}

View file

@ -0,0 +1,819 @@
/*
* Copyright 2012-2022 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.api.json;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.codelibs.core.exception.IORuntimeException;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.api.BaseJsonApiManager;
import org.codelibs.fess.app.service.FavoriteLogService;
import org.codelibs.fess.entity.FacetInfo;
import org.codelibs.fess.entity.GeoInfo;
import org.codelibs.fess.entity.HighlightInfo;
import org.codelibs.fess.entity.PingResponse;
import org.codelibs.fess.entity.SearchRenderData;
import org.codelibs.fess.entity.SearchRequestParams;
import org.codelibs.fess.entity.SearchRequestParams.SearchRequestType;
import org.codelibs.fess.es.client.SearchEngineClient;
import org.codelibs.fess.exception.WebApiException;
import org.codelibs.fess.helper.LabelTypeHelper;
import org.codelibs.fess.helper.PopularWordHelper;
import org.codelibs.fess.helper.RelatedContentHelper;
import org.codelibs.fess.helper.RelatedQueryHelper;
import org.codelibs.fess.helper.SearchHelper;
import org.codelibs.fess.helper.SystemHelper;
import org.codelibs.fess.helper.UserInfoHelper;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.util.ComponentUtil;
import org.codelibs.fess.util.DocumentUtil;
import org.codelibs.fess.util.FacetResponse;
import org.codelibs.fess.util.FacetResponse.Field;
import org.dbflute.optional.OptionalThing;
import org.opensearch.script.Script;
public class JsonApiManager extends BaseJsonApiManager {
private static final Logger logger = LogManager.getLogger(JsonApiManager.class);
public JsonApiManager() {
setPathPrefix("/json");
}
@PostConstruct
public void register() {
if (logger.isInfoEnabled()) {
logger.info("Load {}", this.getClass().getSimpleName());
}
ComponentUtil.getWebApiManagerFactory().add(this);
}
@Override
public boolean matches(final HttpServletRequest request) {
final FessConfig fessConfig = ComponentUtil.getFessConfig();
if (!fessConfig.isWebApiJson()) {
switch (getFormatType(request)) {
case SEARCH:
case LABEL:
case POPULARWORD:
return false;
default:
break;
}
}
final String servletPath = request.getServletPath();
return servletPath.startsWith(pathPrefix);
}
@Override
public void process(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain)
throws IOException, ServletException {
switch (getFormatType(request)) {
case SEARCH:
processSearchRequest(request, response, chain);
break;
case LABEL:
processLabelRequest(request, response, chain);
break;
case POPULARWORD:
processPopularWordRequest(request, response, chain);
break;
case FAVORITE:
processFavoriteRequest(request, response, chain);
break;
case FAVORITES:
processFavoritesRequest(request, response, chain);
break;
case PING:
processPingRequest(request, response, chain);
break;
case SCROLL:
processScrollSearchRequest(request, response, chain);
break;
default:
writeJsonResponse(99, StringUtil.EMPTY, "Not found.");
break;
}
}
protected void processScrollSearchRequest(final HttpServletRequest request, final HttpServletResponse response,
final FilterChain chain) {
final SearchHelper searchHelper = ComponentUtil.getSearchHelper();
final FessConfig fessConfig = ComponentUtil.getFessConfig();
if (!fessConfig.isAcceptedSearchReferer(request.getHeader("referer"))) {
writeJsonResponse(99, StringUtil.EMPTY, "Referer is invalid.");
return;
}
if (!fessConfig.isApiSearchScroll()) {
writeJsonResponse(99, StringUtil.EMPTY, "Scroll Search is not available.");
return;
}
final StringBuilder buf = new StringBuilder(1000);
request.setAttribute(Constants.SEARCH_LOG_ACCESS_TYPE, Constants.SEARCH_LOG_ACCESS_TYPE_JSON);
final JsonRequestParams params = new JsonRequestParams(request, fessConfig);
try {
response.setContentType("application/x-ndjson; charset=UTF-8");
final long count = searchHelper.scrollSearch(params, doc -> {
buf.setLength(0);
buf.append('{');
boolean first2 = true;
for (final Map.Entry<String, Object> entry : doc.entrySet()) {
final String name = entry.getKey();
if (StringUtil.isNotBlank(name) && entry.getValue() != null) {
if (!first2) {
buf.append(',');
} else {
first2 = false;
}
buf.append(escapeJson(name));
buf.append(':');
buf.append(escapeJson(entry.getValue()));
}
}
buf.append('}');
buf.append('\n');
try {
response.getWriter().print(buf.toString());
} catch (final IOException e) {
throw new IORuntimeException(e);
}
return true;
}, OptionalThing.empty());
response.flushBuffer();
if (logger.isDebugEnabled()) {
logger.debug("Loaded {} docs", count);
}
} catch (final Exception e) {
final int status = 9;
if (logger.isDebugEnabled()) {
logger.debug("Failed to process a ping request.", e);
}
writeJsonResponse(status, null, e);
}
}
protected void processPingRequest(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) {
final SearchEngineClient searchEngineClient = ComponentUtil.getSearchEngineClient();
int status;
Exception err = null;
try {
final PingResponse pingResponse = searchEngineClient.ping();
status = pingResponse.getStatus();
writeJsonResponse(status, "\"message\":" + pingResponse.getMessage());
} catch (final Exception e) {
status = 9;
err = e;
if (logger.isDebugEnabled()) {
logger.debug("Failed to process a ping request.", e);
}
writeJsonResponse(status, null, err);
}
}
protected void processSearchRequest(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) {
final SearchHelper searchHelper = ComponentUtil.getSearchHelper();
final FessConfig fessConfig = ComponentUtil.getFessConfig();
final RelatedQueryHelper relatedQueryHelper = ComponentUtil.getRelatedQueryHelper();
final RelatedContentHelper relatedContentHelper = ComponentUtil.getRelatedContentHelper();
int status = 0;
Exception err = null;
String query = null;
final StringBuilder buf = new StringBuilder(1000); // TODO replace response stream
request.setAttribute(Constants.SEARCH_LOG_ACCESS_TYPE, Constants.SEARCH_LOG_ACCESS_TYPE_JSON);
try {
final SearchRenderData data = new SearchRenderData();
final JsonRequestParams params = new JsonRequestParams(request, fessConfig);
query = params.getQuery();
searchHelper.search(params, data, OptionalThing.empty());
final String execTime = data.getExecTime();
final String queryTime = Long.toString(data.getQueryTime());
final String pageSize = Integer.toString(data.getPageSize());
final String currentPageNumber = Integer.toString(data.getCurrentPageNumber());
final String allRecordCount = Long.toString(data.getAllRecordCount());
final String allRecordCountRelation = data.getAllRecordCountRelation();
final String allPageCount = Integer.toString(data.getAllPageCount());
final List<Map<String, Object>> documentItems = data.getDocumentItems();
final FacetResponse facetResponse = data.getFacetResponse();
final String queryId = data.getQueryId();
final String highlightParams = data.getAppendHighlightParams();
final boolean nextPage = data.isExistNextPage();
final boolean prevPage = data.isExistPrevPage();
final long startRecordNumber = data.getCurrentStartRecordNumber();
final long endRecordNumber = data.getCurrentEndRecordNumber();
final List<String> pageNumbers = data.getPageNumberList();
final boolean partial = data.isPartialResults();
final String searchQuery = data.getSearchQuery();
final long requestedTime = data.getRequestedTime();
buf.append("\"q\":");
buf.append(escapeJson(query));
buf.append(",\"query_id\":");
buf.append(escapeJson(queryId));
buf.append(",\"exec_time\":");
buf.append(execTime);
buf.append(",\"query_time\":");
buf.append(queryTime);
buf.append(',');
buf.append("\"page_size\":");
buf.append(pageSize);
buf.append(',');
buf.append("\"page_number\":");
buf.append(currentPageNumber);
buf.append(',');
buf.append("\"record_count\":");
buf.append(allRecordCount);
buf.append(',');
buf.append("\"record_count_relation\":");
buf.append(escapeJson(allRecordCountRelation));
buf.append(',');
buf.append("\"page_count\":");
buf.append(allPageCount);
buf.append(",\"highlight_params\":");
buf.append(escapeJson(highlightParams));
buf.append(",\"next_page\":");
buf.append(escapeJson(nextPage));
buf.append(",\"prev_page\":");
buf.append(escapeJson(prevPage));
buf.append(",\"start_record_number\":");
buf.append(startRecordNumber);
buf.append(",\"end_record_number\":");
buf.append(escapeJson(endRecordNumber));
buf.append(",\"page_numbers\":");
buf.append(escapeJson(pageNumbers));
buf.append(",\"partial\":");
buf.append(escapeJson(partial));
buf.append(",\"search_query\":");
buf.append(escapeJson(searchQuery));
buf.append(",\"requested_time\":");
buf.append(requestedTime);
final String[] relatedQueries = relatedQueryHelper.getRelatedQueries(params.getQuery());
buf.append(",\"related_query\":");
buf.append(escapeJson(relatedQueries));
final String[] relatedContents = relatedContentHelper.getRelatedContents(params.getQuery());
buf.append(",\"related_contents\":");
buf.append(escapeJson(relatedContents));
buf.append(',');
buf.append("\"result\":[");
if (!documentItems.isEmpty()) {
boolean first1 = true;
for (final Map<String, Object> document : documentItems) {
if (!first1) {
buf.append(',');
} else {
first1 = false;
}
buf.append('{');
boolean first2 = true;
for (final Map.Entry<String, Object> entry : document.entrySet()) {
final String name = entry.getKey();
if (StringUtil.isNotBlank(name) && entry.getValue() != null
&& ComponentUtil.getQueryFieldConfig().isApiResponseField(name)) {
if (!first2) {
buf.append(',');
} else {
first2 = false;
}
buf.append(escapeJson(name));
buf.append(':');
buf.append(escapeJson(entry.getValue()));
}
}
buf.append('}');
}
}
buf.append(']');
if (facetResponse != null && facetResponse.hasFacetResponse()) {
// facet field
buf.append(',');
buf.append("\"facet_field\":[");
if (facetResponse.getFieldList() != null) {
boolean first1 = true;
for (final Field field : facetResponse.getFieldList()) {
if (!first1) {
buf.append(',');
} else {
first1 = false;
}
buf.append("{\"name\":");
buf.append(escapeJson(field.getName()));
buf.append(",\"result\":[");
boolean first2 = true;
for (final Map.Entry<String, Long> entry : field.getValueCountMap().entrySet()) {
if (!first2) {
buf.append(',');
} else {
first2 = false;
}
buf.append("{\"value\":");
buf.append(escapeJson(entry.getKey()));
buf.append(",\"count\":");
buf.append(entry.getValue());
buf.append('}');
}
buf.append(']');
buf.append('}');
}
}
buf.append(']');
// facet q
buf.append(',');
buf.append("\"facet_query\":[");
if (facetResponse.getQueryCountMap() != null) {
boolean first1 = true;
for (final Map.Entry<String, Long> entry : facetResponse.getQueryCountMap().entrySet()) {
if (!first1) {
buf.append(',');
} else {
first1 = false;
}
buf.append("{\"value\":");
buf.append(escapeJson(entry.getKey()));
buf.append(",\"count\":");
buf.append(entry.getValue());
buf.append('}');
}
}
buf.append(']');
}
} catch (final Exception e) {
status = 1;
err = e;
if (logger.isDebugEnabled()) {
logger.debug("Failed to process a search request.", e);
}
}
writeJsonResponse(status, buf.toString(), err);
}
protected String detailedMessage(final Throwable t) {
if (t == null) {
return "Unknown";
}
Throwable target = t;
if (target.getCause() == null) {
return target.getClass().getSimpleName() + "[" + target.getMessage() + "]";
}
final StringBuilder sb = new StringBuilder();
while (target != null) {
sb.append(target.getClass().getSimpleName());
if (target.getMessage() != null) {
sb.append("[");
sb.append(target.getMessage());
sb.append("]");
}
sb.append("; ");
target = target.getCause();
if (target != null) {
sb.append("nested: ");
}
}
return sb.toString();
}
protected void processLabelRequest(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) {
final LabelTypeHelper labelTypeHelper = ComponentUtil.getLabelTypeHelper();
int status = 0;
Exception err = null;
final StringBuilder buf = new StringBuilder(255); // TODO replace response stream
try {
final List<Map<String, String>> labelTypeItems = labelTypeHelper.getLabelTypeItemList(SearchRequestType.JSON,
request.getLocale() == null ? Locale.ROOT : request.getLocale());
buf.append("\"record_count\":");
buf.append(labelTypeItems.size());
if (!labelTypeItems.isEmpty()) {
buf.append(',');
buf.append("\"result\":[");
boolean first1 = true;
for (final Map<String, String> labelMap : labelTypeItems) {
if (!first1) {
buf.append(',');
} else {
first1 = false;
}
buf.append("{\"label\":");
buf.append(escapeJson(labelMap.get(Constants.ITEM_LABEL)));
buf.append(", \"value\":");
buf.append(escapeJson(labelMap.get(Constants.ITEM_VALUE)));
buf.append('}');
}
buf.append(']');
}
} catch (final Exception e) {
status = 1;
err = e;
if (logger.isDebugEnabled()) {
logger.debug("Failed to process a label request.", e);
}
}
writeJsonResponse(status, buf.toString(), err);
}
protected void processPopularWordRequest(final HttpServletRequest request, final HttpServletResponse response,
final FilterChain chain) {
if (!ComponentUtil.getFessConfig().isWebApiPopularWord()) {
writeJsonResponse(9, null, "Unsupported operation.");
return;
}
final String seed = request.getParameter("seed");
final List<String> tagList = new ArrayList<>();
final String[] tags = request.getParameterValues("labels");
if (tags != null) {
tagList.addAll(Arrays.asList(tags));
}
final String key = ComponentUtil.getVirtualHostHelper().getVirtualHostKey();
if (StringUtil.isNotBlank(key)) {
tagList.add(key);
}
final String[] fields = request.getParameterValues("fields");
final String[] excludes = StringUtil.EMPTY_STRINGS;// TODO
final PopularWordHelper popularWordHelper = ComponentUtil.getPopularWordHelper();
int status = 0;
Exception err = null;
final StringBuilder buf = new StringBuilder(255); // TODO replace response stream
try {
final List<String> popularWordList = popularWordHelper.getWordList(SearchRequestType.JSON, seed,
tagList.toArray(new String[tagList.size()]), null, fields, excludes);
buf.append("\"result\":[");
boolean first1 = true;
for (final String word : popularWordList) {
if (!first1) {
buf.append(',');
} else {
first1 = false;
}
buf.append(escapeJson(word));
}
buf.append(']');
} catch (final Exception e) {
if (e instanceof WebApiException) {
status = ((WebApiException) e).getStatusCode();
} else {
status = 1;
}
err = e;
if (logger.isDebugEnabled()) {
logger.debug("Failed to process a popularWord request.", e);
}
}
writeJsonResponse(status, buf.toString(), err);
}
protected void processFavoriteRequest(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) {
if (!ComponentUtil.getFessConfig().isUserFavorite()) {
writeJsonResponse(9, null, "Unsupported operation.");
return;
}
final FessConfig fessConfig = ComponentUtil.getFessConfig();
final UserInfoHelper userInfoHelper = ComponentUtil.getUserInfoHelper();
final SearchHelper searchHelper = ComponentUtil.getSearchHelper();
final FavoriteLogService favoriteLogService = ComponentUtil.getComponent(FavoriteLogService.class);
final SystemHelper systemHelper = ComponentUtil.getSystemHelper();
try {
final String docId = request.getParameter("docId");
final String queryId = request.getParameter("queryId");
final String[] docIds = userInfoHelper.getResultDocIds(URLDecoder.decode(queryId, Constants.UTF_8));
if (docIds == null) {
throw new WebApiException(6, "No searched urls.");
}
searchHelper.getDocumentByDocId(docId, new String[] { fessConfig.getIndexFieldUrl(), fessConfig.getIndexFieldLang() },
OptionalThing.empty()).ifPresent(doc -> {
final String favoriteUrl = DocumentUtil.getValue(doc, fessConfig.getIndexFieldUrl(), String.class);
final String userCode = userInfoHelper.getUserCode();
if (StringUtil.isBlank(userCode)) {
throw new WebApiException(2, "No user session.");
}
if (StringUtil.isBlank(favoriteUrl)) {
throw new WebApiException(2, "URL is null.");
}
boolean found = false;
for (final String id : docIds) {
if (docId.equals(id)) {
found = true;
break;
}
}
if (!found) {
throw new WebApiException(5, "Not found: " + favoriteUrl);
}
if (!favoriteLogService.addUrl(userCode, (userInfo, favoriteLog) -> {
favoriteLog.setUserInfoId(userInfo.getId());
favoriteLog.setUrl(favoriteUrl);
favoriteLog.setDocId(docId);
favoriteLog.setQueryId(queryId);
favoriteLog.setCreatedAt(systemHelper.getCurrentTimeAsLocalDateTime());
})) {
throw new WebApiException(4, "Failed to add url: " + favoriteUrl);
}
final String id = DocumentUtil.getValue(doc, fessConfig.getIndexFieldId(), String.class);
searchHelper.update(id, builder -> {
final Script script = ComponentUtil.getLanguageHelper().createScript(doc,
"ctx._source." + fessConfig.getIndexFieldFavoriteCount() + "+=1");
builder.setScript(script);
final Map<String, Object> upsertMap = new HashMap<>();
upsertMap.put(fessConfig.getIndexFieldFavoriteCount(), 1);
builder.setUpsert(upsertMap);
builder.setRefreshPolicy(Constants.TRUE);
});
writeJsonResponse(0, "\"result\":\"ok\"", (String) null);
}).orElse(() -> {
throw new WebApiException(6, "Not found: " + docId);
});
} catch (final Exception e) {
int status;
if (e instanceof WebApiException) {
status = ((WebApiException) e).getStatusCode();
} else {
status = 1;
}
writeJsonResponse(status, null, e);
if (logger.isDebugEnabled()) {
logger.debug("Failed to process a favorite request.", e);
}
}
}
protected void processFavoritesRequest(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) {
if (!ComponentUtil.getFessConfig().isUserFavorite()) {
writeJsonResponse(9, null, "Unsupported operation.");
return;
}
final UserInfoHelper userInfoHelper = ComponentUtil.getUserInfoHelper();
final FessConfig fessConfig = ComponentUtil.getFessConfig();
final SearchHelper searchHelper = ComponentUtil.getSearchHelper();
final FavoriteLogService favoriteLogService = ComponentUtil.getComponent(FavoriteLogService.class);
int status = 0;
String body = null;
Exception err = null;
try {
final String queryId = request.getParameter("queryId");
final String userCode = userInfoHelper.getUserCode();
if (StringUtil.isBlank(userCode)) {
throw new WebApiException(2, "No user session.");
}
if (StringUtil.isBlank(queryId)) {
throw new WebApiException(3, "Query ID is null.");
}
final String[] docIds = userInfoHelper.getResultDocIds(queryId);
final List<Map<String, Object>> docList = searchHelper.getDocumentListByDocIds(docIds, new String[] {
fessConfig.getIndexFieldUrl(), fessConfig.getIndexFieldDocId(), fessConfig.getIndexFieldFavoriteCount() },
OptionalThing.empty(), SearchRequestType.JSON);
List<String> urlList = new ArrayList<>(docList.size());
for (final Map<String, Object> doc : docList) {
final String urlObj = DocumentUtil.getValue(doc, fessConfig.getIndexFieldUrl(), String.class);
if (urlObj != null) {
urlList.add(urlObj);
}
}
urlList = favoriteLogService.getUrlList(userCode, urlList);
final List<String> docIdList = new ArrayList<>(urlList.size());
for (final Map<String, Object> doc : docList) {
final String urlObj = DocumentUtil.getValue(doc, fessConfig.getIndexFieldUrl(), String.class);
if (urlObj != null && urlList.contains(urlObj)) {
final String docIdObj = DocumentUtil.getValue(doc, fessConfig.getIndexFieldDocId(), String.class);
if (docIdObj != null) {
docIdList.add(docIdObj);
}
}
}
final StringBuilder buf = new StringBuilder(255); // TODO replace response stream
buf.append("\"num\":").append(docIdList.size());
buf.append(", \"doc_ids\":[");
if (!docIdList.isEmpty()) {
for (int i = 0; i < docIdList.size(); i++) {
if (i > 0) {
buf.append(',');
}
buf.append(escapeJson(docIdList.get(i)));
}
}
buf.append(']');
body = buf.toString();
} catch (final Exception e) {
if (e instanceof WebApiException) {
status = ((WebApiException) e).getStatusCode();
} else {
status = 1;
}
err = e;
if (logger.isDebugEnabled()) {
logger.debug("Failed to process a favorites request.", e);
}
}
writeJsonResponse(status, body, err);
}
protected static class JsonRequestParams extends SearchRequestParams {
private final HttpServletRequest request;
private final FessConfig fessConfig;
private int startPosition = -1;
private int pageSize = -1;
protected JsonRequestParams(final HttpServletRequest request, final FessConfig fessConfig) {
this.request = request;
this.fessConfig = fessConfig;
}
@Override
public String getTrackTotalHits() {
return request.getParameter(Constants.TRACK_TOTAL_HITS);
}
@Override
public String getQuery() {
return request.getParameter("q");
}
@Override
public String[] getExtraQueries() {
return getParamValueArray(request, "ex_q");
}
@Override
public Map<String, String[]> getFields() {
final Map<String, String[]> fields = new HashMap<>();
for (final Map.Entry<String, String[]> entry : request.getParameterMap().entrySet()) {
final String key = entry.getKey();
if (key.startsWith("fields.")) {
final String[] value = simplifyArray(entry.getValue());
fields.put(key.substring("fields.".length()), value);
}
}
return fields;
}
@Override
public Map<String, String[]> getConditions() {
final Map<String, String[]> conditions = new HashMap<>();
for (final Map.Entry<String, String[]> entry : request.getParameterMap().entrySet()) {
final String key = entry.getKey();
if (key.startsWith("as.")) {
final String[] value = simplifyArray(entry.getValue());
conditions.put(key.substring("as.".length()), value);
}
}
return conditions;
}
@Override
public String[] getLanguages() {
return getParamValueArray(request, "lang");
}
@Override
public GeoInfo getGeoInfo() {
return createGeoInfo(request);
}
@Override
public FacetInfo getFacetInfo() {
return createFacetInfo(request);
}
@Override
public String getSort() {
return request.getParameter("sort");
}
@Override
public int getStartPosition() {
if (startPosition != -1) {
return startPosition;
}
final String start = request.getParameter("start");
if (StringUtil.isBlank(start)) {
startPosition = fessConfig.getPagingSearchPageStartAsInteger();
} else {
try {
startPosition = Integer.parseInt(start);
} catch (final NumberFormatException e) {
startPosition = fessConfig.getPagingSearchPageStartAsInteger();
}
}
return startPosition;
}
@Override
public int getPageSize() {
if (pageSize != -1) {
return pageSize;
}
final String num = request.getParameter("num");
if (StringUtil.isBlank(num)) {
pageSize = fessConfig.getPagingSearchPageSizeAsInteger();
} else {
try {
pageSize = Integer.parseInt(num);
if (pageSize > fessConfig.getPagingSearchPageMaxSizeAsInteger().intValue() || pageSize <= 0) {
pageSize = fessConfig.getPagingSearchPageMaxSizeAsInteger();
}
} catch (final NumberFormatException e) {
pageSize = fessConfig.getPagingSearchPageSizeAsInteger();
}
}
return pageSize;
}
@Override
public Object getAttribute(final String name) {
return request.getAttribute(name);
}
@Override
public Locale getLocale() {
return Locale.ROOT;
}
@Override
public SearchRequestType getType() {
return SearchRequestType.JSON;
}
@Override
public String getSimilarDocHash() {
return request.getParameter("sdh");
}
@Override
public HighlightInfo getHighlightInfo() {
return ComponentUtil.getViewHelper().createHighlightInfo();
}
}
@Override
protected void writeHeaders(final HttpServletResponse response) {
ComponentUtil.getFessConfig().getApiJsonResponseHeaderList().forEach(e -> response.setHeader(e.getFirst(), e.getSecond()));
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,307 @@
/*
* Copyright 2012-2022 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.api.suggest;
import static org.codelibs.core.stream.StreamUtil.stream;
import java.io.IOException;
import java.util.Collections;
import java.util.Locale;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.api.BaseJsonApiManager;
import org.codelibs.fess.entity.FacetInfo;
import org.codelibs.fess.entity.GeoInfo;
import org.codelibs.fess.entity.HighlightInfo;
import org.codelibs.fess.entity.SearchRequestParams;
import org.codelibs.fess.entity.SearchRequestParams.SearchRequestType;
import org.codelibs.fess.exception.InvalidAccessTokenException;
import org.codelibs.fess.helper.RoleQueryHelper;
import org.codelibs.fess.helper.SearchHelper;
import org.codelibs.fess.helper.SuggestHelper;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.suggest.entity.SuggestItem;
import org.codelibs.fess.suggest.request.suggest.SuggestRequestBuilder;
import org.codelibs.fess.suggest.request.suggest.SuggestResponse;
import org.codelibs.fess.util.ComponentUtil;
public class SuggestApiManager extends BaseJsonApiManager {
private static final Logger logger = LogManager.getLogger(SuggestApiManager.class);
public SuggestApiManager() {
setPathPrefix("/suggest");
}
@PostConstruct
public void register() {
if (logger.isInfoEnabled()) {
logger.info("Load {}", this.getClass().getSimpleName());
}
ComponentUtil.getWebApiManagerFactory().add(this);
}
@Override
public boolean matches(final HttpServletRequest request) {
final String servletPath = request.getServletPath();
return servletPath.startsWith(pathPrefix);
}
@Override
public void process(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain)
throws IOException, ServletException {
final FessConfig fessConfig = ComponentUtil.getFessConfig();
if (!fessConfig.isAcceptedSearchReferer(request.getHeader("referer"))) {
writeJsonResponse(99, StringUtil.EMPTY, "Referer is invalid.");
return;
}
int status = 0;
String errMsg = StringUtil.EMPTY;
final StringBuilder buf = new StringBuilder(255); // TODO replace response stream
final RoleQueryHelper roleQueryHelper = ComponentUtil.getRoleQueryHelper();
final SearchHelper searchHelper = ComponentUtil.getSearchHelper();
try {
final RequestParameter parameter = RequestParameter.parse(request);
final String[] langs = searchHelper.getLanguages(request, parameter);
final SuggestHelper suggestHelper = ComponentUtil.getSuggestHelper();
final SuggestRequestBuilder builder = suggestHelper.suggester().suggest();
builder.setQuery(parameter.getQuery());
stream(parameter.getSuggestFields()).of(stream -> stream.forEach(builder::addField));
roleQueryHelper.build(SearchRequestType.SUGGEST).stream().forEach(builder::addRole);
builder.setSize(parameter.getNum());
stream(langs).of(stream -> stream.forEach(builder::addLang));
stream(parameter.getTags()).of(stream -> stream.forEach(builder::addTag));
final String key = ComponentUtil.getVirtualHostHelper().getVirtualHostKey();
if (StringUtil.isNotBlank(key)) {
builder.addTag(key);
}
builder.addKind(SuggestItem.Kind.USER.toString());
if (ComponentUtil.getFessConfig().isSuggestSearchLog()) {
builder.addKind(SuggestItem.Kind.QUERY.toString());
}
if (ComponentUtil.getFessConfig().isSuggestDocuments()) {
builder.addKind(SuggestItem.Kind.DOCUMENT.toString());
}
final SuggestResponse suggestResponse = builder.execute().getResponse();
buf.append("\"result\":{");
buf.append("\"took\":\"").append(suggestResponse.getTookMs()).append('\"');
buf.append(",\"total\":\"").append(suggestResponse.getTotal()).append('\"');
buf.append(",\"num\":\"").append(suggestResponse.getNum()).append('\"');
if (!suggestResponse.getItems().isEmpty()) {
buf.append(",\"hits\":[");
boolean first = true;
for (final SuggestItem item : suggestResponse.getItems()) {
if (!first) {
buf.append(',');
}
first = false;
buf.append("{\"text\":\"").append(StringEscapeUtils.escapeJson(item.getText())).append('\"');
buf.append(",\"tags\":[");
for (int i = 0; i < item.getTags().length; i++) {
if (i > 0) {
buf.append(',');
}
buf.append('\"').append(StringEscapeUtils.escapeJson(item.getTags()[i])).append('\"');
}
buf.append(']');
buf.append('}');
}
buf.append(']');
}
buf.append('}');
} catch (final Exception e) {
status = 1;
errMsg = e.getMessage();
if (errMsg == null) {
errMsg = e.getClass().getName();
}
if (logger.isDebugEnabled()) {
logger.debug("Failed to process a suggest request.", e);
}
if (e instanceof final InvalidAccessTokenException iate) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setHeader("WWW-Authenticate", "Bearer error=\"" + iate.getType() + "\"");
}
}
writeJsonResponse(status, buf.toString(), errMsg);
}
protected static class RequestParameter extends SearchRequestParams {
private final String query;
private final String[] fields;
private final int num;
private final HttpServletRequest request;
private final String[] tags;
protected RequestParameter(final HttpServletRequest request, final String query, final String[] tags, final String[] fields,
final int num) {
this.query = query;
this.tags = tags;
this.fields = fields;
this.num = num;
this.request = request;
}
protected static RequestParameter parse(final HttpServletRequest request) {
final String query = request.getParameter("query");
final String fieldsStr = request.getParameter("fields");
final String[] fields;
if (StringUtil.isNotBlank(fieldsStr)) {
fields = fieldsStr.split(",");
} else {
fields = new String[0];
}
final String numStr = request.getParameter("num");
final int num;
if (StringUtil.isNotBlank(numStr) && StringUtils.isNumeric(numStr)) {
num = Integer.parseInt(numStr);
} else {
num = 10;
}
final String tagsStr = request.getParameter("tags");
final String[] tags;
if (StringUtil.isNotBlank(tagsStr)) {
tags = tagsStr.split(",");
} else {
tags = new String[0];
}
return new RequestParameter(request, query, tags, fields, num);
}
@Override
public String getQuery() {
return query;
}
protected String[] getSuggestFields() {
return fields;
}
protected int getNum() {
return num;
}
@Override
public Map<String, String[]> getFields() {
return Collections.emptyMap();
}
@Override
public Map<String, String[]> getConditions() {
return Collections.emptyMap();
}
public String[] getTags() {
return tags;
}
@Override
public String[] getLanguages() {
return getParamValueArray(request, "lang");
}
@Override
public GeoInfo getGeoInfo() {
throw new UnsupportedOperationException();
}
@Override
public FacetInfo getFacetInfo() {
throw new UnsupportedOperationException();
}
@Override
public String getSort() {
throw new UnsupportedOperationException();
}
@Override
public int getStartPosition() {
throw new UnsupportedOperationException();
}
@Override
public int getPageSize() {
throw new UnsupportedOperationException();
}
@Override
public String[] getExtraQueries() {
throw new UnsupportedOperationException();
}
@Override
public Object getAttribute(final String name) {
throw new UnsupportedOperationException();
}
@Override
public Locale getLocale() {
throw new UnsupportedOperationException();
}
@Override
public SearchRequestType getType() {
return SearchRequestType.SUGGEST;
}
@Override
public String getSimilarDocHash() {
throw new UnsupportedOperationException();
}
@Override
public HighlightInfo getHighlightInfo() {
return new HighlightInfo();
}
}
@Override
protected void writeHeaders(final HttpServletResponse response) {
ComponentUtil.getFessConfig().getApiJsonResponseHeaderList().forEach(e -> response.setHeader(e.getFirst(), e.getSecond()));
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -15,6 +15,8 @@
*/
package org.codelibs.fess.app.job;
import javax.annotation.Resource;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.codelibs.core.lang.StringUtil;
@ -22,10 +24,10 @@ import org.codelibs.core.timer.TimeoutManager;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.logic.AccessContextLogic;
import org.codelibs.fess.app.service.ScheduledJobService;
import org.codelibs.fess.es.config.exbhv.JobLogBhv;
import org.codelibs.fess.helper.JobHelper;
import org.codelibs.fess.helper.SystemHelper;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.opensearch.config.exbhv.JobLogBhv;
import org.codelibs.fess.util.ComponentUtil;
import org.dbflute.optional.OptionalThing;
import org.lastaflute.core.time.TimeManager;
@ -34,8 +36,6 @@ import org.lastaflute.job.LaJob;
import org.lastaflute.job.LaJobRunner;
import org.lastaflute.job.LaJobScheduler;
import jakarta.annotation.Resource;
public class AllJobScheduler implements LaJobScheduler {
private static final Logger logger = LogManager.getLogger(AllJobScheduler.class);
@ -66,7 +66,7 @@ public class AllJobScheduler implements LaJobScheduler {
@Override
public void schedule(final LaCron cron) {
schedulerTime = systemHelper.getCurrentTimeAsLong();
schedulerTime = System.currentTimeMillis();
scheduledJobService.start(cron);
final String myName = fessConfig.getSchedulerTargetName();
@ -81,7 +81,7 @@ public class AllJobScheduler implements LaJobScheduler {
if (logger.isDebugEnabled()) {
logger.debug("Updating scheduled jobs. time:{}", schedulerTime);
}
final long now = systemHelper.getCurrentTimeAsLong();
final long now = System.currentTimeMillis();
scheduledJobService.getScheduledJobListAfter(schedulerTime).forEach(scheduledJob -> {
if (logger.isDebugEnabled()) {
logger.debug("Updating job schedule:{}", scheduledJob.getName());

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -19,12 +19,12 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.codelibs.core.timer.TimeoutTask;
import org.codelibs.fess.Constants;
import org.codelibs.fess.es.config.exentity.JobLog;
import org.codelibs.fess.es.config.exentity.ScheduledJob;
import org.codelibs.fess.exception.ScheduledJobException;
import org.codelibs.fess.helper.JobHelper;
import org.codelibs.fess.helper.SystemHelper;
import org.codelibs.fess.job.JobExecutor;
import org.codelibs.fess.opensearch.config.exentity.JobLog;
import org.codelibs.fess.opensearch.config.exentity.ScheduledJob;
import org.codelibs.fess.util.ComponentUtil;
import org.lastaflute.job.JobManager;
import org.lastaflute.job.LaJob;

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -15,14 +15,14 @@
*/
package org.codelibs.fess.app.logic;
import javax.annotation.Resource;
import org.codelibs.fess.mylasta.action.FessUserBean;
import org.dbflute.hook.AccessContext;
import org.dbflute.optional.OptionalThing;
import org.lastaflute.core.time.TimeManager;
import org.lastaflute.db.dbflute.accesscontext.AccessContextResource;
import jakarta.annotation.Resource;
public class AccessContextLogic {
// ===================================================================================

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -21,23 +21,23 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.AccessTokenPager;
import org.codelibs.fess.es.config.cbean.AccessTokenCB;
import org.codelibs.fess.es.config.exbhv.AccessTokenBhv;
import org.codelibs.fess.es.config.exentity.AccessToken;
import org.codelibs.fess.exception.InvalidAccessTokenException;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.opensearch.config.cbean.AccessTokenCB;
import org.codelibs.fess.opensearch.config.exbhv.AccessTokenBhv;
import org.codelibs.fess.opensearch.config.exentity.AccessToken;
import org.codelibs.fess.taglib.FessFunctions;
import org.codelibs.fess.util.ComponentUtil;
import org.dbflute.cbean.result.PagingResultBean;
import org.dbflute.optional.OptionalEntity;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
public class AccessTokenService {
@Resource

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -21,17 +21,19 @@ import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.BadWordPager;
import org.codelibs.fess.es.client.SearchEngineClient;
import org.codelibs.fess.es.config.cbean.BadWordCB;
import org.codelibs.fess.es.config.exbhv.BadWordBhv;
import org.codelibs.fess.es.config.exentity.BadWord;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.opensearch.client.SearchEngineClient;
import org.codelibs.fess.opensearch.config.cbean.BadWordCB;
import org.codelibs.fess.opensearch.config.exbhv.BadWordBhv;
import org.codelibs.fess.opensearch.config.exentity.BadWord;
import org.codelibs.fess.util.ComponentUtil;
import org.dbflute.bhv.readable.EntityRowHandler;
import org.dbflute.cbean.result.PagingResultBean;
@ -41,8 +43,6 @@ import com.orangesignal.csv.CsvConfig;
import com.orangesignal.csv.CsvReader;
import com.orangesignal.csv.CsvWriter;
import jakarta.annotation.Resource;
public class BadWordService {
private static final String DELETE_PREFIX = "--";

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -17,19 +17,19 @@ package org.codelibs.fess.app.service;
import java.util.List;
import javax.annotation.Resource;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.BoostDocPager;
import org.codelibs.fess.es.config.cbean.BoostDocumentRuleCB;
import org.codelibs.fess.es.config.exbhv.BoostDocumentRuleBhv;
import org.codelibs.fess.es.config.exentity.BoostDocumentRule;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.opensearch.config.cbean.BoostDocumentRuleCB;
import org.codelibs.fess.opensearch.config.exbhv.BoostDocumentRuleBhv;
import org.codelibs.fess.opensearch.config.exentity.BoostDocumentRule;
import org.dbflute.cbean.result.PagingResultBean;
import org.dbflute.optional.OptionalEntity;
import jakarta.annotation.Resource;
public class BoostDocumentRuleService extends FessAppService {
@Resource

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -18,6 +18,8 @@ package org.codelibs.fess.app.service;
import java.util.Collections;
import java.util.List;
import javax.annotation.Resource;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.CharMappingPager;
@ -28,8 +30,6 @@ import org.codelibs.fess.dict.mapping.CharMappingItem;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.dbflute.optional.OptionalEntity;
import jakarta.annotation.Resource;
public class CharMappingService {
@Resource
protected DictionaryManager dictionaryManager;
@ -53,7 +53,7 @@ public class CharMappingService {
}
public OptionalEntity<CharMappingFile> getCharMappingFile(final String dictId) {
return dictionaryManager.getDictionaryFile(dictId).filter(CharMappingFile.class::isInstance)
return dictionaryManager.getDictionaryFile(dictId).filter(file -> file instanceof CharMappingFile)
.map(file -> OptionalEntity.of((CharMappingFile) file)).orElse(OptionalEntity.empty());
}

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -28,6 +28,8 @@ import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.codelibs.core.CoreLibConstants;
@ -35,13 +37,13 @@ import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.CrawlingInfoPager;
import org.codelibs.fess.es.config.cbean.CrawlingInfoCB;
import org.codelibs.fess.es.config.exbhv.CrawlingInfoBhv;
import org.codelibs.fess.es.config.exbhv.CrawlingInfoParamBhv;
import org.codelibs.fess.es.config.exentity.CrawlingInfo;
import org.codelibs.fess.es.config.exentity.CrawlingInfoParam;
import org.codelibs.fess.exception.FessSystemException;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.opensearch.config.cbean.CrawlingInfoCB;
import org.codelibs.fess.opensearch.config.exbhv.CrawlingInfoBhv;
import org.codelibs.fess.opensearch.config.exbhv.CrawlingInfoParamBhv;
import org.codelibs.fess.opensearch.config.exentity.CrawlingInfo;
import org.codelibs.fess.opensearch.config.exentity.CrawlingInfoParam;
import org.codelibs.fess.util.ComponentUtil;
import org.dbflute.bhv.readable.EntityRowHandler;
import org.dbflute.cbean.result.ListResultBean;
@ -52,8 +54,6 @@ import com.orangesignal.csv.CsvConfig;
import com.orangesignal.csv.CsvReader;
import com.orangesignal.csv.CsvWriter;
import jakarta.annotation.Resource;
public class CrawlingInfoService {
private static final Logger logger = LogManager.getLogger(CrawlingInfoService.class);

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -17,21 +17,21 @@ package org.codelibs.fess.app.service;
import java.util.List;
import javax.annotation.Resource;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.DataConfigPager;
import org.codelibs.fess.es.config.cbean.DataConfigCB;
import org.codelibs.fess.es.config.exbhv.DataConfigBhv;
import org.codelibs.fess.es.config.exentity.DataConfig;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.opensearch.config.cbean.DataConfigCB;
import org.codelibs.fess.opensearch.config.exbhv.DataConfigBhv;
import org.codelibs.fess.opensearch.config.exentity.DataConfig;
import org.codelibs.fess.util.ParameterUtil;
import org.dbflute.cbean.result.ListResultBean;
import org.dbflute.cbean.result.PagingResultBean;
import org.dbflute.optional.OptionalEntity;
import jakarta.annotation.Resource;
public class DataConfigService extends FessAppService {
@Resource

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -17,19 +17,19 @@ package org.codelibs.fess.app.service;
import java.util.List;
import javax.annotation.Resource;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.DuplicateHostPager;
import org.codelibs.fess.es.config.cbean.DuplicateHostCB;
import org.codelibs.fess.es.config.exbhv.DuplicateHostBhv;
import org.codelibs.fess.es.config.exentity.DuplicateHost;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.opensearch.config.cbean.DuplicateHostCB;
import org.codelibs.fess.opensearch.config.exbhv.DuplicateHostBhv;
import org.codelibs.fess.opensearch.config.exentity.DuplicateHost;
import org.dbflute.cbean.result.PagingResultBean;
import org.dbflute.optional.OptionalEntity;
import jakarta.annotation.Resource;
public class DuplicateHostService extends FessAppService {
@Resource

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -25,22 +25,24 @@ import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.ElevateWordPager;
import org.codelibs.fess.es.client.SearchEngineClient;
import org.codelibs.fess.es.config.cbean.ElevateWordCB;
import org.codelibs.fess.es.config.exbhv.ElevateWordBhv;
import org.codelibs.fess.es.config.exbhv.ElevateWordToLabelBhv;
import org.codelibs.fess.es.config.exbhv.LabelTypeBhv;
import org.codelibs.fess.es.config.exentity.ElevateWord;
import org.codelibs.fess.es.config.exentity.ElevateWordToLabel;
import org.codelibs.fess.es.config.exentity.LabelType;
import org.codelibs.fess.helper.PermissionHelper;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.opensearch.client.SearchEngineClient;
import org.codelibs.fess.opensearch.config.cbean.ElevateWordCB;
import org.codelibs.fess.opensearch.config.exbhv.ElevateWordBhv;
import org.codelibs.fess.opensearch.config.exbhv.ElevateWordToLabelBhv;
import org.codelibs.fess.opensearch.config.exbhv.LabelTypeBhv;
import org.codelibs.fess.opensearch.config.exentity.ElevateWord;
import org.codelibs.fess.opensearch.config.exentity.ElevateWordToLabel;
import org.codelibs.fess.opensearch.config.exentity.LabelType;
import org.codelibs.fess.util.ComponentUtil;
import org.dbflute.bhv.readable.EntityRowHandler;
import org.dbflute.cbean.result.PagingResultBean;
@ -50,8 +52,6 @@ import com.orangesignal.csv.CsvConfig;
import com.orangesignal.csv.CsvReader;
import com.orangesignal.csv.CsvWriter;
import jakarta.annotation.Resource;
public class ElevateWordService {
private static final Logger logger = LogManager.getLogger(ElevateWordService.class);

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -15,34 +15,30 @@
*/
package org.codelibs.fess.app.service;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.annotation.Resource;
import org.apache.commons.io.output.StringBuilderWriter;
import org.apache.commons.lang3.StringUtils;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.FailureUrlPager;
import org.codelibs.fess.es.config.cbean.FailureUrlCB;
import org.codelibs.fess.es.config.exbhv.FailureUrlBhv;
import org.codelibs.fess.es.config.exentity.CrawlingConfig;
import org.codelibs.fess.es.config.exentity.FailureUrl;
import org.codelibs.fess.exception.ContainerNotAvailableException;
import org.codelibs.fess.helper.SystemHelper;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.opensearch.config.cbean.FailureUrlCB;
import org.codelibs.fess.opensearch.config.exbhv.FailureUrlBhv;
import org.codelibs.fess.opensearch.config.exentity.CrawlingConfig;
import org.codelibs.fess.opensearch.config.exentity.FailureUrl;
import org.codelibs.fess.util.ComponentUtil;
import org.dbflute.cbean.result.PagingResultBean;
import org.dbflute.optional.OptionalEntity;
import jakarta.annotation.Resource;
public class FailureUrlService {
private static final Logger logger = LogManager.getLogger(FailureUrlService.class);
@Resource
protected FailureUrlBhv failureUrlBhv;
@ -128,9 +124,9 @@ public class FailureUrlService {
});
}
public FailureUrl store(final CrawlingConfig crawlingConfig, final String errorName, final String url, final Throwable e) {
public void store(final CrawlingConfig crawlingConfig, final String errorName, final String url, final Throwable e) {
if (e instanceof ContainerNotAvailableException) {
return null;
return;
}
final FailureUrlBhv bhv = ComponentUtil.getComponent(FailureUrlBhv.class);
@ -153,25 +149,20 @@ public class FailureUrlService {
});
failureUrl.setErrorName(errorName);
failureUrl.setErrorLog(getStackTrace(e));
failureUrl.setErrorLog(StringUtils.abbreviate(getStackTrace(e), 4000));
failureUrl.setLastAccessTime(ComponentUtil.getSystemHelper().getCurrentTimeAsLong());
failureUrl.setThreadName(Thread.currentThread().getName());
bhv.insertOrUpdate(failureUrl, op -> {
op.setRefreshPolicy(Constants.TRUE);
});
return failureUrl;
}
private String getStackTrace(final Throwable t) {
final SystemHelper systemHelper = ComponentUtil.getSystemHelper();
try (final StringWriter sw = new StringWriter(); final PrintWriter pw = new PrintWriter(sw)) {
t.printStackTrace(pw);
pw.flush();
return systemHelper.abbreviateLongText(sw.toString());
} catch (final IOException e) {
logger.warn("Failed to print the stack trace {}", t.getMessage(), e);
}
return StringUtil.EMPTY;
final StringBuilderWriter sw = new StringBuilderWriter();
final PrintWriter pw = new PrintWriter(sw, true);
t.printStackTrace(pw);
return systemHelper.abbreviateLongText(sw.toString());
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -20,17 +20,17 @@ import java.util.Collections;
import java.util.List;
import java.util.function.BiConsumer;
import javax.annotation.Resource;
import org.codelibs.fess.es.log.exbhv.FavoriteLogBhv;
import org.codelibs.fess.es.log.exbhv.UserInfoBhv;
import org.codelibs.fess.es.log.exentity.FavoriteLog;
import org.codelibs.fess.es.log.exentity.UserInfo;
import org.codelibs.fess.helper.SystemHelper;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.opensearch.log.exbhv.FavoriteLogBhv;
import org.codelibs.fess.opensearch.log.exbhv.UserInfoBhv;
import org.codelibs.fess.opensearch.log.exentity.FavoriteLog;
import org.codelibs.fess.opensearch.log.exentity.UserInfo;
import org.codelibs.fess.util.ComponentUtil;
import org.dbflute.cbean.result.ListResultBean;
import jakarta.annotation.Resource;
public class FavoriteLogService {
@Resource
protected SystemHelper systemHelper;

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -17,19 +17,19 @@ package org.codelibs.fess.app.service;
import java.util.List;
import javax.annotation.Resource;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.FileAuthPager;
import org.codelibs.fess.es.config.cbean.FileAuthenticationCB;
import org.codelibs.fess.es.config.exbhv.FileAuthenticationBhv;
import org.codelibs.fess.es.config.exentity.FileAuthentication;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.opensearch.config.cbean.FileAuthenticationCB;
import org.codelibs.fess.opensearch.config.exbhv.FileAuthenticationBhv;
import org.codelibs.fess.opensearch.config.exentity.FileAuthentication;
import org.codelibs.fess.util.ParameterUtil;
import org.dbflute.cbean.result.PagingResultBean;
import org.dbflute.optional.OptionalEntity;
import jakarta.annotation.Resource;
public class FileAuthenticationService {
@Resource

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -17,22 +17,22 @@ package org.codelibs.fess.app.service;
import java.util.List;
import javax.annotation.Resource;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.FileConfigPager;
import org.codelibs.fess.es.config.cbean.FileConfigCB;
import org.codelibs.fess.es.config.exbhv.FileAuthenticationBhv;
import org.codelibs.fess.es.config.exbhv.FileConfigBhv;
import org.codelibs.fess.es.config.exentity.FileConfig;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.opensearch.config.cbean.FileConfigCB;
import org.codelibs.fess.opensearch.config.exbhv.FileAuthenticationBhv;
import org.codelibs.fess.opensearch.config.exbhv.FileConfigBhv;
import org.codelibs.fess.opensearch.config.exentity.FileConfig;
import org.codelibs.fess.util.ParameterUtil;
import org.dbflute.cbean.result.ListResultBean;
import org.dbflute.cbean.result.PagingResultBean;
import org.dbflute.optional.OptionalEntity;
import jakarta.annotation.Resource;
public class FileConfigService extends FessAppService {
@Resource

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -19,20 +19,20 @@ import static org.codelibs.core.stream.StreamUtil.stream;
import java.util.List;
import javax.annotation.Resource;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.GroupPager;
import org.codelibs.fess.es.user.cbean.GroupCB;
import org.codelibs.fess.es.user.exbhv.GroupBhv;
import org.codelibs.fess.es.user.exbhv.UserBhv;
import org.codelibs.fess.es.user.exentity.Group;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.opensearch.user.cbean.GroupCB;
import org.codelibs.fess.opensearch.user.exbhv.GroupBhv;
import org.codelibs.fess.opensearch.user.exbhv.UserBhv;
import org.codelibs.fess.opensearch.user.exentity.Group;
import org.codelibs.fess.util.ComponentUtil;
import org.dbflute.cbean.result.PagingResultBean;
import org.dbflute.optional.OptionalEntity;
import jakarta.annotation.Resource;
public class GroupService {
@Resource

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -17,19 +17,19 @@ package org.codelibs.fess.app.service;
import java.util.List;
import javax.annotation.Resource;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.JobLogPager;
import org.codelibs.fess.es.config.cbean.JobLogCB;
import org.codelibs.fess.es.config.exbhv.JobLogBhv;
import org.codelibs.fess.es.config.exentity.JobLog;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.opensearch.config.cbean.JobLogCB;
import org.codelibs.fess.opensearch.config.exbhv.JobLogBhv;
import org.codelibs.fess.opensearch.config.exentity.JobLog;
import org.codelibs.fess.util.ComponentUtil;
import org.dbflute.cbean.result.PagingResultBean;
import org.dbflute.optional.OptionalEntity;
import jakarta.annotation.Resource;
public class JobLogService {
@Resource

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -17,19 +17,19 @@ package org.codelibs.fess.app.service;
import java.util.List;
import javax.annotation.Resource;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.KeyMatchPager;
import org.codelibs.fess.es.config.cbean.KeyMatchCB;
import org.codelibs.fess.es.config.exbhv.KeyMatchBhv;
import org.codelibs.fess.es.config.exentity.KeyMatch;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.opensearch.config.cbean.KeyMatchCB;
import org.codelibs.fess.opensearch.config.exbhv.KeyMatchBhv;
import org.codelibs.fess.opensearch.config.exentity.KeyMatch;
import org.dbflute.cbean.result.PagingResultBean;
import org.dbflute.optional.OptionalEntity;
import jakarta.annotation.Resource;
public class KeyMatchService extends FessAppService {
@Resource

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -18,6 +18,8 @@ package org.codelibs.fess.app.service;
import java.util.Collections;
import java.util.List;
import javax.annotation.Resource;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.KuromojiPager;
@ -28,8 +30,6 @@ import org.codelibs.fess.dict.kuromoji.KuromojiItem;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.dbflute.optional.OptionalEntity;
import jakarta.annotation.Resource;
public class KuromojiService {
@Resource
protected DictionaryManager dictionaryManager;
@ -52,7 +52,7 @@ public class KuromojiService {
}
public OptionalEntity<KuromojiFile> getKuromojiFile(final String dictId) {
return dictionaryManager.getDictionaryFile(dictId).filter(KuromojiFile.class::isInstance)
return dictionaryManager.getDictionaryFile(dictId).filter(file -> file instanceof KuromojiFile)
.map(file -> OptionalEntity.of((KuromojiFile) file)).orElse(OptionalEntity.empty());
}

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -17,21 +17,21 @@ package org.codelibs.fess.app.service;
import java.util.List;
import javax.annotation.Resource;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.LabelTypePager;
import org.codelibs.fess.es.config.cbean.LabelTypeCB;
import org.codelibs.fess.es.config.exbhv.LabelTypeBhv;
import org.codelibs.fess.es.config.exentity.LabelType;
import org.codelibs.fess.helper.LabelTypeHelper;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.opensearch.config.cbean.LabelTypeCB;
import org.codelibs.fess.opensearch.config.exbhv.LabelTypeBhv;
import org.codelibs.fess.opensearch.config.exentity.LabelType;
import org.codelibs.fess.util.ComponentUtil;
import org.dbflute.cbean.result.PagingResultBean;
import org.dbflute.optional.OptionalEntity;
import jakarta.annotation.Resource;
public class LabelTypeService extends FessAppService {
@Resource

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -18,20 +18,20 @@ package org.codelibs.fess.app.service;
import java.util.Collection;
import java.util.List;
import javax.annotation.Resource;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.PathMapPager;
import org.codelibs.fess.es.config.cbean.PathMappingCB;
import org.codelibs.fess.es.config.exbhv.PathMappingBhv;
import org.codelibs.fess.es.config.exentity.PathMapping;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.opensearch.config.cbean.PathMappingCB;
import org.codelibs.fess.opensearch.config.exbhv.PathMappingBhv;
import org.codelibs.fess.opensearch.config.exentity.PathMapping;
import org.codelibs.fess.util.ComponentUtil;
import org.dbflute.cbean.result.PagingResultBean;
import org.dbflute.optional.OptionalEntity;
import jakarta.annotation.Resource;
public class PathMappingService extends FessAppService {
@Resource

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -18,6 +18,8 @@ package org.codelibs.fess.app.service;
import java.util.Collections;
import java.util.List;
import javax.annotation.Resource;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.ProtwordsPager;
@ -28,8 +30,6 @@ import org.codelibs.fess.dict.protwords.ProtwordsItem;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.dbflute.optional.OptionalEntity;
import jakarta.annotation.Resource;
public class ProtwordsService {
@Resource
protected DictionaryManager dictionaryManager;
@ -53,7 +53,7 @@ public class ProtwordsService {
}
public OptionalEntity<ProtwordsFile> getProtwordsFile(final String dictId) {
return dictionaryManager.getDictionaryFile(dictId).filter(ProtwordsFile.class::isInstance)
return dictionaryManager.getDictionaryFile(dictId).filter(file -> file instanceof ProtwordsFile)
.map(file -> OptionalEntity.of((ProtwordsFile) file)).orElse(OptionalEntity.empty());
}

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -17,20 +17,20 @@ package org.codelibs.fess.app.service;
import java.util.List;
import javax.annotation.Resource;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.RelatedContentPager;
import org.codelibs.fess.es.config.cbean.RelatedContentCB;
import org.codelibs.fess.es.config.exbhv.RelatedContentBhv;
import org.codelibs.fess.es.config.exentity.RelatedContent;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.opensearch.config.cbean.RelatedContentCB;
import org.codelibs.fess.opensearch.config.exbhv.RelatedContentBhv;
import org.codelibs.fess.opensearch.config.exentity.RelatedContent;
import org.codelibs.fess.util.ComponentUtil;
import org.dbflute.cbean.result.PagingResultBean;
import org.dbflute.optional.OptionalEntity;
import jakarta.annotation.Resource;
public class RelatedContentService extends FessAppService {
@Resource

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -17,20 +17,20 @@ package org.codelibs.fess.app.service;
import java.util.List;
import javax.annotation.Resource;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.RelatedQueryPager;
import org.codelibs.fess.es.config.cbean.RelatedQueryCB;
import org.codelibs.fess.es.config.exbhv.RelatedQueryBhv;
import org.codelibs.fess.es.config.exentity.RelatedQuery;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.opensearch.config.cbean.RelatedQueryCB;
import org.codelibs.fess.opensearch.config.exbhv.RelatedQueryBhv;
import org.codelibs.fess.opensearch.config.exentity.RelatedQuery;
import org.codelibs.fess.util.ComponentUtil;
import org.dbflute.cbean.result.PagingResultBean;
import org.dbflute.optional.OptionalEntity;
import jakarta.annotation.Resource;
public class RelatedQueryService extends FessAppService {
@Resource

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -17,18 +17,18 @@ package org.codelibs.fess.app.service;
import java.util.List;
import javax.annotation.Resource;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.ReqHeaderPager;
import org.codelibs.fess.es.config.cbean.RequestHeaderCB;
import org.codelibs.fess.es.config.exbhv.RequestHeaderBhv;
import org.codelibs.fess.es.config.exentity.RequestHeader;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.opensearch.config.cbean.RequestHeaderCB;
import org.codelibs.fess.opensearch.config.exbhv.RequestHeaderBhv;
import org.codelibs.fess.opensearch.config.exentity.RequestHeader;
import org.dbflute.cbean.result.PagingResultBean;
import org.dbflute.optional.OptionalEntity;
import jakarta.annotation.Resource;
public class RequestHeaderService {
@Resource

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -19,20 +19,20 @@ import static org.codelibs.core.stream.StreamUtil.stream;
import java.util.List;
import javax.annotation.Resource;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.RolePager;
import org.codelibs.fess.es.user.cbean.RoleCB;
import org.codelibs.fess.es.user.exbhv.RoleBhv;
import org.codelibs.fess.es.user.exbhv.UserBhv;
import org.codelibs.fess.es.user.exentity.Role;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.opensearch.user.cbean.RoleCB;
import org.codelibs.fess.opensearch.user.exbhv.RoleBhv;
import org.codelibs.fess.opensearch.user.exbhv.UserBhv;
import org.codelibs.fess.opensearch.user.exentity.Role;
import org.codelibs.fess.util.ComponentUtil;
import org.dbflute.cbean.result.PagingResultBean;
import org.dbflute.optional.OptionalEntity;
import jakarta.annotation.Resource;
public class RoleService {
@Resource

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -17,18 +17,18 @@ package org.codelibs.fess.app.service;
import java.util.List;
import javax.annotation.Resource;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.RoleTypePager;
import org.codelibs.fess.es.config.cbean.RoleTypeCB;
import org.codelibs.fess.es.config.exbhv.RoleTypeBhv;
import org.codelibs.fess.es.config.exentity.RoleType;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.opensearch.config.cbean.RoleTypeCB;
import org.codelibs.fess.opensearch.config.exbhv.RoleTypeBhv;
import org.codelibs.fess.opensearch.config.exentity.RoleType;
import org.dbflute.cbean.result.PagingResultBean;
import org.dbflute.optional.OptionalEntity;
import jakarta.annotation.Resource;
public class RoleTypeService {
@Resource

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -17,22 +17,22 @@ package org.codelibs.fess.app.service;
import java.util.List;
import javax.annotation.Resource;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.SchedulerPager;
import org.codelibs.fess.es.config.cbean.ScheduledJobCB;
import org.codelibs.fess.es.config.exbhv.ScheduledJobBhv;
import org.codelibs.fess.es.config.exentity.ScheduledJob;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.opensearch.config.cbean.ScheduledJobCB;
import org.codelibs.fess.opensearch.config.exbhv.ScheduledJobBhv;
import org.codelibs.fess.opensearch.config.exentity.ScheduledJob;
import org.codelibs.fess.util.ComponentUtil;
import org.dbflute.cbean.result.PagingResultBean;
import org.dbflute.optional.OptionalEntity;
import org.lastaflute.job.LaCron;
import jakarta.annotation.Resource;
public class ScheduledJobService {
private static final Logger logger = LogManager.getLogger(ScheduledJobService.class);

View file

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 CodeLibs Project and the Others.
* Copyright 2012-2022 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.
@ -27,28 +27,30 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.codelibs.core.beans.util.BeanUtil;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.pager.SearchLogPager;
import org.codelibs.fess.es.log.allcommon.EsPagingResultBean;
import org.codelibs.fess.es.log.cbean.ClickLogCB;
import org.codelibs.fess.es.log.cbean.FavoriteLogCB;
import org.codelibs.fess.es.log.cbean.SearchLogCB;
import org.codelibs.fess.es.log.cbean.UserInfoCB;
import org.codelibs.fess.es.log.exbhv.ClickLogBhv;
import org.codelibs.fess.es.log.exbhv.FavoriteLogBhv;
import org.codelibs.fess.es.log.exbhv.SearchLogBhv;
import org.codelibs.fess.es.log.exbhv.UserInfoBhv;
import org.codelibs.fess.es.log.exentity.ClickLog;
import org.codelibs.fess.es.log.exentity.FavoriteLog;
import org.codelibs.fess.es.log.exentity.SearchLog;
import org.codelibs.fess.es.log.exentity.UserInfo;
import org.codelibs.fess.exception.FessSystemException;
import org.codelibs.fess.helper.SystemHelper;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.opensearch.log.allcommon.EsPagingResultBean;
import org.codelibs.fess.opensearch.log.cbean.ClickLogCB;
import org.codelibs.fess.opensearch.log.cbean.FavoriteLogCB;
import org.codelibs.fess.opensearch.log.cbean.SearchLogCB;
import org.codelibs.fess.opensearch.log.cbean.UserInfoCB;
import org.codelibs.fess.opensearch.log.exbhv.ClickLogBhv;
import org.codelibs.fess.opensearch.log.exbhv.FavoriteLogBhv;
import org.codelibs.fess.opensearch.log.exbhv.SearchLogBhv;
import org.codelibs.fess.opensearch.log.exbhv.UserInfoBhv;
import org.codelibs.fess.opensearch.log.exentity.ClickLog;
import org.codelibs.fess.opensearch.log.exentity.FavoriteLog;
import org.codelibs.fess.opensearch.log.exentity.SearchLog;
import org.codelibs.fess.opensearch.log.exentity.UserInfo;
import org.codelibs.fess.taglib.FessFunctions;
import org.dbflute.optional.OptionalEntity;
import org.opensearch.search.aggregations.AggregationBuilders;
@ -59,8 +61,6 @@ import org.opensearch.search.aggregations.bucket.terms.Terms;
import org.opensearch.search.aggregations.metrics.Avg;
import org.opensearch.search.aggregations.metrics.Cardinality;
import jakarta.annotation.Resource;
public class SearchLogService {
private static final String YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm";
@ -556,14 +556,14 @@ public class SearchLogService {
}
public void deleteSearchLog(final Object e) {
if (e instanceof final ClickLog clickLog) {
clickLogBhv.delete(clickLog);
} else if (e instanceof final FavoriteLog favoriteLog) {
favoriteLogBhv.delete(favoriteLog);
} else if (e instanceof final UserInfo userInfo) {
userInfoBhv.delete(userInfo);
} else if (e instanceof final SearchLog searchLog) {
searchLogBhv.delete(searchLog);
if (e instanceof ClickLog) {
clickLogBhv.delete((ClickLog) e);
} else if (e instanceof FavoriteLog) {
favoriteLogBhv.delete((FavoriteLog) e);
} else if (e instanceof UserInfo) {
userInfoBhv.delete((UserInfo) e);
} else if (e instanceof SearchLog) {
searchLogBhv.delete((SearchLog) e);
} else {
throw new FessSystemException("Unknown log entity: " + e);
}

Some files were not shown because too many files have changed in this diff Show more