diff --git a/pom.xml b/pom.xml index 04da8997d187781229bf68ec264b1754785aadb3..6c108fc7c1b60e7c049fbc6eaf8ef841b7765caa 100644 --- a/pom.xml +++ b/pom.xml @@ -79,6 +79,34 @@ <directory>src/main/resources</directory> </resource> </resources> + <pluginManagement> + <plugins> + <plugin> + <groupId>org.eclipse.m2e</groupId> + <artifactId>lifecycle-mapping</artifactId> + <version>1.0.0</version> + <configuration> + <lifecycleMappingMetadata> + <pluginExecutions> + <pluginExecution> + <pluginExecutionFilter> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <versionRange>[0,)</versionRange> + <goals> + <goal>unpack-dependencies</goal> + </goals> + </pluginExecutionFilter> + <action> + <ignore /> <!-- to avoid warning --> + </action> + </pluginExecution> + </pluginExecutions> + </lifecycleMappingMetadata> + </configuration> + </plugin> + </plugins> + </pluginManagement> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> @@ -120,9 +148,54 @@ <directory>${project.build.directory}/${project.build.finalName}-compress</directory> </resource> </webResources> - <warSourceExcludes>WEB-INF/classes/**/*.*,WEB-INF/lib/*.jar</warSourceExcludes> + <archive> + <manifest> + <mainClass>org.docksidestage.HarborBoot</mainClass> + </manifest> + </archive> </configuration> </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>unpack-provided</id> + <phase>generate-resources</phase> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <configuration> + <includeScope>provided</includeScope> + <outputDirectory>${project.build.directory}/tomcat-lib</outputDirectory> + <includes>**/*</includes> + <overWriteReleases>true</overWriteReleases> + <overWriteSnapshots>true</overWriteSnapshots> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-assembly-plugin</artifactId> + <version>2.5.5</version> + <configuration> + <finalName>${project.artifactId}-${project.version}</finalName> + <appendAssemblyId>false</appendAssemblyId> + <outputDirectory>${project.build.directory}/releases/</outputDirectory> + <descriptors> + <descriptor>${basedir}/src/main/assemblies/package.xml</descriptor> + </descriptors> + </configuration> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>single</goal> + </goals> + </execution> + </executions> + </plugin> <plugin> <groupId>com.mycila.maven-license-plugin</groupId> <artifactId>maven-license-plugin</artifactId> @@ -433,6 +506,7 @@ <groupId>args4j</groupId> <artifactId>args4j</artifactId> <version>2.32</version> + <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.tika</groupId> diff --git a/src/main/assemblies/package.xml b/src/main/assemblies/package.xml new file mode 100644 index 0000000000000000000000000000000000000000..e50987a993019475409fe95844533992bed6126b --- /dev/null +++ b/src/main/assemblies/package.xml @@ -0,0 +1,78 @@ +<?xml version="1.0"?> +<assembly + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd"> + <id>package</id> + <formats> + <format>zip</format> + </formats> + <includeBaseDirectory>false</includeBaseDirectory> + <dependencySets> + <dependencySet> + <outputDirectory>fess-${project.version}/app</outputDirectory> + <useProjectArtifact>true</useProjectArtifact> + <unpack>true</unpack> + <includes> + <include>org.codelibs.fess:fess</include> + </includes> + </dependencySet> + </dependencySets> + <fileSets> + <!-- lib --> + <fileSet> + <directory>${project.build.directory}/tomcat-lib</directory> + <outputDirectory>fess-${project.version}/lib</outputDirectory> + </fileSet> + <fileSet> + <directory>${project.build.directory}/fess/WEB-INF/classes/org/codelibs/fess/</directory> + <includes> + <include>FessBoot**</include> + </includes> + <outputDirectory>fess-${project.version}/lib/org/codelibs/fess</outputDirectory> + </fileSet> + <!-- app --> + <fileSet> + <directory>${project.basedir}/src/main/assemblies/scripts</directory> + <fileMode>0755</fileMode> + <lineEnding>lf</lineEnding> + <includes> + <include>fess</include> + <include>fess.in.sh</include> + </includes> + <outputDirectory>fess-${project.version}/bin</outputDirectory> + </fileSet> + <!-- logs --> + <fileSet> + <directory>src/main/assemblies/scripts</directory> + <outputDirectory>fess-${project.version}/logs</outputDirectory> + <excludes> + <exclude>*</exclude> + </excludes> + <filtered>false</filtered> + </fileSet> + <!-- temp --> + <fileSet> + <directory>src/main/assemblies/scripts</directory> + <outputDirectory>fess-${project.version}/temp</outputDirectory> + <excludes> + <exclude>*</exclude> + </excludes> + <filtered>false</filtered> + </fileSet> + <!-- es/plugins --> + <fileSet> + <directory>${project.basedir}/plugins</directory> + <outputDirectory>fess-${project.version}/es/plugins</outputDirectory> + </fileSet> + <!-- es/data --> + <fileSet> + <directory>src/main/assemblies/scripts</directory> + <outputDirectory>fess-${project.version}/es/data</outputDirectory> + <excludes> + <exclude>*</exclude> + </excludes> + <filtered>false</filtered> + </fileSet> + </fileSets> +</assembly> diff --git a/src/main/assemblies/scripts/fess b/src/main/assemblies/scripts/fess new file mode 100644 index 0000000000000000000000000000000000000000..876a8f902c7b7e8a5f79a64263f24095924410bf --- /dev/null +++ b/src/main/assemblies/scripts/fess @@ -0,0 +1,191 @@ +#!/bin/sh + +# OPTIONS: +# -d daemonize (run in background) +# -p pidfile write PID to <pidfile> +# -h +# --help print command line options +# -v print fess version, then exit +# -D prop set JAVA system property +# -X prop set non-standard JAVA system property +# --prop=val +# --prop val set fess property (i.e. -Des.<prop>=<val>) + +CDPATH="" +SCRIPT="$0" + +# SCRIPT may be an arbitrarily deep series of symlinks. Loop until we have the concrete path. +while [ -h "$SCRIPT" ] ; do + ls=`ls -ld "$SCRIPT"` + # Drop everything prior to -> + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + SCRIPT="$link" + else + SCRIPT=`dirname "$SCRIPT"`/"$link" + fi +done + +# determine fess home +FESS_HOME=`dirname "$SCRIPT"`/.. + +# make ELASTICSEARCH_HOME absolute +FESS_HOME=`cd "$FESS_HOME"; pwd` + + +# If an include wasn't specified in the environment, then search for one... +if [ "x$FESS_INCLUDE" = "x" ]; then + # Locations (in order) to use when searching for an include file. + for include in /usr/share/fess/fess.in.sh \ + /usr/local/share/fess/fess.in.sh \ + /opt/fess/bin/fess.in.sh \ + ~/.fess.in.sh \ + $FESS_HOME/bin/fess.in.sh \ + "`dirname "$0"`"/fess.in.sh; do + if [ -r "$include" ]; then + . "$include" + break + fi + done +# ...otherwise, source the specified include. +elif [ -r "$FESS_INCLUDE" ]; then + . "$FESS_INCLUDE" +fi + +if [ -x "$JAVA_HOME/bin/java" ]; then + JAVA="$JAVA_HOME/bin/java" +else + JAVA=`which java` +fi + +if [ ! -x "$JAVA" ]; then + echo "Could not find any executable java binary. Please install java in your PATH or set JAVA_HOME" + exit 1 +fi + +if [ -z "$FESS_CLASSPATH" ]; then + echo "You must set the FESS_CLASSPATH var" >&2 + exit 1 +fi + +# Special-case path variables. +case `uname` in + CYGWIN*) + FESS_CLASSPATH=`cygpath -p -w "$FESS_CLASSPATH"` + FESS_HOME=`cygpath -p -w "$FESS_HOME"` + ;; +esac + +launch_service() +{ + pidpath=$1 + daemonized=$2 + props=$3 + fess_parms="-Dfess" + + if [ "x$pidpath" != "x" ]; then + fess_parms="$fess_parms -Dfess.pidfile=$pidpath" + fi + + # Make sure we dont use any predefined locale, as we check some exception message strings and rely on english language + # As those strings are created by the OS, they are dependant on the configured locale + LANG=en_US.UTF-8 + LC_ALL=en_US.UTF-8 + + export HOSTNAME=`hostname -s` + + if [ "x$daemonized" = "x" ]; then + fess_parms="$fess_parms -Dfess.foreground=yes" + exec "$JAVA" $JAVA_OPTS $FESS_JAVA_OPTS $fess_parms -Dfess.es.dir="$ES_HOME" -cp "$FESS_CLASSPATH" $props \ + org.codelibs.fess.FessBoot $FESS_OPTS + else + exec "$JAVA" $JAVA_OPTS $FESS_JAVA_OPTS $fess_parms -Dfess.es.dir="$ES_HOME" -cp "$FESS_CLASSPATH" $props \ + org.codelibs.fess.FessBoot $FESS_OPTS <&- & + return $? + fi +} + +# Print command line usage / help +usage() { + echo "Usage: $0 [-vdh] [-p pidfile] [-D prop] [-X prop]" + echo "Start fess." + echo " -d daemonize (run in background)" + echo " -p pidfile write PID to <pidfile>" + echo " -h" + echo " --help print command line options" + echo " -v print fess version, then exit" + echo " -D prop set JAVA system property" + echo " -X prop set non-standard JAVA system property" + echo " --prop=val" + echo " --prop val set fess property (i.e. -Des.<prop>=<val>)" +} + +# Parse any long getopt options and put them into properties before calling getopt below +# Be dash compatible to make sure running under ubuntu works +ARGV="" +while [ $# -gt 0 ] +do + case $1 in + --help) ARGV="$ARGV -h"; shift;; + --*=*) properties="$properties -Dfess.${1#--}" + shift 1 + ;; + --*) [ $# -le 1 ] && { + echo "Option requires an argument: '$1'." + shift + continue + } + properties="$properties -Dfess.${1#--}=$2" + shift 2 + ;; + *) ARGV="$ARGV $1" ; shift + esac +done + +# Parse any command line options. +args=`getopt vdhp:D:X: $ARGV` +eval set -- "$args" + +while true; do + case $1 in + -v) + "$JAVA" $JAVA_OPTS $FESS_JAVA_OPTS $fess_parms -cp "$FESS_CLASSPATH" $props \ + org.codelibs.fess.Version + exit 0 + ;; + -p) + pidfile="$2" + shift 2 + ;; + -d) + daemonized="yes" + shift + ;; + -h) + usage + exit 0 + ;; + -D) + properties="$properties -D$2" + shift 2 + ;; + -X) + properties="$properties -X$2" + shift 2 + ;; + --) + shift + break + ;; + *) + echo "Error parsing argument $1!" >&2 + usage + exit 1 + ;; + esac +done + +# Start up the service +launch_service "$pidfile" "$daemonized" "$properties" + +exit $? diff --git a/src/main/assemblies/scripts/fess.in.sh b/src/main/assemblies/scripts/fess.in.sh new file mode 100755 index 0000000000000000000000000000000000000000..b0babd4a37e120e70c218c50a8a840fc3a543ab2 --- /dev/null +++ b/src/main/assemblies/scripts/fess.in.sh @@ -0,0 +1,76 @@ +#!/bin/sh + +FESS_CLASSPATH=$FESS_HOME/lib + +if [ "x$FESS_MIN_MEM" = "x" ]; then + FESS_MIN_MEM=256m +fi +if [ "x$FESS_MAX_MEM" = "x" ]; then + FESS_MAX_MEM=2g +fi +if [ "x$FESS_HEAP_SIZE" != "x" ]; then + FESS_MIN_MEM=$FESS_HEAP_SIZE + FESS_MAX_MEM=$FESS_HEAP_SIZE +fi + +# min and max heap sizes should be set to the same value to avoid +# stop-the-world GC pauses during resize, and so that we can lock the +# heap in memory on startup to prevent any of it from being swapped +# out. +JAVA_OPTS="$JAVA_OPTS -Xms${FESS_MIN_MEM}" +JAVA_OPTS="$JAVA_OPTS -Xmx${FESS_MAX_MEM}" + +# new generation +if [ "x$FESS_HEAP_NEWSIZE" != "x" ]; then + JAVA_OPTS="$JAVA_OPTS -Xmn${FESS_HEAP_NEWSIZE}" +fi + +# max direct memory +if [ "x$FESS_DIRECT_SIZE" != "x" ]; then + JAVA_OPTS="$JAVA_OPTS -XX:MaxDirectMemorySize=${FESS_DIRECT_SIZE}" +fi + +# set to headless, just in case +JAVA_OPTS="$JAVA_OPTS -Djava.awt.headless=true" + +# Force the JVM to use IPv4 stack +if [ "x$FESS_USE_IPV4" != "x" ]; then + JAVA_OPTS="$JAVA_OPTS -Djava.net.preferIPv4Stack=true" +fi + +JAVA_OPTS="$JAVA_OPTS -XX:+UseParNewGC" +JAVA_OPTS="$JAVA_OPTS -XX:+UseConcMarkSweepGC" + +JAVA_OPTS="$JAVA_OPTS -XX:CMSInitiatingOccupancyFraction=75" +JAVA_OPTS="$JAVA_OPTS -XX:+UseCMSInitiatingOccupancyOnly" + +# GC logging options +if [ "x$FESS_USE_GC_LOGGING" != "x" ]; then + JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCDetails" + JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCTimeStamps" + JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCDateStamps" + JAVA_OPTS="$JAVA_OPTS -XX:+PrintClassHistogram" + JAVA_OPTS="$JAVA_OPTS -XX:+PrintTenuringDistribution" + JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCApplicationStoppedTime" + JAVA_OPTS="$JAVA_OPTS -Xloggc:/var/log/elasticsearch/gc.log" +fi + +# Causes the JVM to dump its heap on OutOfMemory. +JAVA_OPTS="$JAVA_OPTS -XX:+HeapDumpOnOutOfMemoryError" +# The path to the heap dump location, note directory must exists and have enough +# space for a full heap dump. +#JAVA_OPTS="$JAVA_OPTS -XX:HeapDumpPath=$FESS_HOME/logs/heapdump.hprof" + +# Disables explicit GC +JAVA_OPTS="$JAVA_OPTS -XX:+DisableExplicitGC" + +# Ensure UTF-8 encoding by default (e.g. filenames) +JAVA_OPTS="$JAVA_OPTS -Dfile.encoding=UTF-8" + +ES_HOME=$FESS_HOME/es +FESS_OPTS="$FESS_OPTS --context-path /fess" +FESS_OPTS="$FESS_OPTS --port 8080" +FESS_OPTS="$FESS_OPTS --webapp-path $FESS_HOME/app" +FESS_OPTS="$FESS_OPTS --webxml-path $FESS_HOME/app/WEB-INF/web.xml" +FESS_OPTS="$FESS_OPTS --temp-path $FESS_HOME/temp" + diff --git a/src/main/java/org/codelibs/fess/FessBoot.java b/src/main/java/org/codelibs/fess/FessBoot.java index 3346a0af597cef365fa595412a58b14d560d396e..60a6e2b050108b42c656f596b0e29e1b77444b75 100644 --- a/src/main/java/org/codelibs/fess/FessBoot.java +++ b/src/main/java/org/codelibs/fess/FessBoot.java @@ -1,16 +1,86 @@ package org.codelibs.fess; +import java.io.File; + import org.dbflute.tomcat.TomcatBoot; +import org.kohsuke.args4j.CmdLineException; +import org.kohsuke.args4j.CmdLineParser; +import org.kohsuke.args4j.Option; + +public class FessBoot extends TomcatBoot { + + private static final String JAVA_IO_TMPDIR = "java.io.tmpdir"; + + protected Options options; + + public FessBoot(Options options) { + super(options.port, options.contextPath); + this.options = options; + } + + @Override + protected String prepareWebappPath() { + if (options.webappPath != null) { + return options.webappPath; + } + return super.prepareWebappPath(); + } + + @Override + protected String prepareWebXmlPath() { + if (options.webXmlPath != null) { + return options.webXmlPath; + } + return super.prepareWebXmlPath(); + } -public class FessBoot { + protected String getMarkDir() { + if (options.tempPath != null) { + System.setProperty(JAVA_IO_TMPDIR, options.tempPath); + return new File(options.tempPath, "fessboot").getAbsolutePath(); + } + return new File(System.getProperty(JAVA_IO_TMPDIR), "fessboot").getAbsolutePath(); + } + + // =================================================================================== + // main + // ============ public static void main(String[] args) { - // TODO args - new TomcatBoot(8080, "/fess").useTldDetect().asDevelopment(isNoneEnv()).bootAwait(); + 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 " + FessBoot.class.getCanonicalName() + " [options...] arguments..."); + parser.printUsage(System.err); + return; + } + + new FessBoot(options).useTldDetect().asDevelopment(isNoneEnv()).bootAwait(); } private static boolean isNoneEnv() { return System.getProperty("lasta.env") == null; } + protected static class Options { + + @Option(name = "--port", metaVar = "port", usage = "Listen port") + protected int port = 8080; + + @Option(name = "--context-path", metaVar = "contextPath", usage = "Context path") + protected String contextPath = "/fess"; + + @Option(name = "--webapp-path", metaVar = "webappPath", usage = "Webapp path") + protected String webappPath = null; + + @Option(name = "--webxml-path", metaVar = "webXmlPath", usage = "web.xml path") + protected String webXmlPath = null; + + @Option(name = "--temp-path", metaVar = "tempPath", usage = "Temporary path") + protected String tempPath = null; + } } diff --git a/src/main/java/org/codelibs/fess/client/FessEsClient.java b/src/main/java/org/codelibs/fess/client/FessEsClient.java index 9389a4ef0bea4743ca9d3f0d46daf9fb264c492f..77ca352e0bedbbe749ca69ca5d21ad0569b98eb7 100644 --- a/src/main/java/org/codelibs/fess/client/FessEsClient.java +++ b/src/main/java/org/codelibs/fess/client/FessEsClient.java @@ -2,6 +2,7 @@ package org.codelibs.fess.client; import static org.codelibs.elasticsearch.runner.ElasticsearchClusterRunner.newConfigs; +import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -241,10 +242,15 @@ public class FessEsClient implements Client { config.basePath(esDir); } runner.onBuild((number, settingsBuilder) -> { + File pluginDir = new File(esDir, "plugins"); + if (pluginDir.isDirectory()) { + settingsBuilder.put("path.plugins", pluginDir.getAbsolutePath()); + } else { + settingsBuilder.put("path.plugins", new File(System.getProperty("user.dir"), "plugins").getAbsolutePath()); + } if (settings != null) { settingsBuilder.put(settings); } - settingsBuilder.put("path.plugins", System.getProperty("user.dir") + "/plugins"); }); runner.build(config); }