LUCENE-5950: Move to Java 8 as minimum Java version

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1640833 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Ryan Ernst 2014-11-20 22:47:21 +00:00
parent 2b359d8354
commit 5e17f315d4
38 changed files with 136 additions and 182 deletions

View File

@ -279,7 +279,7 @@
<echo> <echo>
SUCCESS: You must right-click your project and choose Refresh. SUCCESS: You must right-click your project and choose Refresh.
Your project must use a Java 7 JRE. Your project must use a Java 8 JRE.
</echo> </echo>
</target> </target>
@ -326,7 +326,7 @@ following two XML attributes/values (adjust values according to
JDKs you have defined locally - see JDKs you have defined locally - see
File | Project Structure | Platform Settings | SDKs): File | Project Structure | Platform Settings | SDKs):
idea.jdk = project-jdk-name="1.7" project-jdk-type="JavaSDK" idea.jdk = project-jdk-name="1.8" project-jdk-type="JavaSDK"
</echo> </echo>
</target> </target>
@ -373,22 +373,13 @@ File | Project Structure | Platform Settings | SDKs):
</subant> </subant>
</target> </target>
<target name="-nightly-smoke-java8params" if="smokeTestRelease.java8"> <target name="nightly-smoke" description="Builds an unsigned release and smoke tests it"
<!-- convert path to UNIX style, so windows backslashes don't hurt escaping: --> depends="clean">
<pathconvert targetos="unix" property="-smokeTestRelease.java8params"> <fail message="To run nightly smoke, the JDK must be exactly Java 1.8, was: ${java.specification.version}">
<regexpmapper from="^(.*)$" to="--test-java8 '\1'"/>
<path location="${smokeTestRelease.java8}"/>
</pathconvert>
</target>
<target name="nightly-smoke" description="Builds an unsigned release and smoke tests it (pass '-DsmokeTestRelease.java8=/path/to/jdk1.8.0' to additionally test with Java 8)"
depends="clean,-nightly-smoke-java8params">
<fail message="To run nightly smoke, the JDK must be exactly Java 1.7, was: ${java.specification.version}">
<condition> <condition>
<not><equals arg1="${java.specification.version}" arg2="1.7"/></not> <not><equals arg1="${java.specification.version}" arg2="1.8"/></not>
</condition> </condition>
</fail> </fail>
<property name="-smokeTestRelease.java8params" value=""/><!-- (if not yet defined) -->
<exec executable="${python32.exe}" failonerror="true" taskname="python32"> <exec executable="${python32.exe}" failonerror="true" taskname="python32">
<arg value="-V"/> <arg value="-V"/>
</exec> </exec>
@ -412,7 +403,6 @@ File | Project Structure | Platform Settings | SDKs):
<!-- Tell Python not to write any bytecode cache into the filesystem: --> <!-- Tell Python not to write any bytecode cache into the filesystem: -->
<arg value="-B"/> <arg value="-B"/>
<arg file="dev-tools/scripts/smokeTestRelease.py"/> <arg file="dev-tools/scripts/smokeTestRelease.py"/>
<arg line="${-smokeTestRelease.java8params}"/>
<arg value="--revision"/> <arg value="--revision"/>
<arg value="skip"/> <arg value="skip"/>
<!-- pass ${version.base} here to emulate a real release, without appendix like "-SNAPSHOT": --> <!-- pass ${version.base} here to emulate a real release, without appendix like "-SNAPSHOT": -->

View File

@ -1,7 +1,7 @@
#Sun Sep 23 13:02:27 EDT 2012 #Sun Sep 23 13:02:27 EDT 2012
eclipse.preferences.version=1 eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.7 org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.doc.comment.support=enabled org.eclipse.jdt.core.compiler.doc.comment.support=enabled
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
@ -18,7 +18,7 @@ org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
org.eclipse.jdt.core.compiler.source=1.7 org.eclipse.jdt.core.compiler.source=1.8
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0

View File

@ -36,7 +36,7 @@ A. How to use nightly Jenkins-built Lucene/Solr Maven artifacts
B. How to generate Lucene/Solr Maven artifacts B. How to generate Lucene/Solr Maven artifacts
Prerequisites: JDK 1.7+ and Ant 1.8.2+ Prerequisites: JDK 1.8+ and Ant 1.8.2+
Run 'ant generate-maven-artifacts' to create an internal Maven Run 'ant generate-maven-artifacts' to create an internal Maven
repository, including POMs, binary .jars, source .jars, and javadoc repository, including POMs, binary .jars, source .jars, and javadoc
@ -50,7 +50,7 @@ B. How to generate Lucene/Solr Maven artifacts
C. How to deploy Maven artifacts to a repository C. How to deploy Maven artifacts to a repository
Prerequisites: JDK 1.7+ and Ant 1.8.2+ Prerequisites: JDK 1.8+ and Ant 1.8.2+
You can deploy targets for all of Lucene/Solr, only Lucene, or only Solr, You can deploy targets for all of Lucene/Solr, only Lucene, or only Solr,
as in B. above. To deploy to a Maven repository, the command is the same as in B. above. To deploy to a Maven repository, the command is the same
@ -77,7 +77,7 @@ D. How to use Maven to build Lucene/Solr
The details, followed by some example Maven commands: The details, followed by some example Maven commands:
1. Prerequisites: JDK 1.7+ and Maven 2.2.1 or 3.X 1. Prerequisites: JDK 1.8+ and Maven 2.2.1 or 3.X
2. Make sure your sources are up to date. If you checked your sources out 2. Make sure your sources are up to date. If you checked your sources out
from the Apache Subversion repository, run "svn update" from the top from the Apache Subversion repository, run "svn update" from the top

View File

