Browse Source

fix #1762 add maintenance page

Shinsuke Sugaya 7 years ago
parent
commit
de3044248b

+ 144 - 0
src/main/java/org/codelibs/fess/app/web/admin/maintenance/AdminMaintenanceAction.java

@@ -0,0 +1,144 @@
+/*
+ * Copyright 2012-2018 CodeLibs Project and the Others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+package org.codelibs.fess.app.web.admin.maintenance;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import javax.annotation.Resource;
+
+import org.codelibs.fess.app.service.ScheduledJobService;
+import org.codelibs.fess.app.web.base.FessAdminAction;
+import org.codelibs.fess.es.client.FessEsClient;
+import org.codelibs.fess.es.config.exbhv.DataConfigBhv;
+import org.codelibs.fess.es.config.exbhv.DataConfigToRoleBhv;
+import org.codelibs.fess.es.config.exbhv.ElevateWordBhv;
+import org.codelibs.fess.es.config.exbhv.FileConfigBhv;
+import org.codelibs.fess.es.config.exbhv.FileConfigToRoleBhv;
+import org.codelibs.fess.es.config.exbhv.LabelToRoleBhv;
+import org.codelibs.fess.es.config.exbhv.LabelTypeBhv;
+import org.codelibs.fess.es.config.exbhv.RoleTypeBhv;
+import org.codelibs.fess.es.config.exbhv.WebConfigBhv;
+import org.codelibs.fess.es.config.exbhv.WebConfigToRoleBhv;
+import org.codelibs.fess.es.user.exbhv.RoleBhv;
+import org.elasticsearch.action.ActionListener;
+import org.lastaflute.web.Execute;
+import org.lastaflute.web.response.HtmlResponse;
+import org.lastaflute.web.ruts.process.ActionRuntime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class AdminMaintenanceAction extends FessAdminAction {
+
+    // ===================================================================================
+    //                                                                            Constant
+    //
+    private static final Logger logger = LoggerFactory.getLogger(AdminMaintenanceAction.class);
+
+    // ===================================================================================
+    //                                                                           Attribute
+    //
+    @Resource
+    protected RoleBhv roleBhv;
+
+    @Resource
+    protected RoleTypeBhv roleTypeBhv;
+
+    @Resource
+    protected LabelToRoleBhv labelToRoleBhv;
+
+    @Resource
+    protected LabelTypeBhv labelTypeBhv;
+
+    @Resource
+    protected WebConfigToRoleBhv webConfigToRoleBhv;
+
+    @Resource
+    protected WebConfigBhv webConfigBhv;
+
+    @Resource
+    protected FileConfigToRoleBhv fileConfigToRoleBhv;
+
+    @Resource
+    protected FileConfigBhv fileConfigBhv;
+
+    @Resource
+    protected DataConfigToRoleBhv dataConfigToRoleBhv;
+
+    @Resource
+    protected DataConfigBhv dataConfigBhv;
+
+    @Resource
+    protected ElevateWordBhv elevateWordBhv;
+
+    @Resource
+    protected FessEsClient fessEsClient;
+
+    @Resource
+    private ScheduledJobService scheduledJobService;
+
+    // ===================================================================================
+    //                                                                               Hook
+    //                                                                              ======
+    @Override
+    protected void setupHtmlData(final ActionRuntime runtime) {
+        super.setupHtmlData(runtime);
+        runtime.registerData("helpLink", systemHelper.getHelpLink(fessConfig.getOnlineHelpNameMaintenance()));
+    }
+
+    // ===================================================================================
+    //                                                                      Search Execute
+    //                                                                      ==============
+
+    @Execute
+    public HtmlResponse index() {
+        saveToken();
+        return asIndexHtml();
+    }
+
+    private HtmlResponse asIndexHtml() {
+        return asHtml(path_AdminMaintenance_AdminMaintenanceJsp).useForm(UpgradeForm.class);
+    }
+
+    @Execute
+    public HtmlResponse reindexOnly(final UpgradeForm form) {
+        validate(form, messages -> {}, this::asIndexHtml);
+        verifyToken(this::asIndexHtml);
+        if (startReindex(isCheckboxEnabled(form.replaceAliases), form.numberOfShardsForDoc, form.autoExpandReplicasForDoc)) {
+            saveInfo(messages -> messages.addSuccessStartedDataUpdate(GLOBAL));
+        }
+        return redirect(getClass());
+    }
+
+    private boolean startReindex(final boolean replaceAliases, final String numberOfShards, final String autoExpandReplicas) {
+        final String docIndex = "fess";
+        final String fromIndex = fessConfig.getIndexDocumentUpdateIndex();
+        final String toIndex = docIndex + "." + new SimpleDateFormat("yyyyMMddHHmm").format(new Date());
+        if (fessEsClient.createIndex(docIndex, toIndex, numberOfShards, autoExpandReplicas)) {
+            fessEsClient.admin().cluster().prepareHealth(toIndex).setWaitForYellowStatus().execute(ActionListener.wrap(response -> {
+                fessEsClient.addMapping(docIndex, "doc", toIndex);
+                fessEsClient.reindex(fromIndex, toIndex, replaceAliases);
+                if (replaceAliases && !fessEsClient.updateAlias(toIndex)) {
+                    logger.warn("Failed to update aliases for " + fromIndex + " and " + toIndex);
+                }
+            }, e -> logger.warn("Failed to reindex from " + fromIndex + " to " + toIndex, e)));
+            return true;
+        }
+        saveError(messages -> messages.addErrorsFailedToReindex(GLOBAL, fromIndex, toIndex));
+        return false;
+    }
+
+}

+ 32 - 0
src/main/java/org/codelibs/fess/app/web/admin/maintenance/UpgradeForm.java

@@ -0,0 +1,32 @@
+/*
+ * Copyright 2012-2018 CodeLibs Project and the Others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+package org.codelibs.fess.app.web.admin.maintenance;
+
+import javax.validation.constraints.Size;
+
+import org.codelibs.fess.Constants;
+import org.codelibs.fess.util.ComponentUtil;
+
+public class UpgradeForm {
+    @Size(max = 10)
+    public String replaceAliases = Constants.ON;
+
+    @Size(max = 10)
+    public String numberOfShardsForDoc = ComponentUtil.getFessConfig().getIndexNumberOfShards();
+
+    @Size(max = 10)
+    public String autoExpandReplicasForDoc = ComponentUtil.getFessConfig().getIndexAutoExpandReplicas();
+}

+ 1 - 33
src/main/java/org/codelibs/fess/app/web/admin/upgrade/AdminUpgradeAction.java

@@ -15,9 +15,6 @@
  */
  */
 package org.codelibs.fess.app.web.admin.upgrade;
 package org.codelibs.fess.app.web.admin.upgrade;
 
 
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
 import javax.annotation.Resource;
 import javax.annotation.Resource;
 
 
 import org.codelibs.fess.app.service.ScheduledJobService;
 import org.codelibs.fess.app.service.ScheduledJobService;
