lastanized RootAction

This commit is contained in:
Shinsuke Sugaya 2015-08-15 22:34:15 +09:00
parent 8b4e62dce9
commit ded1bd6122
22 changed files with 1451 additions and 1309 deletions

View file

@ -149,9 +149,7 @@
<exclude>org/codelibs/fess/app/web/admin/RequestHeaderAction.java</exclude>
<exclude>org/codelibs/fess/app/web/base/AbstractLoginAction.java</exclude>
<exclude>org/codelibs/fess/app/web/ErrorAction.java</exclude>
<exclude>org/codelibs/fess/app/web/RootForm.java</exclude>
<exclude>org/codelibs/fess/app/web/LoginAction.java</exclude>
<exclude>org/codelibs/fess/app/web/RootAction.java</exclude>
<exclude>org/codelibs/fess/app/web/ErrorForm.java</exclude>
<exclude>org/codelibs/fess/app/web/LoginForm.java</exclude>
</excludes>

View file

@ -16,18 +16,21 @@
package org.codelibs.fess;
import org.codelibs.fess.mylasta.action.FessMessages;
import org.lastaflute.web.validation.VaMessenger;
public class InvalidQueryException extends FessSystemException {
private static final long serialVersionUID = 1L;
private final String messageCode;
private final VaMessenger<FessMessages> messageCode;
public InvalidQueryException(final String messageCode, final String message, final Throwable cause) {
public InvalidQueryException(final VaMessenger<FessMessages> messageCode, final String message, final Throwable cause) {
super(message, cause);
this.messageCode = messageCode;
}
public InvalidQueryException(final String messageCode, final String message) {
public InvalidQueryException(final VaMessenger<FessMessages> messageCode, final String message) {
super(message);
this.messageCode = messageCode;
}
@ -35,7 +38,7 @@ public class InvalidQueryException extends FessSystemException {
/**
* @return the messageCode
*/
public String getMessageCode() {
public VaMessenger<FessMessages> getMessageCode() {
return messageCode;
}

File diff suppressed because it is too large Load diff

View file

@ -18,81 +18,20 @@ package org.codelibs.fess.app.web;
import java.io.Serializable;
import org.codelibs.fess.entity.FacetInfo;
import org.codelibs.fess.entity.GeoInfo;
import org.codelibs.fess.util.SearchParamMap;
public class RootForm implements Serializable {
private static final long serialVersionUID = 1L;
public SearchParamMap fields = new SearchParamMap();
//@Maxbytelength(maxbytelength = 1000)
public String query;
public String additional[];
//@Maxbytelength(maxbytelength = 1000)
public String sort;
//@Maxbytelength(maxbytelength = 10)
public String op;
//@IntegerType
public String start;
//@IntegerType
public String pn;
//@IntegerType
public String num;
public String[] lang;
//@Maxbytelength(maxbytelength = 1000)
public String queryId;
public SearchParamMap fields = new SearchParamMap();
// response redirect
//@Required(target = "go")
//@Maxbytelength(maxbytelength = 4000)
public String rt;
//@Required(target = "go,cache")
//@Maxbytelength(maxbytelength = 100)
public String docId;
public String[] hq;
//@Maxbytelength(maxbytelength = 1000)
public String hash;
// xml/json
//@Maxbytelength(maxbytelength = 20)
public String type;
//@Maxbytelength(maxbytelength = 255)
public String callback;
public String[] fn;
// hotsearchword
//@Maxbytelength(maxbytelength = 100)
public String range;
// geo
public GeoInfo geo;
// facet
public FacetInfo facet;
// advance
public SearchParamMap options = new SearchParamMap();
}

View file

@ -29,11 +29,4 @@ public class BoostDocumentRuleSearchForm implements Serializable {
private static final long serialVersionUID = 1L;
public Map<String, String> searchParams = new HashMap<String, String>();
//@IntegerType
public String pageNumber;
public String getCurrentPageNumber() {
return pageNumber;
}
}

View file

@ -15,6 +15,185 @@
*/
package org.codelibs.fess.app.web.base;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang3.StringEscapeUtils;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.core.misc.DynamicProperties;
import org.codelibs.core.net.URLUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.SSCConstants;
import org.codelibs.fess.UnsupportedSearchException;
import org.codelibs.fess.client.FessEsClient;
import org.codelibs.fess.entity.LoginInfo;
import org.codelibs.fess.helper.FieldHelper;
import org.codelibs.fess.helper.LabelTypeHelper;
import org.codelibs.fess.helper.OpenSearchHelper;
import org.codelibs.fess.helper.QueryHelper;
import org.codelibs.fess.helper.RoleQueryHelper;
import org.codelibs.fess.helper.SystemHelper;
import org.codelibs.fess.helper.UserInfoHelper;
import org.codelibs.fess.helper.ViewHelper;
import org.codelibs.fess.screenshot.ScreenShotManager;
import org.codelibs.fess.util.SearchParamMap;
import org.lastaflute.web.callback.ActionRuntime;
import org.lastaflute.web.response.ActionResponse;
import org.lastaflute.web.response.render.RenderData;
import org.lastaflute.web.util.LaRequestUtil;
public abstract class FessSearchAction extends FessBaseAction {
protected static final String LABEL_FIELD = "label";
@Resource
protected FessEsClient fessEsClient;
@Resource
protected ScreenShotManager screenShotManager;
@Resource
protected LabelTypeHelper labelTypeHelper;
@Resource
protected ViewHelper viewHelper;
@Resource
protected QueryHelper queryHelper;
@Resource
protected RoleQueryHelper roleQueryHelper;
@Resource
protected UserInfoHelper userInfoHelper;
@Resource
protected SystemHelper systemHelper;
@Resource
protected FieldHelper fieldHelper;
@Resource
protected OpenSearchHelper openSearchHelper;
@Resource
protected DynamicProperties crawlerProperties;
@Resource
protected HttpServletRequest request;
protected boolean searchLogSupport;
protected boolean favoriteSupport;
@Override
public ActionResponse hookBefore(ActionRuntime runtime) { // application may override
searchLogSupport = Constants.TRUE.equals(crawlerProperties.getProperty(Constants.SEARCH_LOG_PROPERTY, Constants.TRUE));
favoriteSupport = Constants.TRUE.equals(crawlerProperties.getProperty(Constants.USER_FAVORITE_PROPERTY, Constants.FALSE));
runtime.registerData("searchLogSupport", searchLogSupport);
runtime.registerData("favoriteSupport", favoriteSupport);
return super.hookBefore(runtime);
}
@Override
protected void setupHtmlData(ActionRuntime runtime) {
super.setupHtmlData(runtime);
runtime.registerData("osddLink", openSearchHelper.hasOpenSearchFile());
runtime.registerData("helpPage", viewHelper.getPagePath("common/help"));
}
protected void searchAvailable() {
final String supportedSearch =
crawlerProperties.getProperty(Constants.SUPPORTED_SEARCH_FEATURE_PROPERTY, Constants.SUPPORTED_SEARCH_WEB);
if (Constants.SUPPORTED_SEARCH_NONE.equals(supportedSearch)) {
throw new UnsupportedSearchException("A search is not supported: " + LaRequestUtil.getRequest().getRequestURL());
}
}
protected List<Map<String, String>> buildLabelParams(RenderData data, SearchParamMap fields) {
// label
List<Map<String, String>> labelTypeItems = labelTypeHelper.getLabelTypeItemList();
data.register("labelTypeItems", labelTypeItems);
data.register("displayLabelTypeItems", labelTypeItems != null && !labelTypeItems.isEmpty());
if (!labelTypeItems.isEmpty() && !fields.containsKey(FessSearchAction.LABEL_FIELD)) {
final String defaultLabelValue = crawlerProperties.getProperty(Constants.DEFAULT_LABEL_VALUE_PROPERTY, StringUtil.EMPTY);
if (StringUtil.isNotBlank(defaultLabelValue)) {
final String[] values = defaultLabelValue.split("\n");
if (values != null && values.length > 0) {
final List<String> list = new ArrayList<String>(values.length);
for (final String value : values) {
if (StringUtil.isNotBlank(value)) {
list.add(value);
}
}
if (!list.isEmpty()) {
fields.put(FessSearchAction.LABEL_FIELD, list.toArray(new String[list.size()]));
}
}
}
}
final Map<String, String> labelMap = new LinkedHashMap<String, String>();
if (!labelTypeItems.isEmpty()) {
for (final Map<String, String> map : labelTypeItems) {
labelMap.put(map.get(Constants.ITEM_VALUE), map.get(Constants.ITEM_LABEL));
}
}
request.setAttribute(Constants.LABEL_VALUE_MAP, labelMap);
return labelTypeItems;
}
protected void buildUserParams(RenderData data) {
Locale locale = request.getLocale();
if (locale == null) {
locale = Locale.ENGLISH;
}
data.register("langItems", systemHelper.getLanguageItems(locale));
final HttpSession session = request.getSession(false);
if (session != null) {
final Object obj = session.getAttribute(SSCConstants.USER_INFO);
if (obj instanceof LoginInfo) {
final LoginInfo loginInfo = (LoginInfo) obj;
data.register("username", loginInfo.getUsername());
}
}
}
protected void buildInitParams() {
buildInitParamMap(viewHelper.getInitFacetParamMap(), Constants.FACET_QUERY, Constants.FACET_FORM);
buildInitParamMap(viewHelper.getInitGeoParamMap(), Constants.GEO_QUERY, Constants.GEO_FORM);
}
protected void buildInitParamMap(final Map<String, String> paramMap, final String queryKey, final String formKey) {
if (!paramMap.isEmpty()) {
final StringBuilder queryBuf = new StringBuilder(100);
final StringBuilder formBuf = new StringBuilder(100);
for (final Map.Entry<String, String> entry : paramMap.entrySet()) {
queryBuf.append('&');
queryBuf.append(URLUtil.encode(entry.getValue(), Constants.UTF_8));
queryBuf.append('=');
queryBuf.append(URLUtil.encode(entry.getKey(), Constants.UTF_8));
formBuf.append("<input type=\"hidden\" name=\"");
formBuf.append(StringEscapeUtils.escapeHtml4(entry.getValue()));
formBuf.append("\" value=\"");
formBuf.append(StringEscapeUtils.escapeHtml4(entry.getKey()));
formBuf.append("\"/>");
}
request.setAttribute(queryKey, queryBuf.toString());
request.setAttribute(formKey, formBuf.toString());
}
}
}

View file

@ -0,0 +1,80 @@
/*
* Copyright 2009-2015 the 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.app.web.cache;
import java.util.Map;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.web.base.FessSearchAction;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.lastaflute.web.Execute;
import org.lastaflute.web.response.StreamResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CacheAction extends FessSearchAction {
// ===================================================================================
// Constant
//
private static final Logger logger = LoggerFactory.getLogger(CacheAction.class);
// ===================================================================================
// Attribute
//
// ===================================================================================
// Hook
// ======
// ===================================================================================
// Search Execute
// ==============
@Execute
public StreamResponse index(final CacheForm form) {
searchAvailable();
Map<String, Object> doc = null;
try {
doc = fessEsClient.getDocument(fieldHelper.docIndex, fieldHelper.docType, queryRequestBuilder -> {
final TermQueryBuilder termQuery = QueryBuilders.termQuery(fieldHelper.docIdField, form.docId);
queryRequestBuilder.setQuery(termQuery);
queryRequestBuilder.addFields(queryHelper.getResponseFields());
return true;
}).get();
} catch (final Exception e) {
logger.warn("Failed to request: " + form.docId, e);
}
if (doc == null) {
throwValidationError(messages -> {
messages.addErrorsDocidNotFound(GLOBAL, form.docId);
}, () -> asHtml(path_ErrorJsp));
}
final String content = viewHelper.createCacheContent(doc, form.hq);
if (content == null) {
throwValidationError(messages -> {
messages.addErrorsDocidNotFound(GLOBAL, form.docId);
}, () -> asHtml(path_ErrorJsp));
}
return asStream((String) doc.get(fieldHelper.docIdField)).contentType("text/html; charset=UTF-8").data(
content.getBytes(Constants.CHARSET_UTF_8));
}
}

View file

@ -0,0 +1,13 @@
package org.codelibs.fess.app.web.cache;
import org.codelibs.fess.app.web.RootForm;
public class CacheForm extends RootForm {
private static final long serialVersionUID = 1L;
//@Required(target = "go,cache")
//@Maxbytelength(maxbytelength = 100)
public String docId;
public String[] hq;
}

View file

@ -0,0 +1,176 @@
/*
* Copyright 2009-2015 the 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.app.web.go;
import java.awt.Desktop;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.core.net.URLUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.app.web.base.FessSearchAction;
import org.codelibs.fess.es.exentity.ClickLog;
import org.codelibs.fess.helper.CrawlingConfigHelper;
import org.codelibs.fess.helper.SearchLogHelper;
import org.codelibs.fess.util.ComponentUtil;
import org.codelibs.robot.util.CharUtil;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.lastaflute.web.Execute;
import org.lastaflute.web.response.HtmlResponse;
import org.lastaflute.web.util.LaResponseUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class GoAction extends FessSearchAction {
// ===================================================================================
// Constant
//
private static final Logger logger = LoggerFactory.getLogger(GoAction.class);
// ===================================================================================
// Attribute
//
// ===================================================================================
// Hook
// ======
// ===================================================================================
// Search Execute
// ==============
@Execute
public HtmlResponse index(final GoForm form) throws IOException {
searchAvailable();
Map<String, Object> doc = null;
try {
doc = fessEsClient.getDocument(fieldHelper.docIndex, fieldHelper.docType, queryRequestBuilder -> {
final TermQueryBuilder termQuery = QueryBuilders.termQuery(fieldHelper.docIdField, form.docId);
queryRequestBuilder.setQuery(termQuery);
queryRequestBuilder.addFields(queryHelper.getResponseFields());
return true;
}).get();
} catch (final Exception e) {
logger.warn("Failed to request: " + form.docId, e);
}
if (doc == null) {
throwValidationError(messages -> {
messages.addErrorsDocidNotFound(GLOBAL, form.docId);
}, () -> asHtml(path_ErrorJsp));
}
final Object urlObj = doc.get(fieldHelper.urlField);
if (urlObj == null) {
throwValidationError(messages -> {
messages.addErrorsDocumentNotFound(GLOBAL, form.docId);
}, () -> asHtml(path_ErrorJsp));
}
final String url = urlObj.toString();
if (Constants.TRUE.equals(crawlerProperties.getProperty(Constants.SEARCH_LOG_PROPERTY, Constants.TRUE))) {
final String userSessionId = userInfoHelper.getUserCode();
if (userSessionId != null) {
final SearchLogHelper searchLogHelper = ComponentUtil.getSearchLogHelper();
final ClickLog clickLog = new ClickLog();
clickLog.setUrl(url);
final long now = systemHelper.getCurrentTimeAsLong();
clickLog.setRequestedTime(now);
clickLog.setQueryRequestedTime(Long.parseLong(form.rt));
clickLog.setUserSessionId(userSessionId);
clickLog.setDocId(form.docId);
long clickCount = 0;
final Object count = doc.get(fieldHelper.clickCountField);
if (count instanceof Long) {
clickCount = ((Long) count).longValue();
}
clickLog.setClickCount(clickCount);
searchLogHelper.addClickLog(clickLog);
}
}
String hash;
if (StringUtil.isNotBlank(form.hash)) {
final String value = URLUtil.decode(form.hash, Constants.UTF_8);
final StringBuilder buf = new StringBuilder(value.length() + 100);
for (final char c : value.toCharArray()) {
if (CharUtil.isUrlChar(c) || c == ' ') {
buf.append(c);
} else {
try {
buf.append(URLEncoder.encode(String.valueOf(c), Constants.UTF_8));
} catch (final UnsupportedEncodingException e) {
// NOP
}
}
}
hash = buf.toString();
} else {
hash = StringUtil.EMPTY;
}
if (isFileSystemPath(url)) {
if (Constants.TRUE.equals(crawlerProperties.getProperty(Constants.SEARCH_FILE_PROXY_PROPERTY, Constants.TRUE))) {
final CrawlingConfigHelper crawlingConfigHelper = ComponentUtil.getCrawlingConfigHelper();
try {
crawlingConfigHelper.writeContent(doc);
return null;
} catch (final Exception e) {
logger.error("Failed to load: " + doc, e);
throwValidationError(messages -> {
messages.addErrorsNotLoadFromServer(GLOBAL, url);
}, () -> asHtml(path_ErrorJsp));
}
} else if (Constants.TRUE.equals(crawlerProperties.getProperty(Constants.SEARCH_DESKTOP_PROPERTY, Constants.FALSE))) {
final String path = url.replaceFirst("file:/+", "//");
final File file = new File(path);
if (!file.exists()) {
throwValidationError(messages -> {
messages.addErrorsNotFoundOnFileSystem(GLOBAL, url);
}, () -> asHtml(path_ErrorJsp));
}
final Desktop desktop = Desktop.getDesktop();
try {
desktop.open(file);
} catch (final Exception e) {
logger.warn("Could not open " + path, e);
throwValidationError(messages -> {
messages.addErrorsCouldNotOpenOnSystem(GLOBAL, url);
}, () -> asHtml(path_ErrorJsp));
}
LaResponseUtil.getResponse().setStatus(HttpServletResponse.SC_NO_CONTENT);
return null;
} else {
LaResponseUtil.getResponse().sendRedirect(url + hash);
}
} else {
LaResponseUtil.getResponse().sendRedirect(url + hash);
}
return null;
}
protected boolean isFileSystemPath(final String url) {
return url.startsWith("file:") || url.startsWith("smb:");
}
}

View file

@ -0,0 +1,15 @@
package org.codelibs.fess.app.web.go;
import org.codelibs.fess.app.web.RootForm;
public class GoForm extends RootForm {
private static final long serialVersionUID = 1L;
//@Required(target = "go,cache")
//@Maxbytelength(maxbytelength = 100)
public String docId;
public String rt;
public String hash;
}

View file

@ -0,0 +1,50 @@
/*
* Copyright 2009-2015 the 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.app.web.help;
import org.codelibs.fess.app.web.base.FessSearchAction;
import org.lastaflute.web.Execute;
import org.lastaflute.web.response.HtmlResponse;
public class HelpAction extends FessSearchAction {
// ===================================================================================
// Constant
//
// ===================================================================================
// Attribute
//
// ===================================================================================
// Hook
// ======
// ===================================================================================
// Search Execute
// ==============
@Execute
public HtmlResponse help(HelpForm form) {
return asHtml(path_HelpJsp).renderWith(data -> {
buildLabelParams(data, form.fields);
buildUserParams(data);
buildInitParams();
});
}
}

View file

@ -0,0 +1,8 @@
package org.codelibs.fess.app.web.help;
import org.codelibs.fess.app.web.RootForm;
public class HelpForm extends RootForm {
private static final long serialVersionUID = 1L;
}

View file

@ -0,0 +1,49 @@
/*
* Copyright 2009-2015 the 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.app.web.osdd;
import org.codelibs.fess.app.web.base.FessSearchAction;
import org.lastaflute.web.Execute;
import org.lastaflute.web.response.HtmlResponse;
import org.lastaflute.web.util.LaResponseUtil;
public class OsddAction extends FessSearchAction {
// ===================================================================================
// Constant
//
// ===================================================================================
// Attribute
//
// ===================================================================================
// Hook
// ======
// ===================================================================================
// Search Execute
// ==============
@Execute
public HtmlResponse osdd(OsddForm form) {
searchAvailable();
openSearchHelper.write(LaResponseUtil.getResponse());
return null;
}
}

View file

@ -0,0 +1,8 @@
package org.codelibs.fess.app.web.osdd;
import org.codelibs.fess.app.web.RootForm;
public class OsddForm extends RootForm {
private static final long serialVersionUID = 1L;
}

View file

@ -0,0 +1,116 @@
/*
* Copyright 2009-2015 the 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.app.web.screenshot;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.codelibs.core.io.CopyUtil;
import org.codelibs.core.io.OutputStreamUtil;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.app.web.base.FessSearchAction;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.lastaflute.web.Execute;
import org.lastaflute.web.response.HtmlResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ScreenshotAction extends FessSearchAction {
// ===================================================================================
// Constant
//
private static final Logger logger = LoggerFactory.getLogger(ScreenshotAction.class);
// ===================================================================================
// Attribute
//
@Resource
protected HttpServletResponse response;
// ===================================================================================
// Hook
// ======
// ===================================================================================
// Search Execute
// ==============
@Execute
public HtmlResponse index(final ScreenshotForm form) {
searchAvailable();
OutputStream out = null;
BufferedInputStream in = null;
try {
final Map<String, Object> doc = fessEsClient.getDocument(fieldHelper.docIndex, fieldHelper.docType, queryRequestBuilder -> {
final TermQueryBuilder termQuery = QueryBuilders.termQuery(fieldHelper.docIdField, form.docId);
queryRequestBuilder.setQuery(termQuery);
queryRequestBuilder.addFields(queryHelper.getResponseFields());
return true;
}).get();
final String url = doc == null ? null : (String) doc.get(fieldHelper.urlField);
if (StringUtil.isBlank(form.queryId) || StringUtil.isBlank(url) || screenShotManager == null) {
// 404
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return null;
}
final File screenShotFile = screenShotManager.getScreenShotFile(form.queryId, form.docId);
if (screenShotFile == null) {
// 404
response.sendError(HttpServletResponse.SC_NOT_FOUND);
screenShotManager.generate(doc);
return null;
}
response.setContentType(getImageMimeType(screenShotFile));
out = response.getOutputStream();
in = new BufferedInputStream(new FileInputStream(screenShotFile));
CopyUtil.copy(in, out);
OutputStreamUtil.flush(out);
} catch (final Exception e) {
logger.error("Failed to response: " + form.docId, e);
} finally {
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(out);
}
return null;
}
protected String getImageMimeType(final File imageFile) {
final String path = imageFile.getAbsolutePath();
if (path.endsWith(".png")) {
return "image/png";
} else if (path.endsWith(".gif")) {
return "image/gif";
} else if (path.endsWith(".jpg") || path.endsWith(".jpeg")) {
return "image/jpeg";
} else {
return "application/octet-stream";
}
}
}

View file

@ -0,0 +1,12 @@
package org.codelibs.fess.app.web.screenshot;
import org.codelibs.fess.app.web.RootForm;
public class ScreenshotForm extends RootForm {
private static final long serialVersionUID = 1L;
public String docId;
public String queryId;
}

View file

@ -0,0 +1,568 @@
/*
* Copyright 2009-2015 the 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.app.web.search;
import java.text.NumberFormat;
import java.time.Clock;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang3.StringUtils;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.InvalidQueryException;
import org.codelibs.fess.ResultOffsetExceededException;
import org.codelibs.fess.app.web.RootForm;
import org.codelibs.fess.app.web.base.FessSearchAction;
import org.codelibs.fess.client.FessEsClient.SearchConditionBuilder;
import org.codelibs.fess.es.exentity.SearchLog;
import org.codelibs.fess.es.exentity.UserInfo;
import org.codelibs.fess.helper.SearchLogHelper;
import org.codelibs.fess.util.ComponentUtil;
import org.codelibs.fess.util.QueryResponseList;
import org.dbflute.optional.OptionalEntity;
import org.lastaflute.taglib.function.LaFunctions;
import org.lastaflute.web.Execute;
import org.lastaflute.web.response.HtmlResponse;
import org.lastaflute.web.response.render.RenderData;
import org.lastaflute.web.util.LaRequestUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SearchAction extends FessSearchAction {
// ===================================================================================
// Constant
//
private static final Logger logger = LoggerFactory.getLogger(SearchAction.class);
protected static final long DEFAULT_START_COUNT = 0;
protected static final int MAX_PAGE_SIZE = 100;
private static final int DEFAULT_PAGE_SIZE = 20;
protected static final Pattern FIELD_EXTRACTION_PATTERN = Pattern.compile("^([a-zA-Z0-9_]+):.*");
// ===================================================================================
// Attribute
//
// ===================================================================================
// Hook
// ======
// ===================================================================================
// Search Execute
// ==============
@Execute
public HtmlResponse index(final SearchForm form) {
return search(form);
}
@Execute
public HtmlResponse search(SearchForm form) {
if (viewHelper.isUseSession() && StringUtil.isNotBlank(form.num)) {
normalizePageNum(form);
final HttpSession session = request.getSession();
if (session != null) {
session.setAttribute(Constants.RESULTS_PER_PAGE, form.num);
}
}
return doSearch(form);
}
@Execute
public HtmlResponse prev(SearchForm form) {
return doMove(form, -1);
}
@Execute
public HtmlResponse next(SearchForm form) {
return doMove(form, 1);
}
@Execute
public HtmlResponse move(SearchForm form) {
return doMove(form, 0);
}
protected HtmlResponse doSearch(SearchForm form) {
searchAvailable();
if (viewHelper.isUseSession()) {
final HttpSession session = request.getSession(false);
if (session != null) {
final Object resultsPerPage = session.getAttribute(Constants.RESULTS_PER_PAGE);
if (resultsPerPage != null) {
form.num = resultsPerPage.toString();
}
}
}
if (StringUtil.isBlank(form.query)) {
try {
final String optionQuery = queryHelper.buildOptionQuery(form.options);
form.query = optionQuery;
} catch (final InvalidQueryException e) {
if (logger.isDebugEnabled()) {
logger.debug(e.getMessage(), e);
}
throwValidationError(e.getMessageCode(), () -> asHtml(path_ErrorJsp));
}
}
if (StringUtil.isBlank(form.query) && form.fields.isEmpty()) {
// redirect to index page
form.query = null;
return redirect(SearchAction.class);
}
return asHtml(path_SearchJsp).renderWith(data -> {
updateSearchParams(form);
List<Map<String, String>> labelTypeItems = buildLabelParams(data, form.fields);
buildUserParams(data);
doSearchInternal(data, form);
data.register("displayQuery", getDisplayQuery(form, labelTypeItems));
data.register("pagingQuery", getPagingQuery(form));
});
}
protected HtmlResponse doMove(SearchForm form, final int move) {
int pageNum = getDefaultPageSize();
if (StringUtil.isBlank(form.num)) {
form.num = String.valueOf(getDefaultPageSize());
} else {
try {
pageNum = Integer.parseInt(form.num);
} catch (final NumberFormatException e) {
form.num = String.valueOf(getDefaultPageSize());
}
}
if (StringUtil.isBlank(form.pn)) {
form.start = String.valueOf(DEFAULT_START_COUNT);
} else {
Integer pageNumber = Integer.parseInt(form.pn);
if (pageNumber != null && pageNumber > 0) {
pageNumber = pageNumber + move;
if (pageNumber < 1) {
pageNumber = 1;
}
form.start = String.valueOf((pageNumber - 1) * pageNum);
} else {
form.start = String.valueOf(DEFAULT_START_COUNT);
}
}
return doSearch(form);
}
protected String doSearchInternal(RenderData data, SearchForm form) {
final StringBuilder queryBuf = new StringBuilder(255);
if (StringUtil.isNotBlank(form.query)) {
queryBuf.append(form.query);
}
if (StringUtil.isNotBlank(form.op)) {
request.setAttribute(Constants.DEFAULT_OPERATOR, form.op);
}
if (queryBuf.indexOf(" OR ") >= 0) {
queryBuf.insert(0, '(').append(')');
}
if (form.additional != null) {
final Set<String> fieldSet = new HashSet<String>();
for (final String additional : form.additional) {
if (StringUtil.isNotBlank(additional) && additional.length() < 1000 && !hasFieldInQuery(fieldSet, additional)) {
queryBuf.append(' ').append(additional);
}
}
}
if (!form.fields.isEmpty()) {
for (final Map.Entry<String, String[]> entry : form.fields.entrySet()) {
final List<String> valueList = new ArrayList<String>();
final String[] values = entry.getValue();
if (values != null) {
for (final String v : values) {
valueList.add(v);
}
}
if (valueList.size() == 1) {
queryBuf.append(' ').append(entry.getKey()).append(":\"").append(valueList.get(0)).append('\"');
} else if (valueList.size() > 1) {
queryBuf.append(" (");
for (int i = 0; i < valueList.size(); i++) {
if (i != 0) {
queryBuf.append(" OR");
}
queryBuf.append(' ').append(entry.getKey()).append(":\"").append(valueList.get(i)).append('\"');
}
queryBuf.append(')');
}
}
}
if (StringUtil.isNotBlank(form.sort)) {
queryBuf.append(" sort:").append(form.sort);
}
if (form.lang != null) {
final Set<String> langSet = new HashSet<>();
for (final String lang : form.lang) {
if (StringUtil.isNotBlank(lang) && lang.length() < 1000) {
if (Constants.ALL_LANGUAGES.equalsIgnoreCase(lang)) {
langSet.add(Constants.ALL_LANGUAGES);
} else {
final String normalizeLang = systemHelper.normalizeLang(lang);
if (normalizeLang != null) {
langSet.add(normalizeLang);
}
}
}
}
if (langSet.size() > 1 && langSet.contains(Constants.ALL_LANGUAGES)) {
langSet.clear();
form.lang = new String[] { Constants.ALL_LANGUAGES };
} else {
langSet.remove(Constants.ALL_LANGUAGES);
}
appendLangQuery(queryBuf, langSet);
} else if (Constants.TRUE.equals(crawlerProperties.getProperty(Constants.USE_BROWSER_LOCALE_FOR_SEARCH_PROPERTY, Constants.FALSE))) {
final Set<String> langSet = new HashSet<>();
final Enumeration<Locale> locales = request.getLocales();
if (locales != null) {
while (locales.hasMoreElements()) {
final Locale locale = locales.nextElement();
final String normalizeLang = systemHelper.normalizeLang(locale.toString());
if (normalizeLang != null) {
langSet.add(normalizeLang);
}
}
if (!langSet.isEmpty()) {
appendLangQuery(queryBuf, langSet);
}
}
}
final String query = queryBuf.toString().trim();
// init pager
if (StringUtil.isBlank(form.start)) {
form.start = String.valueOf(DEFAULT_START_COUNT);
} else {
try {
Long.parseLong(form.start);
} catch (final NumberFormatException e) {
form.start = String.valueOf(DEFAULT_START_COUNT);
}
}
if (StringUtil.isBlank(form.num)) {
form.num = String.valueOf(getDefaultPageSize());
}
normalizePageNum(form);
final int pageStart = Integer.parseInt(form.start);
final int pageNum = Integer.parseInt(form.num);
List<Map<String, Object>> documentItems = null;
try {
documentItems =
fessEsClient.getDocumentList(fieldHelper.docIndex, fieldHelper.docType,
searchRequestBuilder -> {
return SearchConditionBuilder.builder(searchRequestBuilder).query(query).offset(pageStart).size(pageNum)
.facetInfo(form.facet).geoInfo(form.geo).responseFields(queryHelper.getResponseFields()).build();
});
} catch (final InvalidQueryException e) {
if (logger.isDebugEnabled()) {
logger.debug(e.getMessage(), e);
}
throwValidationError(e.getMessageCode(), () -> asHtml(path_ErrorJsp));
} catch (final ResultOffsetExceededException e) {
if (logger.isDebugEnabled()) {
logger.debug(e.getMessage(), e);
}
throwValidationError(messages -> {
messages.addErrorsResultSizeExceeded(GLOBAL);
}, () -> asHtml(path_ErrorJsp));
}
data.register("documentItems", documentItems);
// search
final QueryResponseList queryResponseList = (QueryResponseList) documentItems;
data.register("facetResponse", queryResponseList.getFacetResponse());
data.register("moreLikeThisResponse", queryResponseList.getMoreLikeThisResponse());
final NumberFormat nf = NumberFormat.getInstance(LaRequestUtil.getRequest().getLocale());
nf.setMaximumIntegerDigits(2);
nf.setMaximumFractionDigits(2);
String execTime;
try {
execTime = nf.format((double) queryResponseList.getExecTime() / 1000);
} catch (final Exception e) {
execTime = StringUtil.EMPTY;
}
data.register("execTime", execTime);
final Clock clock = Clock.systemDefaultZone();
form.rt = Long.toString(clock.millis());
// favorite
if (favoriteSupport || screenShotManager != null) {
form.queryId = userInfoHelper.generateQueryId(query, documentItems);
if (screenShotManager != null) {
screenShotManager.storeRequest(form.queryId, documentItems);
data.register("screenShotSupport", true);
}
}
// search log
if (searchLogSupport) {
final long now = systemHelper.getCurrentTimeAsLong();
final SearchLogHelper searchLogHelper = ComponentUtil.getSearchLogHelper();
final SearchLog searchLog = new SearchLog();
String userCode = null;
if (Constants.TRUE.equals(crawlerProperties.getProperty(Constants.USER_INFO_PROPERTY, Constants.TRUE))) {
userCode = userInfoHelper.getUserCode();
if (StringUtil.isNotBlank(userCode)) {
final UserInfo userInfo = new UserInfo();
userInfo.setCode(userCode);
userInfo.setCreatedTime(now);
userInfo.setUpdatedTime(now);
searchLog.setUserInfo(OptionalEntity.of(userInfo));
}
}
searchLog.setHitCount(queryResponseList.getAllRecordCount());
searchLog.setResponseTime(Integer.valueOf((int) queryResponseList.getExecTime()));
searchLog.setSearchWord(StringUtils.abbreviate(query, 1000));
searchLog.setSearchQuery(StringUtils.abbreviate(queryResponseList.getSearchQuery(), 1000));
searchLog.setSolrQuery(StringUtils.abbreviate(queryResponseList.getSolrQuery(), 1000));
searchLog.setRequestedTime(now);
searchLog.setQueryOffset(pageStart);
searchLog.setQueryPageSize(pageNum);
searchLog.setClientIp(StringUtils.abbreviate(request.getRemoteAddr(), 50));
searchLog.setReferer(StringUtils.abbreviate(request.getHeader("referer"), 1000));
searchLog.setUserAgent(StringUtils.abbreviate(request.getHeader("user-agent"), 255));
if (userCode != null) {
searchLog.setUserSessionId(userCode);
}
final Object accessType = request.getAttribute(Constants.SEARCH_LOG_ACCESS_TYPE);
if (Constants.SEARCH_LOG_ACCESS_TYPE_JSON.equals(accessType)) {
searchLog.setAccessType(Constants.SEARCH_LOG_ACCESS_TYPE_JSON);
} else if (Constants.SEARCH_LOG_ACCESS_TYPE_XML.equals(accessType)) {
searchLog.setAccessType(Constants.SEARCH_LOG_ACCESS_TYPE_XML);
} else if (Constants.SEARCH_LOG_ACCESS_TYPE_OTHER.equals(accessType)) {
searchLog.setAccessType(Constants.SEARCH_LOG_ACCESS_TYPE_OTHER);
} else {
searchLog.setAccessType(Constants.SEARCH_LOG_ACCESS_TYPE_WEB);
}
@SuppressWarnings("unchecked")
final Map<String, List<String>> fieldLogMap = (Map<String, List<String>>) request.getAttribute(Constants.FIELD_LOGS);
if (fieldLogMap != null) {
for (final Map.Entry<String, List<String>> logEntry : fieldLogMap.entrySet()) {
for (final String value : logEntry.getValue()) {
searchLog.addSearchFieldLogValue(logEntry.getKey(), StringUtils.abbreviate(value, 1000));
}
}
}
searchLogHelper.addSearchLog(searchLog);
}
final String[] highlightQueries = (String[]) request.getAttribute(Constants.HIGHLIGHT_QUERIES);
if (highlightQueries != null) {
final StringBuilder buf = new StringBuilder(100);
for (final String q : highlightQueries) {
buf.append("&hq=").append(q);
}
data.register("appendHighlightQueries", buf.toString());
}
data.register("pageSize", queryResponseList.getPageSize());
data.register("currentPageNumber", queryResponseList.getCurrentPageNumber());
data.register("allRecordCount", queryResponseList.getAllRecordCount());
data.register("allPageCount", queryResponseList.getAllPageCount());
data.register("existNextPage", queryResponseList.isExistNextPage());
data.register("existPrevPage", queryResponseList.isExistPrevPage());
data.register("currentStartRecordNumber", queryResponseList.getCurrentStartRecordNumber());
data.register("currentEndRecordNumber", queryResponseList.getCurrentEndRecordNumber());
data.register("pageNumberList", queryResponseList.getPageNumberList());
data.register("partialResults", queryResponseList.isPartialResults());
// TODO
// data.register("queryTime", queryResponseList.get);
// data.register("searchTime", queryResponseList.get);
return query;
}
protected void appendLangQuery(final StringBuilder queryBuf, final Set<String> langSet) {
if (langSet.size() == 1) {
queryBuf.append(' ').append(fieldHelper.langField).append(':').append(langSet.iterator().next());
} else if (langSet.size() > 1) {
boolean first = true;
for (final String lang : langSet) {
if (first) {
queryBuf.append(" (");
first = false;
} else {
queryBuf.append(" OR ");
}
queryBuf.append(fieldHelper.langField).append(':').append(lang);
}
queryBuf.append(')');
}
}
protected void updateSearchParams(SearchForm form) {
if (form.facet == null) {
form.facet = queryHelper.getDefaultFacetInfo();
}
if (form.geo == null) {
form.geo = queryHelper.getDefaultGeoInfo();
}
}
protected String getDisplayQuery(RootForm form, List<Map<String, String>> labelTypeItems) {
final StringBuilder buf = new StringBuilder(100);
buf.append(form.query);
if (!form.fields.isEmpty() && form.fields.containsKey(LABEL_FIELD)) {
final String[] values = form.fields.get(LABEL_FIELD);
final List<String> labelList = new ArrayList<String>();
if (values != null) {
for (final String v : values) {
labelList.add(v);
}
}
for (final String labelTypeValue : labelList) {
for (final Map<String, String> map : labelTypeItems) {
if (map.get(Constants.ITEM_VALUE).equals(labelTypeValue)) {
buf.append(' ');
buf.append(map.get(Constants.ITEM_LABEL));
break;
}
}
}
}
return buf.toString();
}
protected void normalizePageNum(RootForm form) {
try {
final int num = Integer.parseInt(form.num);
if (num > getMaxPageSize()) {
// max page size
form.num = String.valueOf(getMaxPageSize());
} else if (num <= 0) {
form.num = String.valueOf(getDefaultPageSize());
}
} catch (final NumberFormatException e) {
form.num = String.valueOf(getDefaultPageSize());
}
}
protected int getDefaultPageSize() {
return DEFAULT_PAGE_SIZE;
}
protected int getMaxPageSize() {
final Object maxPageSize = crawlerProperties.get(Constants.SEARCH_RESULT_MAX_PAGE_SIZE);
if (maxPageSize == null) {
return MAX_PAGE_SIZE;
}
try {
return Integer.parseInt(maxPageSize.toString());
} catch (final NumberFormatException e) {
return MAX_PAGE_SIZE;
}
}
protected boolean hasFieldInQuery(final Set<String> fieldSet, final String query) {
final Matcher matcher = FIELD_EXTRACTION_PATTERN.matcher(query);
if (matcher.matches()) {
final String field = matcher.replaceFirst("$1");
if (fieldSet.contains(field)) {
return true;
}
fieldSet.add(field);
}
return false;
}
protected String getPagingQuery(SearchForm form) {
final StringBuilder buf = new StringBuilder(200);
if (form.additional != null) {
final Set<String> fieldSet = new HashSet<String>();
for (final String additional : form.additional) {
if (StringUtil.isNotBlank(additional) && additional.length() < 1000 && !hasFieldInQuery(fieldSet, additional)) {
buf.append("&additional=").append(LaFunctions.u(additional));
}
}
}
if (StringUtil.isNotBlank(form.sort)) {
buf.append("&sort=").append(LaFunctions.u(form.sort));
}
if (StringUtil.isNotBlank(form.op)) {
buf.append("&op=").append(LaFunctions.u(form.op));
}
if (form.lang != null) {
final Set<String> langSet = new HashSet<String>();
for (final String lang : form.lang) {
if (StringUtil.isNotBlank(lang) && lang.length() < 1000) {
if (Constants.ALL_LANGUAGES.equals(lang)) {
langSet.clear();
break;
}
final String normalizeLang = systemHelper.normalizeLang(lang);
if (normalizeLang != null) {
langSet.add(normalizeLang);
}
}
}
if (!langSet.isEmpty()) {
for (final String lang : langSet) {
buf.append("&lang=").append(LaFunctions.u(lang));
}
}
}
if (!form.fields.isEmpty()) {
for (final Map.Entry<String, String[]> entry : form.fields.entrySet()) {
final String[] values = entry.getValue();
if (values != null) {
for (final String v : values) {
if (StringUtil.isNotBlank(v)) {
buf.append("&fields.").append(LaFunctions.u(entry.getKey())).append('=').append(LaFunctions.u(v));
}
}
}
}
}
return buf.toString();
}
}

View file

@ -0,0 +1,84 @@
/*
* Copyright 2009-2015 the 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.app.web.search;
import org.codelibs.fess.app.web.RootForm;
import org.codelibs.fess.entity.FacetInfo;
import org.codelibs.fess.entity.GeoInfo;
import org.codelibs.fess.util.SearchParamMap;
public class SearchForm extends RootForm {
private static final long serialVersionUID = 1L;
public String additional[];
//@Maxbytelength(maxbytelength = 10)
public String op;
//@IntegerType
public String start;
//@IntegerType
public String pn;
//@Maxbytelength(maxbytelength = 1000)
public String queryId;
// response redirect
//@Required(target = "go")
//@Maxbytelength(maxbytelength = 4000)
public String rt;
//@Required(target = "go,cache")
//@Maxbytelength(maxbytelength = 100)
public String docId;
public String[] hq;
//@Maxbytelength(maxbytelength = 1000)
public String hash;
// xml/json
//@Maxbytelength(maxbytelength = 20)
public String type;
//@Maxbytelength(maxbytelength = 255)
public String callback;
public String[] fn;
// hotsearchword
//@Maxbytelength(maxbytelength = 100)
public String range;
// geo
public GeoInfo geo;
// facet
public FacetInfo facet;
// advance
public SearchParamMap options = new SearchParamMap();
}

View file

@ -16,21 +16,6 @@
package org.codelibs.fess.helper;
/*
* Copyright 2009-2014 the 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.
*/
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
@ -56,6 +41,7 @@ import org.codelibs.fess.entity.SearchQuery;
import org.codelibs.fess.entity.SearchQuery.SortField;
import org.codelibs.fess.util.QueryUtil;
import org.codelibs.fess.util.SearchParamMap;
import org.lastaflute.web.ruts.message.ActionMessages;
import org.lastaflute.web.util.LaRequestUtil;
public class QueryHelper implements Serializable {
@ -624,7 +610,8 @@ public class QueryHelper implements Serializable {
final String value1 = split[0].trim();
final String value2 = split[1].trim();
if ("*".equals(value1) && "*".equals(value2)) {
throw new InvalidQueryException("errors.invalid_query_str_range", "Invalid range: " + value);
throw new InvalidQueryException(messages -> messages.addErrorsInvalidQueryStrRange(ActionMessages.GLOBAL_PROPERTY_KEY),
"Invalid range: " + value);
}
buf.append(prefix);
buf.append(QueryUtil.escapeRangeValue(value1));
@ -632,7 +619,8 @@ public class QueryHelper implements Serializable {
buf.append(QueryUtil.escapeRangeValue(value2));
buf.append(suffix);
} else {
throw new InvalidQueryException("errors.invalid_query_str_range", "Invalid range: " + value);
throw new InvalidQueryException(messages -> messages.addErrorsInvalidQueryStrRange(ActionMessages.GLOBAL_PROPERTY_KEY),
"Invalid range: " + value);
}
}
@ -730,13 +718,17 @@ public class QueryHelper implements Serializable {
buf.append('\\');
}
if (quoted) {
throw new InvalidQueryException("errors.invalid_query_quoted", "Invalid quoted: " + query);
throw new InvalidQueryException(messages -> messages.addErrorsInvalidQueryQuoted(ActionMessages.GLOBAL_PROPERTY_KEY),
"Invalid quoted: " + query);
} else if (curlyBracket > 0) {
throw new InvalidQueryException("errors.invalid_query_curly_bracket", "Invalid curly bracket: " + query);
throw new InvalidQueryException(messages -> messages.addErrorsInvalidQueryCurlyBracket(ActionMessages.GLOBAL_PROPERTY_KEY),
"Invalid curly bracket: " + query);
} else if (squareBracket > 0) {
throw new InvalidQueryException("errors.invalid_query_square_bracket", "Invalid square bracket: " + query);
throw new InvalidQueryException(messages -> messages.addErrorsInvalidQuerySquareBracket(ActionMessages.GLOBAL_PROPERTY_KEY),
"Invalid square bracket: " + query);
} else if (parenthesis > 0) {
throw new InvalidQueryException("errors.invalid_query_parenthesis", "Invalid parenthesis: " + query);
throw new InvalidQueryException(messages -> messages.addErrorsInvalidQueryParenthesis(ActionMessages.GLOBAL_PROPERTY_KEY),
"Invalid parenthesis: " + query);
}
if (buf.length() > 0) {
addQueryPart(buf.toString(), valueList, sortFieldMap, highLightQueryList, fieldLogMap);

View file

@ -156,12 +156,14 @@
<property name="roleSeparator">","</property>
-->
</component>
<!--
<component name="screenShotManager" class="org.codelibs.fess.screenshot.ScreenShotManager">
<!--
<postConstruct name="add">
<arg>htmlScreenShotGenerator</arg>
</postConstruct>
-->
</component>
<!--
<component name="webDriver" class="org.openqa.selenium.phantomjs.PhantomJSDriver">
<arg>
<component class="org.openqa.selenium.remote.DesiredCapabilities">

View file

@ -22,9 +22,9 @@
<div class="container">
<p class="navbar-text pull-right">
<c:if test="${!empty username}">
<la:link href="/login/logout" styleClass="logout-link">
<todo:link href="/login/logout" styleClass="logout-link">
<la:message key="labels.logout" />
</la:link>
</todo:link>
</c:if>
<la:link href="/help" styleClass="help-link">
<la:message key="labels.index_help" />
@ -41,12 +41,14 @@
alt="<la:message key="labels.index_title" />" />
</h1>
<div>
<html:messages id="msg" message="true">
<%-- TODO
<la:messages id="msg" message="true">
<div class="alert-message info">
<bean:write name="msg" ignore="true" />
</div>
</html:messages>
<html:errors header="errors.front_header"
</la:messages>
--%>
<la:errors header="errors.front_header"
footer="errors.front_footer" prefix="errors.front_prefix"
suffix="errors.front_suffix" />
</div>
@ -65,7 +67,7 @@
<p class="hotSearchWordBody ellipsis">
<la:message key="labels.search_hot_search_word" />
<c:forEach var="item" items="${fe:hsw(null, 5)}">
<html:link href="search?query=${f:u(item)}${fe:facetQuery()}${fe:geoQuery()}">${f:h(item)}</html:link>
<la:link href="search?query=${f:u(item)}${fe:facetQuery()}${fe:geoQuery()}">${f:h(item)}</la:link>
</c:forEach>
</p>
</div>
@ -94,86 +96,86 @@
<label for="contentNum"><la:message
key="labels.index_num" /></label>
<div class="input">
<html:select property="num" styleId="numSearchOption"
<la:select property="num" styleId="numSearchOption"
styleClass="span4" style="display:block;">
<option value="">
<la:message key="labels.search_result_select_num" />
</option>
<html:option value="10">10</html:option>
<html:option value="20">20</html:option>
<html:option value="30">30</html:option>
<html:option value="40">40</html:option>
<html:option value="50">50</html:option>
<html:option value="100">100</html:option>
</html:select>
<la:option value="10">10</la:option>
<la:option value="20">20</la:option>
<la:option value="30">30</la:option>
<la:option value="40">40</la:option>
<la:option value="50">50</la:option>
<la:option value="100">100</la:option>
</la:select>
</div>
</div>
<div class="clearfix">
<label for="contentSort"><la:message
key="labels.index_sort" /></label>
<div class="input">
<html:select property="sort" styleId="sortSearchOption"
<la:select property="sort" styleId="sortSearchOption"
styleClass="span4" style="display:block;">
<option value="">
<la:message key="labels.search_result_select_sort" />
</option>
<html:option value="created.asc">
<la:option value="created.asc">
<la:message key="labels.search_result_sort_created_asc" />
</html:option>
<html:option value="created.desc">
</la:option>
<la:option value="created.desc">
<la:message key="labels.search_result_sort_created_desc" />
</html:option>
<html:option value="contentLength.asc">
</la:option>
<la:option value="contentLength.asc">
<la:message
key="labels.search_result_sort_contentLength_asc" />
</html:option>
<html:option value="contentLength.desc">
</la:option>
<la:option value="contentLength.desc">
<la:message
key="labels.search_result_sort_contentLength_desc" />
</html:option>
<html:option value="lastModified.asc">
</la:option>
<la:option value="lastModified.asc">
<la:message
key="labels.search_result_sort_lastModified_asc" />
</html:option>
<html:option value="lastModified.desc">
</la:option>
<la:option value="lastModified.desc">
<la:message
key="labels.search_result_sort_lastModified_desc" />
</html:option>
</la:option>
<c:if test="${searchLogSupport}">
<html:option value="clickCount_l_x_dv.asc">
<la:option value="clickCount_l_x_dv.asc">
<la:message
key="labels.search_result_sort_clickCount_asc" />
</html:option>
<html:option value="clickCount_l_x_dv.desc">
</la:option>
<la:option value="clickCount_l_x_dv.desc">
<la:message
key="labels.search_result_sort_clickCount_desc" />
</html:option>
</la:option>
</c:if><c:if test="${favoriteSupport}">
<html:option value="favoriteCount_l_x_dv.asc">
<la:option value="favoriteCount_l_x_dv.asc">
<la:message
key="labels.search_result_sort_favoriteCount_asc" />
</html:option>
<html:option value="favoriteCount_l_x_dv.desc">
</la:option>
<la:option value="favoriteCount_l_x_dv.desc">
<la:message
key="labels.search_result_sort_favoriteCount_desc" />
</html:option>
</la:option>
</c:if>
</html:select>
</la:select>
</div>
</div>
<div class="clearfix">
<label for="contentLang"><la:message
key="labels.index_lang" /></label>
<div class="input">
<html:select property="lang"
<la:select property="lang"
styleId="langSearchOption" multiple="true"
styleClass="span4">
<c:forEach var="item" items="${langItems}">
<html:option value="${f:u(item.value)}">
<la:option value="${f:u(item.value)}">
${f:h(item.label)}
</html:option>
</la:option>
</c:forEach>
</html:select>
</la:select>
</div>
</div>
<c:if test="${displayLabelTypeItems}">
@ -181,15 +183,15 @@
<label for="contentLabelType"><la:message
key="labels.index_label" /></label>
<div class="input">
<html:select property="fields.label"
<la:select property="fields.label"
styleId="labelTypeSearchOption" multiple="true"
styleClass="span4">
<c:forEach var="item" items="${labelTypeItems}">
<html:option value="${f:u(item.value)}">
<la:option value="${f:u(item.value)}">
${f:h(item.label)}
</html:option>
</la:option>
</c:forEach>
</html:select>
</la:select>
</div>
</div>
</c:if>

View file

@ -80,9 +80,9 @@
<p class="username">
<la:message key="labels.searchheader_username" arg0="${f:h(username)}" />
|
<la:link href="/login/logout" styleClass="logout-link">
<todo:link href="/login/logout" styleClass="logout-link">
<la:message key="labels.logout" />
</la:link>
</todo:link>
</p>
</c:if>
</div>