@ -43,7 +43,7 @@
<vc-browse-base-url>http://svn.apache.org/viewvc/lucene/dev/trunk</vc-browse-base-url> <vc-browse-base-url>http://svn.apache.org/viewvc/lucene/dev/trunk</vc-browse-base-url>
<specification.version>@spec.version@</specification.version> <specification.version>@spec.version@</specification.version>
<maven.build.timestamp.format>yyyy-MM-dd HH:mm:ss</maven.build.timestamp.format> <maven.build.timestamp.format>yyyy-MM-dd HH:mm:ss</maven.build.timestamp.format>
<java.compat.version>1.7</java.compat.version> <java.compat.version>1.8</java.compat.version>
<jetty.version>8.1.10.v20130312</jetty.version> <jetty.version>8.1.10.v20130312</jetty.version>
<!-- RandomizedTesting library system properties --> <!-- RandomizedTesting library system properties -->

View File

@ -171,15 +171,15 @@ def checkJARMetaData(desc, jarFile, svnRevision, version):
for verify in ( for verify in (
'Specification-Vendor: The Apache Software Foundation', 'Specification-Vendor: The Apache Software Foundation',
'Implementation-Vendor: The Apache Software Foundation', 'Implementation-Vendor: The Apache Software Foundation',
# Make sure 1.7 compiler was used to build release bits: # Make sure 1.8 compiler was used to build release bits:
'X-Compile-Source-JDK: 1.7', 'X-Compile-Source-JDK: 1.8',
# Make sure 1.8 ant was used to build release bits: (this will match 1.8+) # Make sure 1.8 ant was used to build release bits: (this will match 1.8+)
'Ant-Version: Apache Ant 1.8', 'Ant-Version: Apache Ant 1.8',
# Make sure .class files are 1.7 format: # Make sure .class files are 1.8 format:
'X-Compile-Target-JDK: 1.7', 'X-Compile-Target-JDK: 1.8',
'Specification-Version: %s' % version, 'Specification-Version: %s' % version,
# Make sure the release was compiled with 1.7: # Make sure the release was compiled with 1.8:
'Created-By: 1.7'): 'Created-By: 1.8'):
if s.find(verify) == -1: if s.find(verify) == -1:
raise RuntimeError('%s is missing "%s" inside its META-INF/MANIFEST.MF' % \ raise RuntimeError('%s is missing "%s" inside its META-INF/MANIFEST.MF' % \
(desc, verify)) (desc, verify))
@ -705,19 +705,9 @@ def verifyUnpacked(java, project, artifact, unpackPath, svnRevision, version, te
raise RuntimeError('source release has WARs...') raise RuntimeError('source release has WARs...')
print(' run "ant validate"') print(' run "ant validate"')
java.run_java7('ant validate', '%s/validate.log' % unpackPath) java.run_java8('ant validate', '%s/validate.log' % unpackPath)
if project == 'lucene': if project == 'lucene':
print(" run tests w/ Java 7 and testArgs='%s'..." % testArgs)
java.run_java7('ant clean test %s' % testArgs, '%s/test.log' % unpackPath)
java.run_java7('ant jar', '%s/compile.log' % unpackPath)
testDemo(java.run_java7, isSrc, version, '1.7')
print(' generate javadocs w/ Java 7...')
java.run_java7('ant javadocs', '%s/javadocs.log' % unpackPath)
checkJavadocpathFull('%s/build/docs' % unpackPath)
if java.run_java8:
print(" run tests w/ Java 8 and testArgs='%s'..." % testArgs) print(" run tests w/ Java 8 and testArgs='%s'..." % testArgs)
java.run_java8('ant clean test %s' % testArgs, '%s/test.log' % unpackPath) java.run_java8('ant clean test %s' % testArgs, '%s/test.log' % unpackPath)
java.run_java8('ant jar', '%s/compile.log' % unpackPath) java.run_java8('ant jar', '%s/compile.log' % unpackPath)
@ -730,22 +720,10 @@ def verifyUnpacked(java, project, artifact, unpackPath, svnRevision, version, te
else: else:
os.chdir('solr') os.chdir('solr')
print(" run tests w/ Java 7 and testArgs='%s'..." % testArgs)
java.run_java7('ant clean test -Dtests.slow=false %s' % testArgs, '%s/test.log' % unpackPath)
# test javadocs
print(' generate javadocs w/ Java 7...')
java.run_java7('ant clean javadocs', '%s/javadocs.log' % unpackPath)
checkJavadocpathFull('%s/solr/build/docs' % unpackPath, False)
print(' test solr example w/ Java 7...')
java.run_java7('ant clean example', '%s/antexample.log' % unpackPath)
testSolrExample(unpackPath, java.java7_home, True)
if java.run_java8:
print(" run tests w/ Java 8 and testArgs='%s'..." % testArgs) print(" run tests w/ Java 8 and testArgs='%s'..." % testArgs)
java.run_java8('ant clean test -Dtests.slow=false %s' % testArgs, '%s/test.log' % unpackPath) java.run_java8('ant clean test -Dtests.slow=false %s' % testArgs, '%s/test.log' % unpackPath)
# test javadocs
print(' generate javadocs w/ Java 8...') print(' generate javadocs w/ Java 8...')
java.run_java8('ant clean javadocs', '%s/javadocs.log' % unpackPath) java.run_java8('ant clean javadocs', '%s/javadocs.log' % unpackPath)
checkJavadocpathFull('%s/solr/build/docs' % unpackPath, False) checkJavadocpathFull('%s/solr/build/docs' % unpackPath, False)
@ -763,8 +741,6 @@ def verifyUnpacked(java, project, artifact, unpackPath, svnRevision, version, te
checkAllJARs(os.getcwd(), project, svnRevision, version, tmpDir, baseURL) checkAllJARs(os.getcwd(), project, svnRevision, version, tmpDir, baseURL)
if project == 'lucene': if project == 'lucene':
testDemo(java.run_java7, isSrc, version, '1.7')
if java.run_java8:
testDemo(java.run_java8, isSrc, version, '1.8') testDemo(java.run_java8, isSrc, version, '1.8')
print(' check Lucene\'s javadoc JAR') print(' check Lucene\'s javadoc JAR')
@ -773,16 +749,6 @@ def verifyUnpacked(java, project, artifact, unpackPath, svnRevision, version, te
else: else:
checkSolrWAR('%s/server/webapps/solr.war' % unpackPath, svnRevision, version, tmpDir, baseURL) checkSolrWAR('%s/server/webapps/solr.war' % unpackPath, svnRevision, version, tmpDir, baseURL)
print(' copying unpacked distribution for Java 7 ...')
java7UnpackPath = '%s-java7' % unpackPath
if os.path.exists(java7UnpackPath):
shutil.rmtree(java7UnpackPath)
shutil.copytree(unpackPath, java7UnpackPath)
os.chdir(java7UnpackPath)
print(' test solr example w/ Java 7...')
testSolrExample(java7UnpackPath, java.java7_home, False)
if java.run_java8:
print(' copying unpacked distribution for Java 8 ...') print(' copying unpacked distribution for Java 8 ...')
java8UnpackPath = '%s-java8' % unpackPath java8UnpackPath = '%s-java8' % unpackPath
if os.path.exists(java8UnpackPath): if os.path.exists(java8UnpackPath):
@ -1302,16 +1268,13 @@ def make_java_config(parser, java8_home):
def run_java(cmd, logfile): def run_java(cmd, logfile):
run('%s; %s' % (cmd_prefix, cmd), logfile) run('%s; %s' % (cmd_prefix, cmd), logfile)
return run_java return run_java
java7_home = os.environ.get('JAVA_HOME') java8_home = os.environ.get('JAVA_HOME')
if java7_home is None: if java8_home is None:
parser.error('JAVA_HOME must be set') parser.error('JAVA_HOME must be set')
run_java7 = _make_runner(java7_home, '1.7')
run_java8 = None
if java8_home is not None:
run_java8 = _make_runner(java8_home, '1.8') run_java8 = _make_runner(java8_home, '1.8')
jc = namedtuple('JavaConfig', 'run_java7 java7_home run_java8 java8_home') jc = namedtuple('JavaConfig', 'run_java8 java8_home')
return jc(run_java7, java7_home, run_java8, java8_home) return jc(run_java8, java8_home)
version_re = re.compile(r'(\d+\.\d+\.\d+(-ALPHA|-BETA)?)') version_re = re.compile(r'(\d+\.\d+\.\d+(-ALPHA|-BETA)?)')
revision_re = re.compile(r'rev(\d+)') revision_re = re.compile(r'rev(\d+)')

View File

@ -1,19 +1,19 @@
Lucene Build Instructions Lucene Build Instructions
Basic steps: Basic steps:
0) Install JDK 1.7 (or greater), Ant 1.8.2+, Ivy 2.2.0 0) Install JDK 1.8 (or greater), Ant 1.8.2+, Ivy 2.2.0
1) Download Lucene from Apache and unpack it 1) Download Lucene from Apache and unpack it
2) Connect to the top-level of your Lucene installation 2) Connect to the top-level of your Lucene installation
3) Install JavaCC (optional) 3) Install JavaCC (optional)
4) Run ant 4) Run ant
Step 0) Set up your development environment (JDK 1.7 or greater, Step 0) Set up your development environment (JDK 1.8 or greater,
Ant 1.8.2+, Ivy 2.2.0) Ant 1.8.2+, Ivy 2.2.0)
We'll assume that you know how to get and set up the JDK - if you We'll assume that you know how to get and set up the JDK - if you
don't, then we suggest starting at http://java.sun.com and learning don't, then we suggest starting at http://www.oracle.com/java/ and learning
more about Java, before returning to this README. Lucene runs with more about Java, before returning to this README. Lucene runs with
JDK 1.7 and later. JDK 1.8 and later.
Like many Open Source java projects, Lucene uses Apache Ant for build Like many Open Source java projects, Lucene uses Apache Ant for build
control. Specifically, you MUST use Ant version 1.8.2+. control. Specifically, you MUST use Ant version 1.8.2+.