@@ -35,7 +32,6 @@ import org.codelibs.fess.es.config.exbhv.WebConfigBhv;
 import org.codelibs.fess.es.config.exbhv.WebConfigToRoleBhv;
 import org.codelibs.fess.es.config.exbhv.WebConfigToRoleBhv;
 import org.codelibs.fess.es.user.exbhv.RoleBhv;
 import org.codelibs.fess.es.user.exbhv.RoleBhv;
 import org.codelibs.fess.util.UpgradeUtil;
 import org.codelibs.fess.util.UpgradeUtil;
-import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.client.IndicesAdminClient;
 import org.elasticsearch.client.IndicesAdminClient;
 import org.lastaflute.web.Execute;
 import org.lastaflute.web.Execute;
 import org.lastaflute.web.response.HtmlResponse;
 import org.lastaflute.web.response.HtmlResponse;
@@ -94,7 +90,7 @@ public class AdminUpgradeAction extends FessAdminAction {
     protected FessEsClient fessEsClient;
     protected FessEsClient fessEsClient;
 
 
     @Resource
     @Resource
-    private ScheduledJobService scheduledJobService;
+    protected ScheduledJobService scheduledJobService;
 
 
     // ===================================================================================
     // ===================================================================================
     //                                                                               Hook
     //                                                                               Hook
@@ -119,16 +115,6 @@ public class AdminUpgradeAction extends FessAdminAction {
         return asHtml(path_AdminUpgrade_AdminUpgradeJsp).useForm(UpgradeForm.class);
         return asHtml(path_AdminUpgrade_AdminUpgradeJsp).useForm(UpgradeForm.class);
     }
     }
 
 
-    @Execute
-    public HtmlResponse reindexOnly(final UpgradeForm form) {
-        validate(form, messages -> {}, this::asIndexHtml);
-        verifyToken(this::asIndexHtml);
-        if (startReindex(isCheckboxEnabled(form.replaceAliases))) {
-            saveInfo(messages -> messages.addSuccessStartedDataUpdate(GLOBAL));
-        }
-        return redirect(getClass());
-    }
-
     @Execute
     @Execute
     public HtmlResponse upgradeFrom(final UpgradeForm form) {
     public HtmlResponse upgradeFrom(final UpgradeForm form) {
         validate(form, messages -> {}, this::asIndexHtml);
         validate(form, messages -> {}, this::asIndexHtml);
@@ -183,22 +169,4 @@ public class AdminUpgradeAction extends FessAdminAction {
         // nothing
         // nothing
     }
     }
 
 
-    private boolean startReindex(final boolean replaceAliases) {
-        final String docIndex = "fess";
-        final String fromIndex = fessConfig.getIndexDocumentUpdateIndex();
-        final String toIndex = docIndex + "." + new SimpleDateFormat("yyyyMMddHHmm").format(new Date());
-        if (fessEsClient.createIndex(docIndex, "doc", toIndex)) {
-            fessEsClient.admin().cluster().prepareHealth(toIndex).setWaitForYellowStatus().execute(ActionListener.wrap(response -> {
-                fessEsClient.addMapping(docIndex, "doc", toIndex);
-                fessEsClient.reindex(fromIndex, toIndex, replaceAliases);
-                if (replaceAliases && !fessEsClient.updateAlias(toIndex)) {
-                    logger.warn("Failed to update aliases for " + fromIndex + " and " + toIndex);
-                }
-            }, e -> logger.warn("Failed to reindex from " + fromIndex + " to " + toIndex, e)));
-            return true;
-        }
-        saveError(messages -> messages.addErrorsFailedToReindex(GLOBAL, fromIndex, toIndex));
-        return false;
-    }
-
 }
 }

+ 0 - 5
src/main/java/org/codelibs/fess/app/web/admin/upgrade/UpgradeForm.java

@@ -15,14 +15,9 @@
  */
  */
 package org.codelibs.fess.app.web.admin.upgrade;
 package org.codelibs.fess.app.web.admin.upgrade;
 
 
-import javax.validation.constraints.Size;
-
 import org.lastaflute.web.validation.Required;
 import org.lastaflute.web.validation.Required;
 
 
 public class UpgradeForm {
 public class UpgradeForm {
     @Required
     @Required
     public String targetVersion;
     public String targetVersion;
-
-    @Size(max = 10)
-    public String replaceAliases;
 }
 }

+ 67 - 0
src/main/java/org/codelibs/fess/crawler/util/FessCrawlerConfig.java

