Merge branch '10.3.x'
This commit is contained in:
commit
fed313bba3
20 changed files with 327 additions and 257 deletions
|
@ -44,8 +44,8 @@
|
|||
<param name="plugin.groupId" value="org/codelibs" />
|
||||
<param name="plugin.name.prefix" value="elasticsearch-" />
|
||||
<param name="plugin.name" value="configsync" />
|
||||
<param name="plugin.version" value="2.4.0" />
|
||||
<param name="plugin.zip.version" value="2.4.0" />
|
||||
<param name="plugin.version" value="2.4.2" />
|
||||
<param name="plugin.zip.version" value="2.4.2" />
|
||||
</antcall>
|
||||
<!-- dataformat -->
|
||||
<antcall target="install.plugin">
|
||||
|
|
4
pom.xml
4
pom.xml
|
@ -57,10 +57,10 @@
|
|||
<utflute.version>0.6.1B</utflute.version>
|
||||
|
||||
<!-- Crawler -->
|
||||
<crawler.version>1.0.11</crawler.version>
|
||||
<crawler.version>1.0.12-SNAPSHOT</crawler.version>
|
||||
|
||||
<!-- Suggest -->
|
||||
<suggest.version>2.3.0</suggest.version>
|
||||
<suggest.version>2.3.1</suggest.version>
|
||||
|
||||
<!-- Elasticsearch -->
|
||||
<elasticsearch.version>2.4.1</elasticsearch.version>
|
||||
|
|
146
src/main/java/org/codelibs/fess/api/BaseJsonApiManager.java
Normal file
146
src/main/java/org/codelibs/fess/api/BaseJsonApiManager.java
Normal file
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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.lang3.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.lastaflute.web.util.LaRequestUtil;
|
||||
import org.lastaflute.web.util.LaResponseUtil;
|
||||
|
||||
public abstract class BaseJsonApiManager extends BaseApiManager {
|
||||
|
||||
protected void writeJsonResponse(final int status, final String body, final Throwable t) {
|
||||
if (t == null) {
|
||||
writeJsonResponse(status, body, (String) null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (t instanceof InvalidAccessTokenException) {
|
||||
final InvalidAccessTokenException e = (InvalidAccessTokenException) t;
|
||||
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) {
|
||||
final String callback = LaRequestUtil.getRequest().getParameter("callback");
|
||||
final boolean isJsonp = 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(Constants.WEB_API_VERSION);
|
||||
buf.append(',');
|
||||
buf.append("\"status\":");
|
||||
buf.append(status);
|
||||
if (status == 0) {
|
||||
if (StringUtil.isNotBlank(body)) {
|
||||
buf.append(',');
|
||||
buf.append(body);
|
||||
}
|
||||
} else {
|
||||
buf.append(',');
|
||||
buf.append("\"message\":");
|
||||
buf.append(escapeJson(errMsg));
|
||||
}
|
||||
buf.append('}');
|
||||
buf.append('}');
|
||||
if (isJsonp) {
|
||||
buf.append(')');
|
||||
}
|
||||
write(buf.toString(), "text/javascript+json", 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 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 Number) {
|
||||
buf.append(obj);
|
||||
} 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();
|
||||
}
|
||||
|
||||
}
|
|
@ -37,7 +37,7 @@ import javax.servlet.ServletException;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang.StringEscapeUtils;
|
||||
import org.apache.commons.lang3.StringEscapeUtils;
|
||||
import org.codelibs.core.CoreLibConstants;
|
||||
import org.codelibs.core.lang.StringUtil;
|
||||
import org.codelibs.fess.Constants;
|
||||
|
@ -317,9 +317,9 @@ public class GsaApiManager extends BaseApiManager implements WebApiManager {
|
|||
buf.append("</data>");
|
||||
} else if (obj instanceof Date) {
|
||||
final SimpleDateFormat sdf = new SimpleDateFormat(CoreLibConstants.DATE_FORMAT_ISO_8601_EXTEND);
|
||||
buf.append(StringEscapeUtils.escapeXml(sdf.format(obj)));
|
||||
buf.append(StringEscapeUtils.escapeXml10(sdf.format(obj)));
|
||||
} else if (obj != null) {
|
||||
buf.append(StringEscapeUtils.escapeXml(obj.toString()));
|
||||
buf.append(StringEscapeUtils.escapeXml10(obj.toString()));
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
|
|
@ -15,27 +15,25 @@
|
|||
*/
|
||||
package org.codelibs.fess.api.json;
|
||||
|
||||
import static org.codelibs.core.stream.StreamUtil.stream;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.net.URLDecoder;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
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.BaseJsonApiManager;
|
||||
import org.codelibs.fess.app.service.FavoriteLogService;
|
||||
import org.codelibs.fess.app.service.SearchService;
|
||||
import org.codelibs.fess.entity.FacetInfo;
|
||||
|
@ -45,7 +43,6 @@ 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.FessEsClient;
|
||||
import org.codelibs.fess.exception.InvalidAccessTokenException;
|
||||
import org.codelibs.fess.exception.WebApiException;
|
||||
import org.codelibs.fess.helper.LabelTypeHelper;
|
||||
import org.codelibs.fess.helper.PopularWordHelper;
|
||||
|
@ -62,12 +59,10 @@ import org.elasticsearch.common.xcontent.ToXContent;
|
|||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.script.Script;
|
||||
import org.lastaflute.web.util.LaRequestUtil;
|
||||
import org.lastaflute.web.util.LaResponseUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class JsonApiManager extends BaseApiManager {
|
||||
public class JsonApiManager extends BaseJsonApiManager {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(JsonApiManager.class);
|
||||
|
||||
|
@ -121,15 +116,19 @@ public class JsonApiManager extends BaseApiManager {
|
|||
try {
|
||||
final PingResponse pingResponse = fessEsClient.ping();
|
||||
status = pingResponse.getStatus();
|
||||
String errMsg = null;
|
||||
if (status != 0) {
|
||||
errMsg = stream(pingResponse.getFailures()).get(stream -> stream.collect(Collectors.joining()));
|
||||
}
|
||||
writeJsonResponse(status, null, errMsg);
|
||||
} catch (final Exception e) {
|
||||
status = 9;
|
||||
err = e;
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Failed to process a ping request.", e);
|
||||
}
|
||||
writeJsonResponse(status, null, err);
|
||||
}
|
||||
|
||||
writeJsonResponse(status, null, err);
|
||||
}
|
||||
|
||||
protected void processSearchRequest(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) {
|
||||
|
@ -534,187 +533,6 @@ public class JsonApiManager extends BaseApiManager {
|
|||
|
||||
}
|
||||
|
||||
public static void writeJsonResponse(final int status, final String body, final Throwable t) {
|
||||
if (t == null) {
|
||||
writeJsonResponse(status, body, (String) null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (t instanceof InvalidAccessTokenException) {
|
||||
final InvalidAccessTokenException e = (InvalidAccessTokenException) t;
|
||||
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());
|
||||
}
|
||||
|
||||
public static void writeJsonResponse(final int status, final String body, final String errMsg) {
|
||||
final String callback = LaRequestUtil.getRequest().getParameter("callback");
|
||||
final boolean isJsonp = 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(Constants.WEB_API_VERSION);
|
||||
buf.append(',');
|
||||
buf.append("\"status\":");
|
||||
buf.append(status);
|
||||
if (status == 0) {
|
||||
if (StringUtil.isNotBlank(body)) {
|
||||
buf.append(',');
|
||||
buf.append(body);
|
||||
}
|
||||
} else {
|
||||
buf.append(',');
|
||||
buf.append("\"message\":");
|
||||
buf.append(escapeJson(errMsg));
|
||||
}
|
||||
buf.append('}');
|
||||
buf.append('}');
|
||||
if (isJsonp) {
|
||||
buf.append(')');
|
||||
}
|
||||
write(buf.toString(), "text/javascript+json", Constants.UTF_8);
|
||||
|
||||
}
|
||||
|
||||
public static String escapeCallbackName(final String callbackName) {
|
||||
return "/**/" + callbackName.replaceAll("[^0-9a-zA-Z_\\$\\.]", StringUtil.EMPTY);
|
||||
}
|
||||
|
||||
public static String escapeJson(final Object obj) {
|
||||
if (obj == null) {
|
||||
return "null";
|
||||
}
|
||||
|
||||
final StringBuilder buf = new StringBuilder(255);
|
||||
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 Number) {
|
||||
buf.append(obj);
|
||||
} else if (obj instanceof Date) {
|
||||
final SimpleDateFormat sdf = new SimpleDateFormat(CoreLibConstants.DATE_FORMAT_ISO_8601_EXTEND, Locale.ROOT);
|
||||
buf.append('\"').append(escapeJsonString(sdf.format(obj))).append('\"');
|
||||
} else {
|
||||
buf.append('\"').append(escapeJsonString(obj.toString())).append('\"');
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public static String escapeJsonString(final String str) {
|
||||
|
||||
final StringBuilder out = new StringBuilder(str.length() * 2);
|
||||
int sz;
|
||||
sz = str.length();
|
||||
for (int i = 0; i < sz; i++) {
|
||||
final char ch = str.charAt(i);
|
||||
|
||||
// handle unicode
|
||||
if (ch > 0xfff) {
|
||||
out.append("\\u");
|
||||
out.append(hex(ch));
|
||||
} else if (ch > 0xff) {
|
||||
out.append("\\u0");
|
||||
out.append(hex(ch));
|
||||
} else if (ch > 0x7f) {
|
||||
out.append("\\u00");
|
||||
out.append(hex(ch));
|
||||
} else if (ch < 32) {
|
||||
switch (ch) {
|
||||
case '\b':
|
||||
out.append('\\');
|
||||
out.append('b');
|
||||
break;
|
||||
case '\n':
|
||||
out.append('\\');
|
||||
out.append('n');
|
||||
break;
|
||||
case '\t':
|
||||
out.append('\\');
|
||||
out.append('t');
|
||||
break;
|
||||
case '\f':
|
||||
out.append('\\');
|
||||
out.append('f');
|
||||
break;
|
||||
case '\r':
|
||||
out.append('\\');
|
||||
out.append('r');
|
||||
break;
|
||||
default:
|
||||
if (ch > 0xf) {
|
||||
out.append("\\u00");
|
||||
out.append(hex(ch));
|
||||
} else {
|
||||
out.append("\\u000");
|
||||
out.append(hex(ch));
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (ch) {
|
||||
case '"':
|
||||
out.append("\\u0022");
|
||||
break;
|
||||
case '\\':
|
||||
out.append("\\u005C");
|
||||
break;
|
||||
case '/':
|
||||
out.append("\\u002F");
|
||||
break;
|
||||
default:
|
||||
out.append(ch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
private static String hex(final char ch) {
|
||||
return Integer.toHexString(ch).toUpperCase();
|
||||
}
|
||||
|
||||
protected static class JsonRequestParams implements SearchRequestParams {
|
||||
|
||||
private final HttpServletRequest request;
|
||||
|
|
|
@ -26,10 +26,10 @@ import javax.servlet.ServletException;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang3.StringEscapeUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.codelibs.core.lang.StringUtil;
|
||||
import org.codelibs.fess.api.BaseApiManager;
|
||||
import org.codelibs.fess.api.json.JsonApiManager;
|
||||
import org.codelibs.fess.api.BaseJsonApiManager;
|
||||
import org.codelibs.fess.app.service.SearchService;
|
||||
import org.codelibs.fess.entity.FacetInfo;
|
||||
import org.codelibs.fess.entity.GeoInfo;
|
||||
|
@ -45,7 +45,7 @@ import org.codelibs.fess.util.ComponentUtil;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SuggestApiManager extends BaseApiManager {
|
||||
public class SuggestApiManager extends BaseJsonApiManager {
|
||||
private static final Logger logger = LoggerFactory.getLogger(SuggestApiManager.class);
|
||||
|
||||
public SuggestApiManager() {
|
||||
|
@ -106,13 +106,13 @@ public class SuggestApiManager extends BaseApiManager {
|
|||
}
|
||||
first = false;
|
||||
|
||||
buf.append("{\"text\":\"").append(JsonApiManager.escapeJsonString(item.getText())).append('\"');
|
||||
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(JsonApiManager.escapeJsonString(item.getTags()[i])).append('\"');
|
||||
buf.append('\"').append(StringEscapeUtils.escapeJson(item.getTags()[i])).append('\"');
|
||||
}
|
||||
buf.append(']');
|
||||
|
||||
|
@ -121,7 +121,7 @@ public class SuggestApiManager extends BaseApiManager {
|
|||
if (i > 0) {
|
||||
buf.append(',');
|
||||
}
|
||||
buf.append('\"').append(JsonApiManager.escapeJsonString(item.getRoles()[i])).append('\"');
|
||||
buf.append('\"').append(StringEscapeUtils.escapeJson(item.getRoles()[i])).append('\"');
|
||||
}
|
||||
buf.append(']');
|
||||
|
||||
|
@ -130,7 +130,7 @@ public class SuggestApiManager extends BaseApiManager {
|
|||
if (i > 0) {
|
||||
buf.append(',');
|
||||
}
|
||||
buf.append('\"').append(JsonApiManager.escapeJsonString(item.getFields()[i])).append('\"');
|
||||
buf.append('\"').append(StringEscapeUtils.escapeJson(item.getFields()[i])).append('\"');
|
||||
}
|
||||
buf.append(']');
|
||||
|
||||
|
@ -156,7 +156,7 @@ public class SuggestApiManager extends BaseApiManager {
|
|||
}
|
||||
}
|
||||
|
||||
JsonApiManager.writeJsonResponse(status, buf.toString(), errMsg);
|
||||
writeJsonResponse(status, buf.toString(), errMsg);
|
||||
}
|
||||
|
||||
protected static class RequestParameter implements SearchRequestParams {
|
||||
|
@ -179,7 +179,7 @@ public class SuggestApiManager extends BaseApiManager {
|
|||
final String query = request.getParameter("query");
|
||||
final String fieldsStr = request.getParameter("fields");
|
||||
final String[] fields;
|
||||
if (StringUtils.isNotBlank(fieldsStr)) {
|
||||
if (StringUtil.isNotBlank(fieldsStr)) {
|
||||
fields = fieldsStr.split(",");
|
||||
} else {
|
||||
fields = new String[0];
|
||||
|
@ -187,7 +187,7 @@ public class SuggestApiManager extends BaseApiManager {
|
|||
|
||||
final String numStr = request.getParameter("num");
|
||||
final int num;
|
||||
if (StringUtils.isNotBlank(numStr) && StringUtils.isNumeric(numStr)) {
|
||||
if (StringUtil.isNotBlank(numStr) && StringUtils.isNumeric(numStr)) {
|
||||
num = Integer.parseInt(numStr);
|
||||
} else {
|
||||
num = 10;
|
||||
|
|
|
@ -30,7 +30,7 @@ import java.util.Map;
|
|||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.StringEscapeUtils;
|
||||
import org.apache.commons.lang3.StringEscapeUtils;
|
||||
import org.codelibs.core.lang.StringUtil;
|
||||
import org.codelibs.fess.Constants;
|
||||
import org.codelibs.fess.app.service.FailureUrlService;
|
||||
|
|
|
@ -15,18 +15,40 @@
|
|||
*/
|
||||
package org.codelibs.fess.entity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
|
||||
import org.elasticsearch.cluster.health.ClusterHealthStatus;
|
||||
|
||||
public class PingResponse {
|
||||
private int status = 0;
|
||||
private int status;
|
||||
|
||||
private List<String> failures;
|
||||
|
||||
private String clusterName;
|
||||
|
||||
private String clusterStatus;
|
||||
|
||||
public PingResponse(final ClusterHealthResponse response) {
|
||||
status = response.getStatus() == ClusterHealthStatus.RED ? 1 : 0;
|
||||
failures = response.getValidationFailures();
|
||||
clusterName = response.getClusterName();
|
||||
clusterStatus = response.getStatus().toString();
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public String[] getFailures() {
|
||||
return failures.stream().toArray(n -> new String[n]);
|
||||
}
|
||||
|
||||
public String getClusterName() {
|
||||
return clusterName;
|
||||
}
|
||||
|
||||
public String getClusterStatus() {
|
||||
return clusterStatus;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import static org.codelibs.core.stream.StreamUtil.stream;
|
|||
import static org.codelibs.elasticsearch.runner.ElasticsearchClusterRunner.newConfigs;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -328,6 +329,7 @@ public class FessEsClient implements Client {
|
|||
// ignore
|
||||
}
|
||||
if (!exists) {
|
||||
waitForConfigSyncStatus();
|
||||
configListMap.getOrDefault(configIndex, Collections.emptyList()).forEach(
|
||||
path -> {
|
||||
String source = null;
|
||||
|
@ -340,7 +342,12 @@ public class FessEsClient implements Client {
|
|||
if (response.getHttpStatusCode() == 200) {
|
||||
logger.info("Register " + path + " to " + configIndex);
|
||||
} else {
|
||||
logger.warn("Invalid request for " + path);
|
||||
if (response.getContentException() != null) {
|
||||
logger.warn("Invalid request for " + path + ".", response.getContentException());
|
||||
} else {
|
||||
logger.warn("Invalid request for " + path + ". The response is "
|
||||
+ response.getContentAsString());
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
|
@ -520,6 +527,24 @@ public class FessEsClient implements Client {
|
|||
}
|
||||
}
|
||||
|
||||
private void waitForConfigSyncStatus() {
|
||||
try (CurlResponse response =
|
||||
Curl.get(org.codelibs.fess.util.ResourceUtil.getElasticsearchHttpUrl() + "/_configsync/wait").param("status", "green")
|
||||
.execute()) {
|
||||
if (response.getHttpStatusCode() == 200) {
|
||||
logger.info("ConfigSync is ready.");
|
||||
} else {
|
||||
if (response.getContentException() != null) {
|
||||
throw new FessSystemException("Configsync is not available.", response.getContentException());
|
||||
} else {
|
||||
throw new FessSystemException("Configsync is not available.", response.getContentException());
|
||||
}
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
throw new FessSystemException("Configsync is not available.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@PreDestroy
|
||||
public void close() {
|
||||
|
|
|
@ -89,6 +89,10 @@ public class PopularWordHelper {
|
|||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public void clearCache() {
|
||||
cache.invalidateAll();
|
||||
}
|
||||
|
||||
protected String getCacheKey(final String seed, final String[] tags, final String[] roles, final String[] fields,
|
||||
final String[] excludes) {
|
||||
final StringBuilder buf = new StringBuilder(100);
|
||||
|
|
|
@ -33,6 +33,7 @@ import java.util.UUID;
|
|||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
|
@ -75,6 +76,8 @@ public class SystemHelper {
|
|||
|
||||
protected Random random = new SecureRandom();
|
||||
|
||||
protected AtomicInteger previousClusterState = new AtomicInteger(0);
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
final FessConfig fessConfig = ComponentUtil.getFessConfig();
|
||||
|
@ -313,4 +316,8 @@ public class SystemHelper {
|
|||
this.random = random;
|
||||
}
|
||||
|
||||
public boolean isChangedClusterState(int status) {
|
||||
return previousClusterState.getAndSet(status) != status;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
72
src/main/java/org/codelibs/fess/job/PingEsJob.java
Normal file
72
src/main/java/org/codelibs/fess/job/PingEsJob.java
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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.job;
|
||||
|
||||
import org.codelibs.core.lang.StringUtil;
|
||||
import org.codelibs.fess.entity.PingResponse;
|
||||
import org.codelibs.fess.es.client.FessEsClient;
|
||||
import org.codelibs.fess.helper.SystemHelper;
|
||||
import org.codelibs.fess.mylasta.direction.FessConfig;
|
||||
import org.codelibs.fess.mylasta.mail.EsStatusPostcard;
|
||||
import org.codelibs.fess.util.ComponentUtil;
|
||||
import org.lastaflute.core.mail.Postbox;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class PingEsJob {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PingEsJob.class);
|
||||
|
||||
public String execute() {
|
||||
final FessEsClient fessEsClient = ComponentUtil.getFessEsClient();
|
||||
final FessConfig fessConfig = ComponentUtil.getFessConfig();
|
||||
final SystemHelper systemHelper = ComponentUtil.getSystemHelper();
|
||||
|
||||
final StringBuilder resultBuf = new StringBuilder();
|
||||
|
||||
final String notificationTo = fessConfig.getNotificationTo();
|
||||
final PingResponse ping = fessEsClient.ping();
|
||||
final int status = ping.getStatus();
|
||||
if (systemHelper.isChangedClusterState(status)) {
|
||||
if (StringUtil.isNotBlank(notificationTo)) {
|
||||
final Postbox postbox = ComponentUtil.getComponent(Postbox.class);
|
||||
try {
|
||||
EsStatusPostcard.droppedInto(postbox, postcard -> {
|
||||
postcard.setFrom(fessConfig.getMailFromAddress(), fessConfig.getMailFromName());
|
||||
postcard.addReplyTo(fessConfig.getMailReturnPath());
|
||||
postcard.addTo(notificationTo);
|
||||
postcard.setHostname(systemHelper.getHostname());
|
||||
postcard.setClustername(ping.getClusterName());
|
||||
postcard.setClusterstatus(ping.getClusterStatus());
|
||||
});
|
||||
} catch (final Exception e) {
|
||||
logger.warn("Failed to send a test mail.", e);
|
||||
}
|
||||
}
|
||||
resultBuf.append("Status of ").append(ping.getClusterName()).append(" is changed to ").append(ping.getClusterStatus())
|
||||
.append('.');
|
||||
} else {
|
||||
if (status == 0) {
|
||||
resultBuf.append(ping.getClusterName()).append(" is alive.");
|
||||
} else {
|
||||
resultBuf.append(ping.getClusterName()).append(" is not available.");
|
||||
}
|
||||
}
|
||||
|
||||
return resultBuf.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -243,6 +243,7 @@ public class SuggestJob {
|
|||
if (exitValue != 0) {
|
||||
throw new FessSystemException("Exit Code: " + exitValue + "\nOutput:\n" + it.getOutput());
|
||||
}
|
||||
ComponentUtil.getPopularWordHelper().clearCache();
|
||||
} catch (final FessSystemException e) {
|
||||
throw e;
|
||||
} catch (final InterruptedException e) {
|
||||
|
|
|
@ -50,7 +50,7 @@ public class EsStatusPostcard extends LaTypicalPostcard {
|
|||
|
||||
@Override
|
||||
protected String[] getPropertyNames() {
|
||||
return new String[] { "hostname", "server", "statusBefore", "statusAfter", "indexBefore", "indexAfter" };
|
||||
return new String[] { "hostname", "clustername", "clusterstatus" };
|
||||
}
|
||||
|
||||
// ===================================================================================
|
||||
|
@ -108,47 +108,20 @@ public class EsStatusPostcard extends LaTypicalPostcard {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the value of server, used in parameter comment. <br>
|
||||
* Set the value of clustername, used in parameter comment. <br>
|
||||
* Even if empty string, treated as empty plainly. So "IF pmb != null" is false if empty.
|
||||
* @param server The parameter value of server. (NotNull)
|
||||
* @param clustername The parameter value of clustername. (NotNull)
|
||||
*/
|
||||
public void setServer(String server) {
|
||||
registerVariable("server", server);
|
||||
public void setClustername(String clustername) {
|
||||
registerVariable("clustername", clustername);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of statusBefore, used in parameter comment. <br>
|
||||
* Set the value of clusterstatus, used in parameter comment. <br>
|
||||
* Even if empty string, treated as empty plainly. So "IF pmb != null" is false if empty.
|
||||
* @param statusBefore The parameter value of statusBefore. (NotNull)
|
||||
* @param clusterstatus The parameter value of clusterstatus. (NotNull)
|
||||
*/
|
||||
public void setStatusBefore(String statusBefore) {
|
||||
registerVariable("statusBefore", statusBefore);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of statusAfter, used in parameter comment. <br>
|
||||
* Even if empty string, treated as empty plainly. So "IF pmb != null" is false if empty.
|
||||
* @param statusAfter The parameter value of statusAfter. (NotNull)
|
||||
*/
|
||||
public void setStatusAfter(String statusAfter) {
|
||||
registerVariable("statusAfter", statusAfter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of indexBefore, used in parameter comment. <br>
|
||||
* Even if empty string, treated as empty plainly. So "IF pmb != null" is false if empty.
|
||||
* @param indexBefore The parameter value of indexBefore. (NotNull)
|
||||
*/
|
||||
public void setIndexBefore(String indexBefore) {
|
||||
registerVariable("indexBefore", indexBefore);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of indexAfter, used in parameter comment. <br>
|
||||
* Even if empty string, treated as empty plainly. So "IF pmb != null" is false if empty.
|
||||
* @param indexAfter The parameter value of indexAfter. (NotNull)
|
||||
*/
|
||||
public void setIndexAfter(String indexAfter) {
|
||||
registerVariable("indexAfter", indexAfter);
|
||||
public void setClusterstatus(String clusterstatus) {
|
||||
registerVariable("clusterstatus", clusterstatus);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,3 +10,5 @@
|
|||
{"name":"Doc Purger","target":"all","cronExpression":"* * * * *","scriptType":"groovy","scriptData":"return container.getComponent(\"purgeDocJob\").execute();","jobLogging":false,"crawler":false,"available":true,"sortOrder":5,"createdBy":"system","createdTime":0,"updatedBy":"system","updatedTime":0}
|
||||
{"index":{"_index":".fess_config","_type":"scheduled_job","_id":"thumbnail_purger"}}
|
||||
{"name":"Thumbnail Purger","target":"all","cronExpression":"0 0 * * *","scriptType":"groovy","scriptData":"return container.getComponent(\"purgeThumbnailJob\").expiry(30 * 24 * 60 * 60 * 1000).execute();","jobLogging":true,"crawler":false,"available":true,"sortOrder":6,"createdBy":"system","createdTime":0,"updatedBy":"system","updatedTime":0}
|
||||
{"index":{"_index":".fess_config","_type":"scheduled_job","_id":"ping_es"}}
|
||||
{"name":"Ping Elasticsearch","target":"all","cronExpression":"* * * * *","scriptType":"groovy","scriptData":"return container.getComponent(\"pingEsJob\").execute();","jobLogging":false,"crawler":false,"available":true,"sortOrder":7,"createdBy":"system","createdTime":0,"updatedBy":"system","updatedTime":0}
|
||||
|
|
|
@ -18,4 +18,6 @@
|
|||
</component>
|
||||
<component name="purgeThumbnailJob" class="org.codelibs.fess.job.PurgeThumbnailJob" instance="prototype">
|
||||
</component>
|
||||
<component name="pingEsJob" class="org.codelibs.fess.job.PingEsJob" instance="prototype">
|
||||
</component>
|
||||
</components>
|
||||
|
|
|
@ -4,11 +4,9 @@
|
|||
subject: [FESS] Status Change: /*pmb.hostname:orElse('Unknown')*/
|
||||
>>>
|
||||
--- Server Info ---
|
||||
Cluster Name: /*pmb.clustername:orElse('Unknown')*/
|
||||
Host Name: /*pmb.hostname:orElse('Unknown')*/
|
||||
|
||||
Elasticsearch: /*pmb.server*/
|
||||
|
||||
--- Status ---
|
||||
/*IF pmb.statusBefore != null*/Status: /*pmb.statusBefore*/ -> /*pmb.statusAfter*//*END*/
|
||||
/*IF pmb.indexBefore != null*/Index: /*pmb.indexBefore*/ -> /*pmb.indexAfter*//*END*/
|
||||
Cluster Status: /*pmb.clusterstatus:orElse('Unknown')*/
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
<la:message key="labels.administration" />
|
||||
</la:link>
|
||||
</c:if>
|
||||
<la:link href="/logout" styleClass="dropdown-item">
|
||||
<la:link href="/logout/" styleClass="dropdown-item">
|
||||
<la:message key="labels.logout" />
|
||||
</la:link>
|
||||
</div>
|
||||
|
|
|
@ -48,7 +48,7 @@ ${fe:facetForm()}${fe:geoForm()}
|
|||
<la:message key="labels.administration" />
|
||||
</la:link>
|
||||
</c:if>
|
||||
<la:link href="/logout" styleClass="dropdown-item">
|
||||
<la:link href="/logout/" styleClass="dropdown-item">
|
||||
<la:message key="labels.logout" />
|
||||
</la:link>
|
||||
</div>
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
<la:message key="labels.administration" />
|
||||
</la:link>
|
||||
</c:if>
|
||||
<la:link href="/logout" styleClass="dropdown-item">
|
||||
<la:link href="/logout/" styleClass="dropdown-item">
|
||||
<la:message key="labels.logout" />
|
||||
</la:link>
|
||||
</div>
|
||||
|
|
Loading…
Add table
Reference in a new issue