View File

@ -5,6 +5,11 @@ http://s.apache.org/luceneversions
======================= Lucene 6.0.0 ======================= ======================= Lucene 6.0.0 =======================
System Requirements
* LUCENE-5950: Move to Java 8 as minimum Java version.
(Ryan Ernst)
New Features New Features
API Changes API Changes

View File

@ -1,9 +1,6 @@
# System Requirements # System Requirements
Apache Lucene runs of Java 7 or greater, Java 8 is verified to be Apache Lucene runs on Java 8 or greater.
compatible and may bring some performance improvements. When using
Oracle Java 7 or OpenJDK 7, be sure to not use the GA build 147 or
update versions u40, u45 and u51! We recommend using u55 or later.
It is also recommended to always use the latest update version of your It is also recommended to always use the latest update version of your
Java VM, because bugs may affect Lucene. An overview of known JVM bugs Java VM, because bugs may affect Lucene. An overview of known JVM bugs

View File

@ -336,7 +336,7 @@
<svn-export-source source.dir="."/> <svn-export-source source.dir="."/>
<!-- Exclude javadoc package-list files under licenses incompatible with the ASL --> <!-- Exclude javadoc package-list files under licenses incompatible with the ASL -->
<delete dir="${svn.export.dir}/tools/javadoc/java7"/> <delete dir="${svn.export.dir}/tools/javadoc/java8"/>
<!-- Exclude clover license files incompatible with the ASL --> <!-- Exclude clover license files incompatible with the ASL -->
<delete dir="${svn.export.dir}/tools/clover"/> <delete dir="${svn.export.dir}/tools/clover"/>

View File