@@ -0,0 +1,67 @@
+/*
+ * Copyright 2012-2018 CodeLibs Project and the Others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+package org.codelibs.fess.crawler.util;
+
+import org.codelibs.fess.util.ComponentUtil;
+
+public class FessCrawlerConfig extends EsCrawlerConfig {
+
+    @Override
+    public String getQueueIndex() {
+        return ComponentUtil.getFessConfig().getIndexDocumentCrawlerIndex() + ".queue";
+    }
+
+    @Override
+    public String getDataIndex() {
+        return ComponentUtil.getFessConfig().getIndexDocumentCrawlerIndex() + ".data";
+    }
+
+    @Override
+    public String getFilterIndex() {
+        return ComponentUtil.getFessConfig().getIndexDocumentCrawlerIndex() + ".filter";
+    }
+
+    @Override
+    public int getQueueShards() {
+        return ComponentUtil.getFessConfig().getIndexDocumentCrawlerQueueNumberOfShardsAsInteger();
+    }
+
+    @Override
+    public int getDataShards() {
+        return ComponentUtil.getFessConfig().getIndexDocumentCrawlerDataNumberOfShardsAsInteger();
+    }
+
+    @Override
+    public int getFilterShards() {
+        return ComponentUtil.getFessConfig().getIndexDocumentCrawlerFilterNumberOfShardsAsInteger();
+    }
+
+    @Override
+    public int getQueueReplicas() {
+        return ComponentUtil.getFessConfig().getIndexDocumentCrawlerQueueNumberOfReplicasAsInteger();
+    }
+
+    @Override
+    public int getDataReplicas() {
+        return ComponentUtil.getFessConfig().getIndexDocumentCrawlerDataNumberOfReplicasAsInteger();
+    }
+
+    @Override
+    public int getFilterReplicas() {
+        return ComponentUtil.getFessConfig().getIndexDocumentCrawlerFilterNumberOfReplicasAsInteger();
+    }
+
+}

+ 10 - 5
src/main/java/org/codelibs/fess/es/client/FessEsClient.java

@@ -311,7 +311,7 @@ public class FessEsClient implements Client {
                     final boolean exists = existsIndex(fessConfig.getIndexDocumentUpdateIndex());
                     final boolean exists = existsIndex(fessConfig.getIndexDocumentUpdateIndex());
                     if (!exists) {
                     if (!exists) {
                         indexName = generateNewIndexName(configIndex);
                         indexName = generateNewIndexName(configIndex);
-                        createIndex(configIndex, configType, indexName);
+                        createIndex(configIndex, indexName);
                         createAlias(configIndex, indexName);
                         createAlias(configIndex, indexName);
                     } else {
                     } else {
                         client.admin().cluster().prepareHealth(fessConfig.getIndexDocumentUpdateIndex()).setWaitForYellowStatus().execute()
                         client.admin().cluster().prepareHealth(fessConfig.getIndexDocumentUpdateIndex()).setWaitForYellowStatus().execute()
@@ -341,7 +341,7 @@ public class FessEsClient implements Client {
                     }
                     }
                     final boolean exists = existsIndex(indexName);
                     final boolean exists = existsIndex(indexName);
                     if (!exists) {
                     if (!exists) {
-                        createIndex(configIndex, configType, indexName);
+                        createIndex(configIndex, indexName);
                         createAlias(configIndex, indexName);
                         createAlias(configIndex, indexName);
                     }
                     }
                 }
                 }
@@ -396,7 +396,12 @@ public class FessEsClient implements Client {
         return false;
         return false;
     }
     }
 
 
-    public boolean createIndex(final String index, final String docType, final String indexName) {
+    public boolean createIndex(final String index, final String indexName) {
+        final FessConfig fessConfig = ComponentUtil.getFessConfig();
+        return createIndex(index, indexName, fessConfig.getIndexNumberOfShards(), fessConfig.getIndexAutoExpandReplicas());
+    }
+
+    public boolean createIndex(final String index, final String indexName, final String numberOfShards, final String autoExpandReplicas) {
         final FessConfig fessConfig = ComponentUtil.getFessConfig();
         final FessConfig fessConfig = ComponentUtil.getFessConfig();
 
 
         waitForConfigSyncStatus();
         waitForConfigSyncStatus();
@@ -411,8 +416,8 @@ public class FessEsClient implements Client {
             }
             }
             source = source.replaceAll(Pattern.quote("${fess.dictionary.path}"), dictionaryPath);
             source = source.replaceAll(Pattern.quote("${fess.dictionary.path}"), dictionaryPath);
             source = source.replaceAll(Pattern.quote("${fess.index.codec}"), fessConfig.getIndexCodec());
             source = source.replaceAll(Pattern.quote("${fess.index.codec}"), fessConfig.getIndexCodec());
-            source = source.replaceAll(Pattern.quote("${fess.index.number_of_shards}"), fessConfig.getIndexNumberOfShards());
-            source = source.replaceAll(Pattern.quote("${fess.index.auto_expand_replicas}"), fessConfig.getIndexAutoExpandReplicas());
+            source = source.replaceAll(Pattern.quote("${fess.index.number_of_shards}"), numberOfShards);
+            source = source.replaceAll(Pattern.quote("${fess.index.auto_expand_replicas}"), autoExpandReplicas);
             final CreateIndexResponse indexResponse =
             final CreateIndexResponse indexResponse =
                     client.admin().indices().prepareCreate(indexName).setSource(source, XContentType.JSON).execute()
                     client.admin().indices().prepareCreate(indexName).setSource(source, XContentType.JSON).execute()
                             .actionGet(fessConfig.getIndexIndicesTimeout());
                             .actionGet(fessConfig.getIndexIndicesTimeout());

+ 3 - 0
src/main/java/org/codelibs/fess/mylasta/action/FessHtmlPath.java

@@ -255,6 +255,9 @@ public interface FessHtmlPath {
     /** The path of the HTML: /admin/log/admin_log.jsp */
     /** The path of the HTML: /admin/log/admin_log.jsp */
     HtmlNext path_AdminLog_AdminLogJsp = new HtmlNext("/admin/log/admin_log.jsp");
     HtmlNext path_AdminLog_AdminLogJsp = new HtmlNext("/admin/log/admin_log.jsp");
 
 
+    /** The path of the HTML: /admin/maintenance/admin_maintenance.jsp */
+    HtmlNext path_AdminMaintenance_AdminMaintenanceJsp = new HtmlNext("/admin/maintenance/admin_maintenance.jsp");
+
     /** The path of the HTML: /admin/pathmap/admin_pathmap.jsp */
     /** The path of the HTML: /admin/pathmap/admin_pathmap.jsp */
     HtmlNext path_AdminPathmap_AdminPathmapJsp = new HtmlNext("/admin/pathmap/admin_pathmap.jsp");
     HtmlNext path_AdminPathmap_AdminPathmapJsp = new HtmlNext("/admin/pathmap/admin_pathmap.jsp");
 
 

