/* * Copyright 2012-2017 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.exec; import java.io.File; import java.io.IOException; import java.lang.management.ManagementFactory; import java.time.LocalDateTime; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; import javax.annotation.Resource; import org.codelibs.core.lang.StringUtil; import org.codelibs.core.misc.DynamicProperties; import org.codelibs.fess.Constants; import org.codelibs.fess.crawler.client.EsClient; import org.codelibs.fess.es.client.FessEsClient; import org.codelibs.fess.exception.ContainerNotAvailableException; import org.codelibs.fess.helper.SuggestHelper; import org.codelibs.fess.util.ComponentUtil; import org.kohsuke.args4j.CmdLineException; import org.kohsuke.args4j.CmdLineParser; import org.kohsuke.args4j.Option; import org.lastaflute.di.core.external.GenericExternalContext; import org.lastaflute.di.core.external.GenericExternalContextComponentDefRegister; import org.lastaflute.di.core.factory.SingletonLaContainerFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class SuggestCreator { private static final Logger logger = LoggerFactory.getLogger(Crawler.class); @Resource public FessEsClient fessEsClient; protected static class Options { @Option(name = "-s", aliases = "--sessionId", metaVar = "sessionId", usage = "Session ID") protected String sessionId; @Option(name = "-n", aliases = "--name", metaVar = "name", usage = "Name") protected String name; @Option(name = "-p", aliases = "--properties", metaVar = "properties", usage = "Properties File") protected String propertiesPath; protected Options() { // noghing } @Override public String toString() { return "Options [sessionId=" + sessionId + ", name=" + name + ", propertiesPath=" + propertiesPath + "]"; } } public static void main(final String[] args) { final Options options = new Options(); final CmdLineParser parser = new CmdLineParser(options); try { parser.parseArgument(args); } catch (final CmdLineException e) { System.err.println(e.getMessage()); System.err.println("java " + Crawler.class.getCanonicalName() + " [options...] arguments..."); parser.printUsage(System.err); return; } if (logger.isDebugEnabled()) { try { ManagementFactory.getRuntimeMXBean().getInputArguments().stream().forEach(s -> logger.debug("Parameter: " + s)); System.getProperties().entrySet().stream().forEach(e -> logger.debug("Property: " + e.getKey() + "=" + e.getValue())); System.getenv().entrySet().forEach(e -> logger.debug("Env: " + e.getKey() + "=" + e.getValue())); logger.debug("Option: " + options); } catch (final Exception e) { // ignore } } final String transportAddresses = System.getProperty(Constants.FESS_ES_TRANSPORT_ADDRESSES); if (StringUtil.isNotBlank(transportAddresses)) { System.setProperty(EsClient.TRANSPORT_ADDRESSES, transportAddresses); } final String clusterName = System.getProperty(Constants.FESS_ES_CLUSTER_NAME); if (StringUtil.isNotBlank(clusterName)) { System.setProperty(EsClient.CLUSTER_NAME, clusterName); } int exitCode; try { SingletonLaContainerFactory.setConfigPath("app.xml"); SingletonLaContainerFactory.setExternalContext(new GenericExternalContext()); SingletonLaContainerFactory.setExternalContextComponentDefRegister(new GenericExternalContextComponentDefRegister()); SingletonLaContainerFactory.init(); final Thread shutdownCallback = new Thread("ShutdownHook") { @Override public void run() { if (logger.isDebugEnabled()) { logger.debug("Destroying LaContainer.."); } destroyContainer(); } }; Runtime.getRuntime().addShutdownHook(shutdownCallback); exitCode = process(options); } catch (final ContainerNotAvailableException e) { if (logger.isDebugEnabled()) { logger.debug("Crawler is stopped.", e); } else if (logger.isInfoEnabled()) { logger.info("Crawler is stopped."); } exitCode = Constants.EXIT_FAIL; } catch (final Throwable t) { logger.error("Suggest creator does not work correctly.", t); exitCode = Constants.EXIT_FAIL; } finally { destroyContainer(); } logger.info("Finished suggestCreator."); System.exit(exitCode); } private static void destroyContainer() { synchronized (SingletonLaContainerFactory.class) { SingletonLaContainerFactory.destroy(); } } private static int process(final Options options) { final DynamicProperties systemProperties = ComponentUtil.getSystemProperties(); if (StringUtil.isNotBlank(options.propertiesPath)) { systemProperties.reload(options.propertiesPath); } else { try { final File propFile = File.createTempFile("suggest_", ".properties"); if (propFile.delete() && logger.isDebugEnabled()) { logger.debug("Deleted a temp file: " + propFile.getAbsolutePath()); } systemProperties.reload(propFile.getAbsolutePath()); propFile.deleteOnExit(); } catch (final IOException e) { logger.warn("Failed to create system properties file.", e); } } final SuggestCreator creator = ComponentUtil.getComponent(SuggestCreator.class); final LocalDateTime startTime = LocalDateTime.now(); int ret = creator.create(); if (ret == 0) { ret = creator.purge(startTime); } return ret; } private int create() { if (!ComponentUtil.getFessConfig().isSuggestDocuments()) { logger.info("Skip create suggest document."); return 0; } logger.info("Start create suggest document."); final AtomicInteger result = new AtomicInteger(1); final CountDownLatch latch = new CountDownLatch(1); final SuggestHelper suggestHelper = ComponentUtil.getSuggestHelper(); suggestHelper.indexFromDocuments(ret -> { logger.info("Success index from documents."); result.set(0); latch.countDown(); }, t -> { logger.error("Failed to update suggest index.", t); latch.countDown(); }); try { latch.await(); } catch (final InterruptedException ignore) { if (logger.isDebugEnabled()) { logger.debug("Interrupted.", ignore); } } return result.get(); } private int purge(final LocalDateTime time) { final SuggestHelper suggestHelper = ComponentUtil.getSuggestHelper(); try { suggestHelper.purgeDocumentSuggest(time); final long cleanupDay = ComponentUtil.getFessConfig().getPurgeSuggestSearchLogDay(); if (cleanupDay > 0) { suggestHelper.purgeSearchlogSuggest(time.minusDays(cleanupDay)); } return 0; } catch (final Exception e) { logger.info("Purge error.", e); return 1; } } }