@ -162,13 +162,13 @@
<property name="javac.deprecation" value="off"/> <property name="javac.deprecation" value="off"/>
<property name="javac.debug" value="on"/> <property name="javac.debug" value="on"/>
<property name="javac.source" value="1.7"/> <property name="javac.source" value="1.8"/>
<property name="javac.target" value="1.7"/> <property name="javac.target" value="1.8"/>
<property name="javac.args" value="-Xlint -Xlint:-deprecation -Xlint:-serial -Xlint:-options"/> <property name="javac.args" value="-Xlint -Xlint:-deprecation -Xlint:-serial -Xlint:-options"/>
<property name="javadoc.link" value="http://download.oracle.com/javase/7/docs/api/"/> <property name="javadoc.link" value="http://download.oracle.com/javase/8/docs/api/"/>
<property name="javadoc.link.junit" value="http://junit.sourceforge.net/javadoc/"/> <property name="javadoc.link.junit" value="http://junit.sourceforge.net/javadoc/"/>
<property name="javadoc.packagelist.dir" location="${common.dir}/tools/javadoc"/> <property name="javadoc.packagelist.dir" location="${common.dir}/tools/javadoc"/>
<available file="${javadoc.packagelist.dir}/java7/package-list" property="javadoc.java7.packagelist.exists"/> <available file="${javadoc.packagelist.dir}/java8/package-list" property="javadoc.java8.packagelist.exists"/>
<property name="javadoc.access" value="protected"/> <property name="javadoc.access" value="protected"/>
<property name="javadoc.charset" value="utf-8"/> <property name="javadoc.charset" value="utf-8"/>
<property name="javadoc.dir" location="${common.dir}/build/docs"/> <property name="javadoc.dir" location="${common.dir}/build/docs"/>
@ -287,7 +287,7 @@
</propertyset> </propertyset>
<patternset id="lucene.local.src.package.patterns" <patternset id="lucene.local.src.package.patterns"
excludes="**/pom.xml,**/*.iml,**/*.jar,build/**,dist/**,benchmark/work/**,benchmark/temp/**,tools/javadoc/java7/**,tools/clover/**" excludes="**/pom.xml,**/*.iml,**/*.jar,build/**,dist/**,benchmark/work/**,benchmark/temp/**,tools/javadoc/java8/**,tools/clover/**"
/> />
<!-- Default exclude sources and javadoc jars from Ivy fetch to save time and bandwidth --> <!-- Default exclude sources and javadoc jars from Ivy fetch to save time and bandwidth -->
@ -304,9 +304,9 @@
</condition> </condition>
</fail> </fail>
<fail message="Minimum supported Java version is 1.7."> <fail message="Minimum supported Java version is 1.8.">
<condition> <condition>
<not><hasmethod classname="java.lang.Throwable" method="getSuppressed"/></not> <not><hasmethod classname="java.util.Arrays" method="parallelSort"/></not>
</condition> </condition>
</fail> </fail>
@ -332,7 +332,6 @@
--> -->
<condition property="build.java.runtime" value="${-cleaned.specification.version}" else="unknown"> <condition property="build.java.runtime" value="${-cleaned.specification.version}" else="unknown">
<or> <or>
<equals arg1="${-cleaned.specification.version}" arg2="1.7"/>
<equals arg1="${-cleaned.specification.version}" arg2="1.8"/> <equals arg1="${-cleaned.specification.version}" arg2="1.8"/>
<equals arg1="${-cleaned.specification.version}" arg2="1.9"/> <equals arg1="${-cleaned.specification.version}" arg2="1.9"/>
</or> </or>
@ -350,10 +349,7 @@
<contains string="${java.vm.name}" substring="openjdk" casesensitive="false"/> <contains string="${java.vm.name}" substring="openjdk" casesensitive="false"/>
<contains string="${java.vm.name}" substring="jrockit" casesensitive="false"/> <contains string="${java.vm.name}" substring="jrockit" casesensitive="false"/>
</or> </or>
<or>
<equals arg1="${build.java.runtime}" arg2="1.7"/>
<equals arg1="${build.java.runtime}" arg2="1.8"/> <equals arg1="${build.java.runtime}" arg2="1.8"/>
</or>
<!-- TODO: Fix this! For now only run this on 64bit, because jTIDY OOMs with default heap size: --> <!-- TODO: Fix this! For now only run this on 64bit, because jTIDY OOMs with default heap size: -->
<contains string="${os.arch}" substring="64"/> <contains string="${os.arch}" substring="64"/>
</and> </and>
@ -361,15 +357,10 @@
<!-- workaround for https://issues.apache.org/bugzilla/show_bug.cgi?id=53347 --> <!-- workaround for https://issues.apache.org/bugzilla/show_bug.cgi?id=53347 -->
<condition property="build.compiler" value="javac1.7"> <condition property="build.compiler" value="javac1.7">
<and>
<not>
<equals arg1="${build.java.runtime}" arg2="1.7"/>
</not>
<or> <or>
<antversion exactly="1.8.3" /> <antversion exactly="1.8.3" />
<antversion exactly="1.8.4" /> <antversion exactly="1.8.4" />
</or> </or>
</and>
</condition> </condition>
<target name="-documentation-lint-unsupported" unless="documentation-lint.supported"> <target name="-documentation-lint-unsupported" unless="documentation-lint.supported">
@ -381,12 +372,8 @@
<echo level="warning" message="WARN: Linting documentation HTML is not supported on this Java version (${build.java.runtime}) / JVM (${java.vm.name}). NOTHING DONE!"/> <echo level="warning" message="WARN: Linting documentation HTML is not supported on this Java version (${build.java.runtime}) / JVM (${java.vm.name}). NOTHING DONE!"/>
</target> </target>
<!-- for now disable doclint on JDK 8+: --> <!-- for now disable doclint: -->
<condition property="javadoc.args" value="-Xdoclint:none" else=""> <property name="javadoc.args" value="-Xdoclint:none"/>
<not>
<equals arg1="${build.java.runtime}" arg2="1.7"/>
</not>
</condition>
<!-- Import custom ANT tasks. --> <!-- Import custom ANT tasks. -->
<import file="${common.dir}/tools/custom-tasks.xml" /> <import file="${common.dir}/tools/custom-tasks.xml" />
@ -919,7 +906,7 @@
<value><!-- empty/ default encoding. --></value> <value><!-- empty/ default encoding. --></value>
<!-- <!--
Disabled because of Java 1.7 bug on Linux/ Unix: Disabled because of Java 1.8 bug on Linux/ Unix:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7181721 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7181721
<value>UTF-16</value> <value>UTF-16</value>
@ -1875,10 +1862,7 @@ ${ant.project.name}.test.dependencies=${test.classpath.list}
<!-- ECJ Javadoc linting: --> <!-- ECJ Javadoc linting: -->
<condition property="ecj-javadoc-lint.supported"> <condition property="ecj-javadoc-lint.supported">
<or>
<equals arg1="${build.java.runtime}" arg2="1.7"/>
<equals arg1="${build.java.runtime}" arg2="1.8"/> <equals arg1="${build.java.runtime}" arg2="1.8"/>
</or>
</condition> </condition>
<condition property="ecj-javadoc-lint-tests.supported"> <condition property="ecj-javadoc-lint-tests.supported">
@ -1974,7 +1958,7 @@ ${ant.project.name}.test.dependencies=${test.classpath.list}
<attribute name="overview" default="${src.dir}/overview.html"/> <attribute name="overview" default="${src.dir}/overview.html"/>
<attribute name="linksource" default="no"/> <attribute name="linksource" default="no"/>
<sequential> <sequential>
<antcall target="download-java7-javadoc-packagelist"/> <antcall target="download-java8-javadoc-packagelist"/>
<delete file="@{destdir}/stylesheet.css" failonerror="false"/> <delete file="@{destdir}/stylesheet.css" failonerror="false"/>
<copy todir="@{destdir}" file="${prettify.dir}/prettify.js" overwrite="false" /> <copy todir="@{destdir}" file="${prettify.dir}/prettify.js" overwrite="false" />
<record name="@{destdir}/log_javadoc.txt" action="start" append="no"/> <record name="@{destdir}/log_javadoc.txt" action="start" append="no"/>
@ -2004,7 +1988,7 @@ ${ant.project.name}.test.dependencies=${test.classpath.list}
<tag name="lucene.internal" <tag name="lucene.internal"
description="NOTE: This API is for internal purposes only and might change in incompatible ways in the next release."/> description="NOTE: This API is for internal purposes only and might change in incompatible ways in the next release."/>
<link offline="true" packagelistLoc="${javadoc.dir}"/> <link offline="true" packagelistLoc="${javadoc.dir}"/>
<link offline="true" href="${javadoc.link}" packagelistLoc="${javadoc.packagelist.dir}/java7"/> <link offline="true" href="${javadoc.link}" packagelistLoc="${javadoc.packagelist.dir}/java8"/>
<bottom><![CDATA[ <bottom><![CDATA[
<i>Copyright &copy; ${year} Apache Software Foundation. All Rights Reserved.</i> <i>Copyright &copy; ${year} Apache Software Foundation. All Rights Reserved.</i>
<script src='{@docRoot}/prettify.js' type='text/javascript'></script> <script src='{@docRoot}/prettify.js' type='text/javascript'></script>
@ -2144,10 +2128,10 @@ ${ant.project.name}.test.dependencies=${test.classpath.list}
</sequential> </sequential>
</macrodef> </macrodef>
<target name="download-java7-javadoc-packagelist" unless="javadoc.java7.packagelist.exists"> <target name="download-java8-javadoc-packagelist" unless="javadoc.java8.packagelist.exists">
<mkdir dir="${javadoc.packagelist.dir}/java7"/> <mkdir dir="${javadoc.packagelist.dir}/java8"/>
<get src="${javadoc.link}/package-list" <get src="${javadoc.link}/package-list"
dest="${javadoc.packagelist.dir}/java7/package-list" ignoreerrors="true"/> dest="${javadoc.packagelist.dir}/java8/package-list" ignoreerrors="true"/>
</target> </target>
<!-- VALIDATION work --> <!-- VALIDATION work -->

View File

@ -101,7 +101,7 @@ public abstract class LiveFieldValues<S,T> implements ReferenceManager.RefreshLi
if (value == missingValue) { if (value == missingValue) {
// Deleted but the deletion is not yet reflected in // Deleted but the deletion is not yet reflected in
// the reader: // the reader:
return null; return (T)null;
} else if (value != null) { } else if (value != null) {
return value; return value;
} else { } else {

View File

@ -110,7 +110,10 @@ public class SpanMultiTermQueryWrapper<Q extends MultiTermQuery> extends SpanQue
public String toString(String field) { public String toString(String field) {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("SpanMultiTermQueryWrapper("); builder.append("SpanMultiTermQueryWrapper(");
builder.append(query.toString(field)); // NOTE: query.toString must be placed in a temp local to avoid compile errors on Java 8u20
// see https://bugs.openjdk.java.net/browse/JDK-8056984?page=com.atlassian.streams.streams-jira-plugin:activity-stream-issue-tab
String queryStr = query.toString(field);
builder.append(queryStr);
builder.append(")"); builder.append(")");
if (getBoost() != 1F) { if (getBoost() != 1F) {
builder.append('^'); builder.append('^');

View File

@ -113,7 +113,9 @@ public class TestPrefixCodedTerms extends LuceneTestCase {
} }
Iterator<Term> expected = superSet.iterator(); Iterator<Term> expected = superSet.iterator();
Iterator<Term> actual = new MergedIterator<>(subs.toArray(new Iterator[0])); // NOTE: currenlty using diamond operator on MergedIterator (without explicit Term class) causes
// errors on ecj used for javadoc lint
Iterator<Term> actual = new MergedIterator<Term>(subs.toArray(new Iterator[0]));
while (actual.hasNext()) { while (actual.hasNext()) {
assertTrue(expected.hasNext()); assertTrue(expected.hasNext());
assertEquals(expected.next(), actual.next()); assertEquals(expected.next(), actual.next());

View File

@ -98,10 +98,6 @@
<property name="-grammar.relative.path" location="${grammar.path}" relative="true"/> <property name="-grammar.relative.path" location="${grammar.path}" relative="true"/>
<replace-value property="grammar.relative.path" value="${-grammar.relative.path}${file.separator}" from="${file.separator}" to="/"/> <replace-value property="grammar.relative.path" value="${-grammar.relative.path}${file.separator}" from="${file.separator}" to="/"/>
<java classname="org.antlr.Tool" fork="true" failonerror="true" classpathref="antlr.classpath" taskname="antlr"> <java classname="org.antlr.Tool" fork="true" failonerror="true" classpathref="antlr.classpath" taskname="antlr">
<!-- this is a hack because antlr generates code comments in nondeterministic order
(using HashMap somewhere it should use LinkedHashMap). This hack only works for Java 7,
Java 8 always uses murmurhash for strings and uses time-of-day as seed. -->
<sysproperty key="jdk.map.althashing.threshold" value="-1"/>
<sysproperty key="file.encoding" value="UTF-8"/> <sysproperty key="file.encoding" value="UTF-8"/>
<sysproperty key="user.language" value="en"/> <sysproperty key="user.language" value="en"/>
<sysproperty key="user.country" value="US"/> <sysproperty key="user.country" value="US"/>

View File

@ -315,7 +315,9 @@ public class TestGrouping extends LuceneTestCase {
BytesRef groupValue = mvalGd.groupValue.exists() ? ((MutableValueStr) mvalGd.groupValue).value.get() : null; BytesRef groupValue = mvalGd.groupValue.exists() ? ((MutableValueStr) mvalGd.groupValue).value.get() : null;
groups.add(new GroupDocs<>(Float.NaN, mvalGd.maxScore, mvalGd.totalHits, mvalGd.scoreDocs, groupValue, mvalGd.groupSortValues)); groups.add(new GroupDocs<>(Float.NaN, mvalGd.maxScore, mvalGd.totalHits, mvalGd.scoreDocs, groupValue, mvalGd.groupSortValues));
} }
return new TopGroups<>(mvalTopGroups.groupSort, mvalTopGroups.withinGroupSort, mvalTopGroups.totalHitCount, mvalTopGroups.totalGroupedHitCount, groups.toArray(new GroupDocs[groups.size()]), Float.NaN); // NOTE: currenlty using diamond operator on TopGroups (without explicit Term class) causes
// errors on ecj used for javadoc lint
return new TopGroups<BytesRef>(mvalTopGroups.groupSort, mvalTopGroups.withinGroupSort, mvalTopGroups.totalHitCount, mvalTopGroups.totalGroupedHitCount, groups.toArray(new GroupDocs[groups.size()]), Float.NaN);
} }
fail(); fail();
return null; return null;

View File

@ -4,9 +4,9 @@ org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonN
org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
org.eclipse.jdt.core.compiler.annotation.nonnullisdefault=disabled org.eclipse.jdt.core.compiler.annotation.nonnullisdefault=disabled
org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.7 org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.doc.comment.support=enabled org.eclipse.jdt.core.compiler.doc.comment.support=enabled
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=ignore org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=ignore
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
@ -93,4 +93,4 @@ org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disa
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=ignore org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=ignore
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=ignore org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=ignore
org.eclipse.jdt.core.compiler.source=1.7 org.eclipse.jdt.core.compiler.source=1.8

View File

@ -44,15 +44,22 @@ java.security.spec
java.sql java.sql
java.text java.text
java.text.spi java.text.spi
java.time
java.time.chrono
java.time.format
java.time.temporal
java.time.zone
java.util java.util
java.util.concurrent java.util.concurrent
java.util.concurrent.atomic java.util.concurrent.atomic
java.util.concurrent.locks java.util.concurrent.locks
java.util.function
java.util.jar java.util.jar
java.util.logging java.util.logging
java.util.prefs java.util.prefs
java.util.regex java.util.regex
java.util.spi java.util.spi
java.util.stream
java.util.zip java.util.zip
javax.accessibility javax.accessibility
javax.activation javax.activation
@ -204,6 +211,7 @@ org.w3c.dom
org.w3c.dom.bootstrap org.w3c.dom.bootstrap
org.w3c.dom.events org.w3c.dom.events
org.w3c.dom.ls org.w3c.dom.ls
org.w3c.dom.views
org.xml.sax org.xml.sax
org.xml.sax.ext org.xml.sax.ext
org.xml.sax.helpers org.xml.sax.helpers

View File

@ -29,6 +29,11 @@ Velocity 1.7 and Velocity Tools 2.0
Apache UIMA 2.3.1 Apache UIMA 2.3.1
Apache ZooKeeper 3.4.6 Apache ZooKeeper 3.4.6
System Requirements
----------------------
* LUCENE-5950: Move to Java 8 as minimum Java version.
(Ryan Ernst)
Upgrading from Solr 5.x Upgrading from Solr 5.x
---------------------- ----------------------

View File

@ -111,10 +111,10 @@ docs/index.html
Instructions for Building Apache Solr from Source Instructions for Building Apache Solr from Source
------------------------------------------------- -------------------------------------------------
1. Download the Java SE 7 JDK (Java Development Kit) or later from http://java.sun.com/ 1. Download the Java SE 8 JDK (Java Development Kit) or later from http://www.oracle.com/java/
You will need the JDK installed, and the $JAVA_HOME/bin (Windows: %JAVA_HOME%\bin) You will need the JDK installed, and the $JAVA_HOME/bin (Windows: %JAVA_HOME%\bin)
folder included on your command path. To test this, issue a "java -version" command folder included on your command path. To test this, issue a "java -version" command
from your shell (command prompt) and verify that the Java version is 1.7 or later. from your shell (command prompt) and verify that the Java version is 1.8 or later.
2. Download the Apache Ant binary distribution (1.8.2+) from 2. Download the Apache Ant binary distribution (1.8.2+) from
http://ant.apache.org/ You will need Ant installed and the $ANT_HOME/bin (Windows: http://ant.apache.org/ You will need Ant installed and the $ANT_HOME/bin (Windows:

View File

@ -1,9 +1,6 @@
# System Requirements # System Requirements
Apache Solr runs of Java 7 or greater, Java 8 is verified to be Apache Solr runs of Java 8 or greater.
compatible and may bring some performance improvements. When using
Oracle Java 7 or OpenJDK 7, be sure to not use the GA build 147 or
update versions u40, u45 and u51! We recommend using u55 or later.
It is also recommended to always use the latest update version of your It is also recommended to always use the latest update version of your
Java VM, because bugs may affect Solr. An overview of known JVM bugs Java VM, because bugs may affect Solr. An overview of known JVM bugs

View File

@ -1052,11 +1052,11 @@ IF "%FIRST_ARG%"=="start" (
) )
:need_java_home :need_java_home
@echo Please set the JAVA_HOME environment variable to the path where you installed Java 1.7+ @echo Please set the JAVA_HOME environment variable to the path where you installed Java 1.8+
goto done goto done
:need_java_vers :need_java_vers
@echo Java 1.7 or later is required to run Solr. @echo Java 1.8 or later is required to run Solr.
goto done goto done
:err :err

View File

@ -380,7 +380,7 @@
<svn-export-source source.dir=".."/> <svn-export-source source.dir=".."/>
<!-- Exclude javadoc package-list files under licenses incompatible with the ASL --> <!-- Exclude javadoc package-list files under licenses incompatible with the ASL -->
<delete dir="${svn.export.dir}/lucene/tools/javadoc/java7"/> <delete dir="${svn.export.dir}/lucene/tools/javadoc/java8"/>
<!-- Exclude clover license files incompatible with the ASL --> <!-- Exclude clover license files incompatible with the ASL -->
<delete dir="${svn.export.dir}/lucene/tools/clover"/> <delete dir="${svn.export.dir}/lucene/tools/clover"/>

View File

@ -25,9 +25,9 @@
<property name="Name" value="Solr" /> <property name="Name" value="Solr" />
<!-- solr uses 1.7 --> <!-- solr uses 1.8 -->
<property name="javac.source" value="1.7"/> <property name="javac.source" value="1.8"/>
<property name="javac.target" value="1.7"/> <property name="javac.target" value="1.8"/>
<property name="javac.args" value=""/> <property name="javac.args" value=""/>
<property name="dest" location="${common-solr.dir}/build" /> <property name="dest" location="${common-solr.dir}/build" />

View File

@ -244,7 +244,7 @@
See the Java Regular Expression documentation for more See the Java Regular Expression documentation for more
infomation on pattern and replacement string syntax. infomation on pattern and replacement string syntax.
http://docs.oracle.com/javase/7/docs/api/java/util/regex/package-summary.html http://docs.oracle.com/javase/8/docs/api/java/util/regex/package-summary.html
--> -->
<filter class="solr.PatternReplaceFilterFactory" <filter class="solr.PatternReplaceFilterFactory"
pattern="([^a-z])" replacement="" replace="all" pattern="([^a-z])" replacement="" replace="all"

View File

@ -229,7 +229,7 @@
See the Java Regular Expression documentation for more See the Java Regular Expression documentation for more
infomation on pattern and replacement string syntax. infomation on pattern and replacement string syntax.
http://docs.oracle.com/javase/7/docs/api/java/util/regex/package-summary.html http://docs.oracle.com/javase/8/docs/api/java/util/regex/package-summary.html
--> -->
<filter class="solr.PatternReplaceFilterFactory" <filter class="solr.PatternReplaceFilterFactory"
pattern="([^a-z])" replacement="" replace="all" pattern="([^a-z])" replacement="" replace="all"

View File

@ -361,7 +361,7 @@
documentation for more information on pattern and replacement documentation for more information on pattern and replacement
string syntax. string syntax.
http://docs.oracle.com/javase/7/docs/api/java/util/regex/package-summary.html http://docs.oracle.com/javase/8/docs/api/java/util/regex/package-summary.html
--> -->
<filter class="solr.PatternReplaceFilterFactory" pattern="([^a-z])" <filter class="solr.PatternReplaceFilterFactory" pattern="([^a-z])"
replacement="" replace="all" /> replacement="" replace="all" />

View File

@ -357,7 +357,7 @@
documentation for more information on pattern and replacement documentation for more information on pattern and replacement
string syntax. string syntax.
http://docs.oracle.com/javase/7/docs/api/java/util/regex/package-summary.html http://docs.oracle.com/javase/8/docs/api/java/util/regex/package-summary.html
--> -->
<filter class="solr.PatternReplaceFilterFactory" pattern="([^a-z])" <filter class="solr.PatternReplaceFilterFactory" pattern="([^a-z])"
replacement="" replace="all" /> replacement="" replace="all" />

View File

@ -59,8 +59,9 @@ public final class MaxFieldValueUpdateProcessorFactory extends FieldValueSubsetU
public Collection pickSubset(Collection values) { public Collection pickSubset(Collection values) {
Collection result = values; Collection result = values;
try { try {
result = Collections.singletonList // NOTE: max must be put into a temp local in order to avoid ecj errors for javadoc lint
(Collections.max(values)); Object max = Collections.max(values);
result = Collections.singletonList(max);
} catch (ClassCastException e) { } catch (ClassCastException e) {
throw new SolrException throw new SolrException
(BAD_REQUEST, (BAD_REQUEST,

View File

@ -59,8 +59,9 @@ public final class MinFieldValueUpdateProcessorFactory extends FieldValueSubsetU
public Collection pickSubset(Collection values) { public Collection pickSubset(Collection values) {
Collection result = values; Collection result = values;
try { try {
result = Collections.singletonList // NOTE: min must be put into a temp local in order to avoid ecj errors for javadoc lint
(Collections.min(values)); Object min = Collections.min(values);
result = Collections.singletonList(min);
} catch (ClassCastException e) { } catch (ClassCastException e) {
throw new SolrException throw new SolrException
(BAD_REQUEST, (BAD_REQUEST,

View File

@ -219,7 +219,7 @@
See the Java Regular Expression documentation for more See the Java Regular Expression documentation for more
infomation on pattern and replacement string syntax. infomation on pattern and replacement string syntax.
http://docs.oracle.com/javase/7/docs/api/java/util/regex/package-summary.html http://docs.oracle.com/javase/8/docs/api/java/util/regex/package-summary.html
--> -->
<filter class="solr.PatternReplaceFilterFactory" <filter class="solr.PatternReplaceFilterFactory"
pattern="([^a-z])" replacement="" replace="all" pattern="([^a-z])" replacement="" replace="all"

View File

@ -214,7 +214,7 @@
See the Java Regular Expression documentation for more See the Java Regular Expression documentation for more
infomation on pattern and replacement string syntax. infomation on pattern and replacement string syntax.
http://docs.oracle.com/javase/7/docs/api/java/util/regex/package-summary.html http://docs.oracle.com/javase/8/docs/api/java/util/regex/package-summary.html
--> -->
<filter class="solr.PatternReplaceFilterFactory" <filter class="solr.PatternReplaceFilterFactory"
pattern="([^a-z])" replacement="" replace="all" pattern="([^a-z])" replacement="" replace="all"

View File

@ -615,7 +615,7 @@
See the Java Regular Expression documentation for more See the Java Regular Expression documentation for more
information on pattern and replacement string syntax. information on pattern and replacement string syntax.
http://docs.oracle.com/javase/7/docs/api/java/util/regex/package-summary.html http://docs.oracle.com/javase/8/docs/api/java/util/regex/package-summary.html
--> -->
<filter class="solr.PatternReplaceFilterFactory" <filter class="solr.PatternReplaceFilterFactory"
pattern="([^a-z])" replacement="" replace="all" pattern="([^a-z])" replacement="" replace="all"

View File

@ -534,7 +534,7 @@
See the Java Regular Expression documentation for more See the Java Regular Expression documentation for more
information on pattern and replacement string syntax. information on pattern and replacement string syntax.
http://docs.oracle.com/javase/7/docs/api/java/util/regex/package-summary.html http://docs.oracle.com/javase/8/docs/api/java/util/regex/package-summary.html
--> -->
<filter class="solr.PatternReplaceFilterFactory" <filter class="solr.PatternReplaceFilterFactory"
pattern="([^a-z])" replacement="" replace="all" pattern="([^a-z])" replacement="" replace="all"

View File

@ -565,7 +565,7 @@
See the Java Regular Expression documentation for more See the Java Regular Expression documentation for more
information on pattern and replacement string syntax. information on pattern and replacement string syntax.
http://docs.oracle.com/javase/7/docs/api/java/util/regex/package-summary.html http://docs.oracle.com/javase/8/docs/api/java/util/regex/package-summary.html
--> -->
<filter class="solr.PatternReplaceFilterFactory" <filter class="solr.PatternReplaceFilterFactory"
pattern="([^a-z])" replacement="" replace="all" pattern="([^a-z])" replacement="" replace="all"

View File

@ -615,7 +615,7 @@
See the Java Regular Expression documentation for more See the Java Regular Expression documentation for more
information on pattern and replacement string syntax. information on pattern and replacement string syntax.
http://docs.oracle.com/javase/7/docs/api/java/util/regex/package-summary.html http://docs.oracle.com/javase/8/docs/api/java/util/regex/package-summary.html
--> -->
<filter class="solr.PatternReplaceFilterFactory" <filter class="solr.PatternReplaceFilterFactory"
pattern="([^a-z])" replacement="" replace="all" pattern="([^a-z])" replacement="" replace="all"

View File

@ -616,7 +616,7 @@
See the Java Regular Expression documentation for more See the Java Regular Expression documentation for more
information on pattern and replacement string syntax. information on pattern and replacement string syntax.
http://docs.oracle.com/javase/7/docs/api/java/util/regex/package-summary.html http://docs.oracle.com/javase/8/docs/api/java/util/regex/package-summary.html
--> -->
<filter class="solr.PatternReplaceFilterFactory" <filter class="solr.PatternReplaceFilterFactory"
pattern="([^a-z])" replacement="" replace="all" pattern="([^a-z])" replacement="" replace="all"

View File

@ -54,13 +54,13 @@ To follow along with this tutorial, you will need...
</p> </p>
<ol> <ol>
<li>Java 1.7 or greater. Some places you can get it are from <li>Java 1.8 or greater. Some places you can get it are from
<a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">Oracle</a>, <a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">Oracle</a>,
<a href="http://openjdk.java.net/">Open JDK</a>, or <a href="http://openjdk.java.net/">Open JDK</a>, or
<a href="http://www.ibm.com/developerworks/java/jdk/">IBM</a>. <a href="http://www.ibm.com/developerworks/java/jdk/">IBM</a>.
<ul> <ul>
<li>Running <span class="codefrag">java -version</span> at the command <li>Running <span class="codefrag">java -version</span> at the command
line should indicate a version number starting with 1.7. line should indicate a version number starting with 1.8.
</li> </li>
<li>Gnu's GCJ is not supported and does not work with Solr.</li> <li>Gnu's GCJ is not supported and does not work with Solr.</li>
</ul> </ul>