+ 12 - 0
src/main/java/org/codelibs/fess/mylasta/action/FessLabels.java

@@ -581,6 +581,9 @@ public class FessLabels extends UserMessages {
     /** The key of the message: Access Token */
     /** The key of the message: Access Token */
     public static final String LABELS_menu_access_token = "{labels.menu_access_token}";
     public static final String LABELS_menu_access_token = "{labels.menu_access_token}";
 
 
+    /** The key of the message: Maintenance */
+    public static final String LABELS_menu_maintenance = "{labels.menu_maintenance}";
+
     /** The key of the message: Related Content */
     /** The key of the message: Related Content */
     public static final String LABELS_menu_related_content = "{labels.menu_related_content}";
     public static final String LABELS_menu_related_content = "{labels.menu_related_content}";
 
 
@@ -2811,6 +2814,15 @@ public class FessLabels extends UserMessages {
     /** The key of the message: Access Type */
     /** The key of the message: Access Type */
     public static final String LABELS_searchlog_accesstype = "{labels.searchlog_accesstype}";
     public static final String LABELS_searchlog_accesstype = "{labels.searchlog_accesstype}";
 
 
+    /** The key of the message: Maintenance */
+    public static final String LABELS_maintenance_title_configuration = "{labels.maintenance_title_configuration}";
+
+    /** The key of the message: The number of shards */
+    public static final String LABELS_number_of_shards_for_doc = "{labels.number_of_shards_for_doc}";
+
+    /** The key of the message: Auto expand replicas */
+    public static final String LABELS_auto_expand_replicas_for_doc = "{labels.auto_expand_replicas_for_doc}";
+
     /**
     /**
      * Assert the property is not null.
      * Assert the property is not null.
      * @param property The value of the property. (NotNull)
      * @param property The value of the property. (NotNull)

+ 177 - 0
src/main/java/org/codelibs/fess/mylasta/direction/FessConfig.java

@@ -512,6 +512,24 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction
     /** The key of the configuration. e.g. .crawler */
     /** The key of the configuration. e.g. .crawler */
     String INDEX_DOCUMENT_CRAWLER_INDEX = "index.document.crawler.index";
     String INDEX_DOCUMENT_CRAWLER_INDEX = "index.document.crawler.index";
 
 
+    /** The key of the configuration. e.g. 10 */
+    String INDEX_DOCUMENT_CRAWLER_QUEUE_number_of_shards = "index.document.crawler.queue.number_of_shards";
+
+    /** The key of the configuration. e.g. 10 */
+    String INDEX_DOCUMENT_CRAWLER_DATA_number_of_shards = "index.document.crawler.data.number_of_shards";
+
+    /** The key of the configuration. e.g. 10 */
+    String INDEX_DOCUMENT_CRAWLER_FILTER_number_of_shards = "index.document.crawler.filter.number_of_shards";
+
+    /** The key of the configuration. e.g. 1 */
+    String INDEX_DOCUMENT_CRAWLER_QUEUE_number_of_replicas = "index.document.crawler.queue.number_of_replicas";
+
+    /** The key of the configuration. e.g. 1 */
+    String INDEX_DOCUMENT_CRAWLER_DATA_number_of_replicas = "index.document.crawler.data.number_of_replicas";
+
+    /** The key of the configuration. e.g. 1 */
+    String INDEX_DOCUMENT_CRAWLER_FILTER_number_of_replicas = "index.document.crawler.filter.number_of_replicas";
+
     /** The key of the configuration. e.g. .fess_config */
     /** The key of the configuration. e.g. .fess_config */
     String INDEX_CONFIG_INDEX = "index.config.index";
     String INDEX_CONFIG_INDEX = "index.config.index";
 
 
@@ -1129,6 +1147,9 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction
     /** The key of the configuration. e.g. searchlog */
     /** The key of the configuration. e.g. searchlog */
     String ONLINE_HELP_NAME_SEARCHLOG = "online.help.name.searchlog";
     String ONLINE_HELP_NAME_SEARCHLOG = "online.help.name.searchlog";
 
 
+    /** The key of the configuration. e.g. maintenance */
+    String ONLINE_HELP_NAME_MAINTENANCE = "online.help.name.maintenance";
+
     /** The key of the configuration. e.g. ja */
     /** The key of the configuration. e.g. ja */
     String ONLINE_HELP_SUPPORTED_LANGS = "online.help.supported.langs";
     String ONLINE_HELP_SUPPORTED_LANGS = "online.help.supported.langs";
 
 
@@ -2864,6 +2885,96 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction
      */
      */
     String getIndexDocumentCrawlerIndex();
     String getIndexDocumentCrawlerIndex();
 
 
+    /**
+     * Get the value for the key 'index.document.crawler.queue.number_of_shards'. <br>
+     * The value is, e.g. 10 <br>
+     * @return The value of found property. (NotNull: if not found, exception but basically no way)
+     */
+    String getIndexDocumentCrawlerQueueNumberOfShards();
+
+    /**
+     * Get the value for the key 'index.document.crawler.queue.number_of_shards' as {@link Integer}. <br>
+     * The value is, e.g. 10 <br>
+     * @return The value of found property. (NotNull: if not found, exception but basically no way)
+     * @throws NumberFormatException When the property is not integer.
+     */
+    Integer getIndexDocumentCrawlerQueueNumberOfShardsAsInteger();
+
+    /**
+     * Get the value for the key 'index.document.crawler.data.number_of_shards'. <br>
+     * The value is, e.g. 10 <br>
+     * @return The value of found property. (NotNull: if not found, exception but basically no way)
+     */
+    String getIndexDocumentCrawlerDataNumberOfShards();
+
+    /**
+     * Get the value for the key 'index.document.crawler.data.number_of_shards' as {@link Integer}. <br>
+     * The value is, e.g. 10 <br>
+     * @return The value of found property. (NotNull: if not found, exception but basically no way)
+     * @throws NumberFormatException When the property is not integer.
+     */
+    Integer getIndexDocumentCrawlerDataNumberOfShardsAsInteger();
+
+    /**
+     * Get the value for the key 'index.document.crawler.filter.number_of_shards'. <br>
+     * The value is, e.g. 10 <br>
+     * @return The value of found property. (NotNull: if not found, exception but basically no way)
+     */
+    String getIndexDocumentCrawlerFilterNumberOfShards();
+
+    /**
+     * Get the value for the key 'index.document.crawler.filter.number_of_shards' as {@link Integer}. <br>
+     * The value is, e.g. 10 <br>
+     * @return The value of found property. (NotNull: if not found, exception but basically no way)
+     * @throws NumberFormatException When the property is not integer.
+     */
+    Integer getIndexDocumentCrawlerFilterNumberOfShardsAsInteger();
+
+    /**
+     * Get the value for the key 'index.document.crawler.queue.number_of_replicas'. <br>
+     * The value is, e.g. 1 <br>
+     * @return The value of found property. (NotNull: if not found, exception but basically no way)
+     */
+    String getIndexDocumentCrawlerQueueNumberOfReplicas();
+
+    /**
+     * Get the value for the key 'index.document.crawler.queue.number_of_replicas' as {@link Integer}. <br>
+     * The value is, e.g. 1 <br>
+     * @return The value of found property. (NotNull: if not found, exception but basically no way)
+     * @throws NumberFormatException When the property is not integer.
+     */
+    Integer getIndexDocumentCrawlerQueueNumberOfReplicasAsInteger();
+
+    /**
+     * Get the value for the key 'index.document.crawler.data.number_of_replicas'. <br>
+     * The value is, e.g. 1 <br>
+     * @return The value of found property. (NotNull: if not found, exception but basically no way)
+     */
+    String getIndexDocumentCrawlerDataNumberOfReplicas();
+
+    /**
+     * Get the value for the key 'index.document.crawler.data.number_of_replicas' as {@link Integer}. <br>
+     * The value is, e.g. 1 <br>
+     * @return The value of found property. (NotNull: if not found, exception but basically no way)
+     * @throws NumberFormatException When the property is not integer.
+     */
+    Integer getIndexDocumentCrawlerDataNumberOfReplicasAsInteger();
+
+    /**
+     * Get the value for the key 'index.document.crawler.filter.number_of_replicas'. <br>
+     * The value is, e.g. 1 <br>
+     * @return The value of found property. (NotNull: if not found, exception but basically no way)
+     */
+    String getIndexDocumentCrawlerFilterNumberOfReplicas();
+
+    /**
+     * Get the value for the key 'index.document.crawler.filter.number_of_replicas' as {@link Integer}. <br>
+     * The value is, e.g. 1 <br>
+     * @return The value of found property. (NotNull: if not found, exception but basically no way)
+     * @throws NumberFormatException When the property is not integer.
+     */
+    Integer getIndexDocumentCrawlerFilterNumberOfReplicasAsInteger();
+
     /**
     /**
      * Get the value for the key 'index.config.index'. <br>
      * Get the value for the key 'index.config.index'. <br>
      * The value is, e.g. .fess_config <br>
      * The value is, e.g. .fess_config <br>
@@ -5009,6 +5120,13 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction
      */
      */
     String getOnlineHelpNameSearchlog();
     String getOnlineHelpNameSearchlog();
 
 
+    /**
+     * Get the value for the key 'online.help.name.maintenance'. <br>
+     * The value is, e.g. maintenance <br>
+     * @return The value of found property. (NotNull: if not found, exception but basically no way)
+     */
+    String getOnlineHelpNameMaintenance();
+
     /**
     /**
      * Get the value for the key 'online.help.supported.langs'. <br>
      * Get the value for the key 'online.help.supported.langs'. <br>
      * The value is, e.g. ja <br>
      * The value is, e.g. ja <br>
@@ -6653,6 +6771,54 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction
             return get(FessConfig.INDEX_DOCUMENT_CRAWLER_INDEX);
             return get(FessConfig.INDEX_DOCUMENT_CRAWLER_INDEX);
         }
         }
 
 
+        public String getIndexDocumentCrawlerQueueNumberOfShards() {
+            return get(FessConfig.INDEX_DOCUMENT_CRAWLER_QUEUE_number_of_shards);
+        }
+
+        public Integer getIndexDocumentCrawlerQueueNumberOfShardsAsInteger() {
+            return getAsInteger(FessConfig.INDEX_DOCUMENT_CRAWLER_QUEUE_number_of_shards);
+        }
+
+        public String getIndexDocumentCrawlerDataNumberOfShards() {
+            return get(FessConfig.INDEX_DOCUMENT_CRAWLER_DATA_number_of_shards);
+        }
+
+        public Integer getIndexDocumentCrawlerDataNumberOfShardsAsInteger() {
+            return getAsInteger(FessConfig.INDEX_DOCUMENT_CRAWLER_DATA_number_of_shards);
+        }
+
+        public String getIndexDocumentCrawlerFilterNumberOfShards() {
+            return get(FessConfig.INDEX_DOCUMENT_CRAWLER_FILTER_number_of_shards);
+        }
+
+        public Integer getIndexDocumentCrawlerFilterNumberOfShardsAsInteger() {
+            return getAsInteger(FessConfig.INDEX_DOCUMENT_CRAWLER_FILTER_number_of_shards);
+        }
+
+        public String getIndexDocumentCrawlerQueueNumberOfReplicas() {
+            return get(FessConfig.INDEX_DOCUMENT_CRAWLER_QUEUE_number_of_replicas);
+        }
+
+        public Integer getIndexDocumentCrawlerQueueNumberOfReplicasAsInteger() {
+            return getAsInteger(FessConfig.INDEX_DOCUMENT_CRAWLER_QUEUE_number_of_replicas);
+        }
+
+        public String getIndexDocumentCrawlerDataNumberOfReplicas() {
+            return get(FessConfig.INDEX_DOCUMENT_CRAWLER_DATA_number_of_replicas);
+        }
+
+        public Integer getIndexDocumentCrawlerDataNumberOfReplicasAsInteger() {
+            return getAsInteger(FessConfig.INDEX_DOCUMENT_CRAWLER_DATA_number_of_replicas);
+        }
+
+        public String getIndexDocumentCrawlerFilterNumberOfReplicas() {
+            return get(FessConfig.INDEX_DOCUMENT_CRAWLER_FILTER_number_of_replicas);
+        }
+
+        public Integer getIndexDocumentCrawlerFilterNumberOfReplicasAsInteger() {
+            return getAsInteger(FessConfig.INDEX_DOCUMENT_CRAWLER_FILTER_number_of_replicas);
+        }
+
         public String getIndexConfigIndex() {
         public String getIndexConfigIndex() {
             return get(FessConfig.INDEX_CONFIG_INDEX);
             return get(FessConfig.INDEX_CONFIG_INDEX);
         }
         }
@@ -7777,6 +7943,10 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction
             return get(FessConfig.ONLINE_HELP_NAME_SEARCHLOG);
             return get(FessConfig.ONLINE_HELP_NAME_SEARCHLOG);
         }
         }
 
 
+        public String getOnlineHelpNameMaintenance() {
+            return get(FessConfig.ONLINE_HELP_NAME_MAINTENANCE);
+        }
+
         public String getOnlineHelpSupportedLangs() {
         public String getOnlineHelpSupportedLangs() {
             return get(FessConfig.ONLINE_HELP_SUPPORTED_LANGS);
             return get(FessConfig.ONLINE_HELP_SUPPORTED_LANGS);
         }
         }
@@ -8424,6 +8594,12 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction
             defaultMap.put(FessConfig.INDEX_DOCUMENT_TYPE, "doc");
             defaultMap.put(FessConfig.INDEX_DOCUMENT_TYPE, "doc");
             defaultMap.put(FessConfig.INDEX_DOCUMENT_SUGGEST_INDEX, "fess");
             defaultMap.put(FessConfig.INDEX_DOCUMENT_SUGGEST_INDEX, "fess");
             defaultMap.put(FessConfig.INDEX_DOCUMENT_CRAWLER_INDEX, ".crawler");
             defaultMap.put(FessConfig.INDEX_DOCUMENT_CRAWLER_INDEX, ".crawler");
+            defaultMap.put(FessConfig.INDEX_DOCUMENT_CRAWLER_QUEUE_number_of_shards, "10");
+            defaultMap.put(FessConfig.INDEX_DOCUMENT_CRAWLER_DATA_number_of_shards, "10");
+            defaultMap.put(FessConfig.INDEX_DOCUMENT_CRAWLER_FILTER_number_of_shards, "10");
+            defaultMap.put(FessConfig.INDEX_DOCUMENT_CRAWLER_QUEUE_number_of_replicas, "1");
+            defaultMap.put(FessConfig.INDEX_DOCUMENT_CRAWLER_DATA_number_of_replicas, "1");
+            defaultMap.put(FessConfig.INDEX_DOCUMENT_CRAWLER_FILTER_number_of_replicas, "1");
             defaultMap.put(FessConfig.INDEX_CONFIG_INDEX, ".fess_config");
             defaultMap.put(FessConfig.INDEX_CONFIG_INDEX, ".fess_config");
             defaultMap.put(FessConfig.INDEX_USER_INDEX, ".fess_user");
             defaultMap.put(FessConfig.INDEX_USER_INDEX, ".fess_user");
             defaultMap.put(FessConfig.INDEX_LOG_INDEX, "fess_log");
             defaultMap.put(FessConfig.INDEX_LOG_INDEX, "fess_log");
@@ -8614,6 +8790,7 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction
             defaultMap.put(FessConfig.ONLINE_HELP_NAME_ACCESSTOKEN, "accesstoken");
             defaultMap.put(FessConfig.ONLINE_HELP_NAME_ACCESSTOKEN, "accesstoken");
             defaultMap.put(FessConfig.ONLINE_HELP_NAME_SUGGEST, "suggest");
             defaultMap.put(FessConfig.ONLINE_HELP_NAME_SUGGEST, "suggest");
             defaultMap.put(FessConfig.ONLINE_HELP_NAME_SEARCHLOG, "searchlog");
             defaultMap.put(FessConfig.ONLINE_HELP_NAME_SEARCHLOG, "searchlog");
+            defaultMap.put(FessConfig.ONLINE_HELP_NAME_MAINTENANCE, "maintenance");
             defaultMap.put(FessConfig.ONLINE_HELP_SUPPORTED_LANGS, "ja");
             defaultMap.put(FessConfig.ONLINE_HELP_SUPPORTED_LANGS, "ja");
             defaultMap.put(FessConfig.SUGGEST_POPULAR_WORD_SEED, "0");
             defaultMap.put(FessConfig.SUGGEST_POPULAR_WORD_SEED, "0");
             defaultMap.put(FessConfig.SUGGEST_POPULAR_WORD_TAGS, "");
             defaultMap.put(FessConfig.SUGGEST_POPULAR_WORD_TAGS, "");

+ 16 - 0
src/main/resources/crawler_es+crawlerConfig.xml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE components PUBLIC "-//DBFLUTE//DTD LastaDi 1.0//EN" 
+	"http://dbflute.org/meta/lastadi10.dtd">
+<components namespace="fessCrawler">
+	<component name="crawlerConfig" class="org.codelibs.fess.crawler.util.FessCrawlerConfig">
+		<property name="queueIndex">".crawler.queue"</property>
+		<property name="queueShards">5</property>
+		<property name="queueReplicas">1</property>
+		<property name="dataIndex">".crawler.data"</property>
+		<property name="dataShards">5</property>
+		<property name="dataReplicas">1</property>
+		<property name="filterIndex">".crawler.filter"</property>
+		<property name="filterShards">5</property>
+		<property name="filterReplicas">1</property>
+	</component>
+</components>

+ 0 - 8
src/main/resources/crawler_es+crawlerIndexName.xml

@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE components PUBLIC "-//DBFLUTE//DTD LastaDi 1.0//EN" 
-	"http://dbflute.org/meta/lastadi10.dtd">
-<components namespace="fessCrawler">
-	<component name="crawlerIndexName" class="java.lang.String">
-		<arg>org.codelibs.fess.util.ComponentUtil.getFessConfig().getIndexDocumentCrawlerIndex()</arg>
-	</component>
-</components>

+ 7 - 0
src/main/resources/fess_config.properties

@@ -265,6 +265,12 @@ index.document.update.index=fess.update
 index.document.type=doc
 index.document.type=doc
 index.document.suggest.index=fess
 index.document.suggest.index=fess
 index.document.crawler.index=.crawler
 index.document.crawler.index=.crawler
+index.document.crawler.queue.number_of_shards=10
+index.document.crawler.data.number_of_shards=10
+index.document.crawler.filter.number_of_shards=10
+index.document.crawler.queue.number_of_replicas=1
+index.document.crawler.data.number_of_replicas=1
+index.document.crawler.filter.number_of_replicas=1
 index.config.index=.fess_config
 index.config.index=.fess_config
 index.user.index=.fess_user
 index.user.index=.fess_user
 index.log.index=fess_log
 index.log.index=fess_log
@@ -574,6 +580,7 @@ online.help.name.esreq=esreq
 online.help.name.accesstoken=accesstoken
 online.help.name.accesstoken=accesstoken
 online.help.name.suggest=suggest
 online.help.name.suggest=suggest
 online.help.name.searchlog=searchlog
 online.help.name.searchlog=searchlog
+online.help.name.maintenance=maintenance
 
 
 online.help.supported.langs=ja
 online.help.supported.langs=ja
 
 

+ 5 - 1
src/main/resources/fess_label.properties

@@ -184,6 +184,7 @@ labels.menu_failure_url=Failure URL
 labels.menu_search_list=Search
 labels.menu_search_list=Search
 labels.menu_backup=Back Up
 labels.menu_backup=Back Up
 labels.menu_access_token=Access Token
 labels.menu_access_token=Access Token
+labels.menu_maintenance=Maintenance
 labels.menu_related_content=Related Content
 labels.menu_related_content=Related Content
 labels.menu_related_query=Related Query
 labels.menu_related_query=Related Query
 labels.sidebar.placeholder_search=Search...
 labels.sidebar.placeholder_search=Search...
@@ -926,4 +927,7 @@ labels.searchlog_configuration_button_delete=Delete
 labels.searchlog_queryid=Query ID
 labels.searchlog_queryid=Query ID
 labels.searchlog_usersessionid=User ID
 labels.searchlog_usersessionid=User ID
 labels.searchlog_requestedtime=Time
 labels.searchlog_requestedtime=Time
-labels.searchlog_accesstype=Access Type
+labels.searchlog_accesstype=Access Type
+labels.maintenance_title_configuration=Maintenance
+labels.number_of_shards_for_doc=The number of shards
+labels.auto_expand_replicas_for_doc=Auto expand replicas

+ 4 - 0
src/main/resources/fess_label_en.properties

@@ -184,6 +184,7 @@ labels.menu_failure_url=Failure URL
 labels.menu_search_list=Search
 labels.menu_search_list=Search
 labels.menu_backup=Back Up
 labels.menu_backup=Back Up
 labels.menu_access_token=Access Token
 labels.menu_access_token=Access Token
+labels.menu_maintenance=Maintenance
 labels.menu_related_content=Related Content
 labels.menu_related_content=Related Content
 labels.menu_related_query=Related Query
 labels.menu_related_query=Related Query
 labels.sidebar.placeholder_search=Search...
 labels.sidebar.placeholder_search=Search...
@@ -927,3 +928,6 @@ labels.searchlog_queryid=Query ID
 labels.searchlog_usersessionid=User ID
 labels.searchlog_usersessionid=User ID
 labels.searchlog_requestedtime=Time
 labels.searchlog_requestedtime=Time
 labels.searchlog_accesstype=Access Type
 labels.searchlog_accesstype=Access Type
+labels.maintenance_title_configuration=Maintenance
+labels.number_of_shards_for_doc=The number of shards
+labels.auto_expand_replicas_for_doc=Auto expand replicas

+ 5 - 1
src/main/resources/fess_label_ja.properties

@@ -176,6 +176,7 @@ labels.menu_failure_url=障害URL
 labels.menu_search_list=検索
 labels.menu_search_list=検索
 labels.menu_backup=バックアップ
 labels.menu_backup=バックアップ
 labels.menu_access_token=アクセストークン
 labels.menu_access_token=アクセストークン
+labels.menu_maintenance=メンテナンス
 labels.menu_related_content=関連コンテンツ
 labels.menu_related_content=関連コンテンツ
 labels.menu_related_query=関連クエリー
 labels.menu_related_query=関連クエリー
 labels.sidebar.placeholder_search=検索...
 labels.sidebar.placeholder_search=検索...
@@ -928,4 +929,7 @@ labels.searchlog_configuration_button_delete=削除
 labels.searchlog_queryid=Query ID
 labels.searchlog_queryid=Query ID
 labels.searchlog_usersessionid=User ID
 labels.searchlog_usersessionid=User ID
 labels.searchlog_requestedtime=時刻
 labels.searchlog_requestedtime=時刻
-labels.searchlog_accesstype=アクセスタイプ
+labels.searchlog_accesstype=アクセスタイプ
+labels.maintenance_title_configuration=メンテナンス
+labels.number_of_shards_for_doc=シャード数
+labels.auto_expand_replicas_for_doc=最大レプリカ数

+ 92 - 0
src/main/webapp/WEB-INF/view/admin/maintenance/admin_maintenance.jsp

@@ -0,0 +1,92 @@
+<%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%><!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<title><la:message key="labels.admin_brand_title" /> | <la:message
+		key="labels.maintenance_title_configuration" /></title>
+<jsp:include page="/WEB-INF/view/common/admin/head.jsp"></jsp:include>
+</head>
+<body class="hold-transition skin-blue sidebar-mini">
+	<div class="wrapper">
+		<jsp:include page="/WEB-INF/view/common/admin/header.jsp"></jsp:include>
+		<jsp:include page="/WEB-INF/view/common/admin/sidebar.jsp">
+			<jsp:param name="menuCategoryType" value="log" />
+			<jsp:param name="menuType" value="maintenance" />
+		</jsp:include>
+		<div class="content-wrapper">
+			<section class="content-header">
+				<h1>
+					<la:message key="labels.maintenance_title_configuration" />
+				</h1>
+			</section>
+			<section class="content">
+				<div class="row">
+					<la:form action="/admin/maintenance/">
+						<%-- Message: BEGIN --%>
+						<div class="col-md-12">
+							<la:info id="msg" message="true">
+								<div class="alert alert-info">${msg}</div>
+							</la:info>
+							<la:errors />
+						</div>
+						<%-- Message: END --%>
+						<div class="col-md-12">
+							<div class="box box-primary">
+								<div class="box-header with-border">
+									<h3 class="box-title">
+										<la:message key="labels.upgrade_reindex" />
+									</h3>
+								</div>
+								<!-- /.box-header -->
+								<div class="box-body">
+									<div class="form-group">
+										<label for="replaceAliases" class="col-sm-3 control-label"><la:message
+												key="labels.replace_aliases" /></label>
+										<div class="col-sm-9">
+											<la:errors property="replaceAliases" />
+											<div class="checkbox">
+												<label> <la:checkbox styleId="replaceAliases" property="replaceAliases" /> <la:message
+														key="labels.enabled" />
+												</label>
+											</div>
+										</div>
+									</div>
+									<div class="form-group">
+										<label for="numberOfShardsForDoc" class="col-sm-3 control-label"><la:message
+												key="labels.number_of_shards_for_doc" /></label>
+										<div class="col-sm-9">
+											<la:errors property="numberOfShardsForDoc" />
+											<la:text styleId="numberOfShardsForDoc" property="numberOfShardsForDoc" styleClass="form-control" />
+										</div>
+									</div>
+									<div class="form-group">
+										<label for="autoExpandReplicasForDoc" class="col-sm-3 control-label"><la:message
+												key="labels.auto_expand_replicas_for_doc" /></label>
+										<div class="col-sm-9">
+											<la:errors property="autoExpandReplicasForDoc" />
+											<la:text styleId="autoExpandReplicasForDoc" property="autoExpandReplicasForDoc" styleClass="form-control" />
+										</div>
+									</div>
+								</div>
+								<!-- /.box-body -->
+								<div class="box-footer">
+									<button type="submit" class="btn btn-primary"
+										name="reindexOnly"
+										value="<la:message key="labels.reindex_start_button"/>">
+										<i class="fa fa-arrow-circle-right"></i>
+										<la:message key="labels.reindex_start_button" />
+									</button>
+								</div>
+								<!-- /.box-footer -->
+							</div>
+							<!-- /.box -->
+						</div>
+					</la:form>
+				</div>
+			</section>
+		</div>
+		<jsp:include page="/WEB-INF/view/common/admin/footer.jsp"></jsp:include>
+	</div>
+	<jsp:include page="/WEB-INF/view/common/admin/foot.jsp"></jsp:include>
+</body>
+</html>

+ 0 - 35
src/main/webapp/WEB-INF/view/admin/upgrade/admin_upgrade.jsp

@@ -63,41 +63,6 @@
 							</div>
 							</div>
 							<!-- /.box -->
 							<!-- /.box -->
 						</div>
 						</div>
-						<div class="col-md-12">
-							<div class="box box-primary">
-								<div class="box-header with-border">
-									<h3 class="box-title">
-										<la:message key="labels.upgrade_reindex" />
-									</h3>
-								</div>
-								<!-- /.box-header -->
-								<div class="box-body">
-									<div class="form-group">
-										<label for="replaceAliases" class="col-sm-3 control-label"><la:message
-												key="labels.replace_aliases" /></label>
-										<div class="col-sm-9">
-											<la:errors property="replaceAliases" />
-											<div class="checkbox">
-												<label> <la:checkbox styleId="replaceAliases" property="replaceAliases" /> <la:message
-														key="labels.enabled" />
-												</label>
-											</div>
-										</div>
-									</div>
-								</div>
-								<!-- /.box-body -->
-								<div class="box-footer">
-									<button type="submit" class="btn btn-primary"
-										name="reindexOnly"
-										value="<la:message key="labels.reindex_start_button"/>">
-										<i class="fa fa-arrow-circle-right"></i>
-										<la:message key="labels.reindex_start_button" />
-									</button>
-								</div>
-								<!-- /.box-footer -->
-							</div>
-							<!-- /.box -->
-						</div>
 					</la:form>
 					</la:form>
 				</div>
 				</div>
 			</section>
 			</section>

+ 7 - 0
src/main/webapp/WEB-INF/view/common/admin/sidebar.jsp

@@ -290,6 +290,13 @@
 							<span><la:message key="labels.menu_backup" /></span>
 							<span><la:message key="labels.menu_backup" /></span>
 						</la:link></li>
 						</la:link></li>
 
 
+					<li
+						<c:if test="${param.menuType=='maintenance'}">class="active"</c:if>><la:link
+							href="/admin/maintenance/">
+							<i class='fa fa-genderless'></i>
+							<span><la:message key="labels.menu_maintenance" /></span>
+						</la:link></li>
+
 				</ul></li>
 				</ul></li>
 			<c:if test="${fe:fileExists('/WEB-INF/view/common/admin/sidebar_extra.jsp')}">
 			<c:if test="${fe:fileExists('/WEB-INF/view/common/admin/sidebar_extra.jsp')}">
 				<c:import url="/WEB-INF/view/common/admin/sidebar_extra.jsp" />
 				<c:import url="/WEB-INF/view/common/admin/sidebar_extra.jsp" />