From cb788d8e9ef07bef9f25cc175e60d41878f8e0d1 Mon Sep 17 00:00:00 2001 From: Tomoko Uchida Date: Sat, 11 Dec 2021 10:10:44 +0900 Subject: [PATCH 01/12] LUCENE-10305: Ensure line endings of versions.props is LF --- .gitattributes | 1 + versions.props | 44 ++++++++++++++++++++++---------------------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/.gitattributes b/.gitattributes index c7c7b25d269..e4f4bf8b496 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,6 @@ # Ignore all differences in line endings for the lock file. versions.lock text eol=lf +versions.props text eol=lf # Gradle files are always in LF. *.gradle text eol=lf diff --git a/versions.props b/versions.props index d4a9677b56b..46fe0cb5115 100644 --- a/versions.props +++ b/versions.props @@ -1,22 +1,22 @@ -com.carrotsearch.randomizedtesting:*=2.7.6 -com.carrotsearch:hppc=0.9.0 -com.google.errorprone:*=2.4.0 -com.ibm.icu:icu4j=70.1 -commons-codec:commons-codec=1.13 -io.sgr:s2-geometry-library-java=1.0.0 -javax.servlet:javax.servlet-api=3.1.0 -junit:junit=4.13.1 -net.sourceforge.nekohtml:nekohtml=1.9.17 -org.antlr:antlr4*=4.5.1-1 -org.apache.commons:commons-compress=1.19 -org.apache.httpcomponents:httpclient=4.5.13 -org.apache.logging.log4j:*=2.13.2 -org.apache.opennlp:opennlp-tools=1.9.1 -org.carrot2:morfologik-*=2.1.8 -org.eclipse.jetty:*=9.4.41.v20210516 -org.hamcrest:*=2.2 -org.locationtech.jts:jts-core=1.17.0 -org.locationtech.spatial4j:*=0.8 -org.ow2.asm:*=7.2 -ua.net.nlp:morfologik-ukrainian-search=4.9.1 -xerces:xercesImpl=2.12.0 +com.carrotsearch.randomizedtesting:*=2.7.6 +com.carrotsearch:hppc=0.9.0 +com.google.errorprone:*=2.4.0 +com.ibm.icu:icu4j=70.1 +commons-codec:commons-codec=1.13 +io.sgr:s2-geometry-library-java=1.0.0 +javax.servlet:javax.servlet-api=3.1.0 +junit:junit=4.13.1 +net.sourceforge.nekohtml:nekohtml=1.9.17 +org.antlr:antlr4*=4.5.1-1 +org.apache.commons:commons-compress=1.19 +org.apache.httpcomponents:httpclient=4.5.13 +org.apache.logging.log4j:*=2.13.2 +org.apache.opennlp:opennlp-tools=1.9.1 +org.carrot2:morfologik-*=2.1.8 +org.eclipse.jetty:*=9.4.41.v20210516 +org.hamcrest:*=2.2 +org.locationtech.jts:jts-core=1.17.0 +org.locationtech.spatial4j:*=0.8 +org.ow2.asm:*=7.2 +ua.net.nlp:morfologik-ukrainian-search=4.9.1 +xerces:xercesImpl=2.12.0 From e111182e12ed91498962abf4700319738cd53189 Mon Sep 17 00:00:00 2001 From: Tomoko Uchida Date: Sat, 11 Dec 2021 10:43:03 +0900 Subject: [PATCH 02/12] LUCENE-10303: Upgrade log4j to 2.15.0 --- lucene/CHANGES.txt | 2 ++ lucene/licenses/log4j-api-2.13.2.jar.sha1 | 1 - lucene/licenses/log4j-api-2.15.0.jar.sha1 | 1 + lucene/licenses/log4j-core-2.13.2.jar.sha1 | 1 - lucene/licenses/log4j-core-2.15.0.jar.sha1 | 1 + versions.lock | 4 ++-- versions.props | 2 +- 7 files changed, 7 insertions(+), 5 deletions(-) delete mode 100644 lucene/licenses/log4j-api-2.13.2.jar.sha1 create mode 100644 lucene/licenses/log4j-api-2.15.0.jar.sha1 delete mode 100644 lucene/licenses/log4j-core-2.13.2.jar.sha1 create mode 100644 lucene/licenses/log4j-core-2.15.0.jar.sha1 diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index ccaa2f2303f..eb0d28d29a1 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -108,6 +108,8 @@ Other * LUCENE-10284: Upgrade morfologik-stemming to 2.1.8. (Dawid Weiss) +* LUCENE-10303: Upgrade log4j to 2.15.0. (Tomoko Uchida) + ======================= Lucene 9.0.0 ======================= New Features diff --git a/lucene/licenses/log4j-api-2.13.2.jar.sha1 b/lucene/licenses/log4j-api-2.13.2.jar.sha1 deleted file mode 100644 index a9826491245..00000000000 --- a/lucene/licenses/log4j-api-2.13.2.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -567ea514dedd8679c429c5b5b39b0d67b6464c3c diff --git a/lucene/licenses/log4j-api-2.15.0.jar.sha1 b/lucene/licenses/log4j-api-2.15.0.jar.sha1 new file mode 100644 index 00000000000..a699db85f74 --- /dev/null +++ b/lucene/licenses/log4j-api-2.15.0.jar.sha1 @@ -0,0 +1 @@ +4a5aa7e55a29391c6f66e0b259d5189aa11e45d0 \ No newline at end of file diff --git a/lucene/licenses/log4j-core-2.13.2.jar.sha1 b/lucene/licenses/log4j-core-2.13.2.jar.sha1 deleted file mode 100644 index ce26d9c45a8..00000000000 --- a/lucene/licenses/log4j-core-2.13.2.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -8eb1fc1914eb2550bf3ddea26917c9a7cbb00593 diff --git a/lucene/licenses/log4j-core-2.15.0.jar.sha1 b/lucene/licenses/log4j-core-2.15.0.jar.sha1 new file mode 100644 index 00000000000..b0ab8d9f40f --- /dev/null +++ b/lucene/licenses/log4j-core-2.15.0.jar.sha1 @@ -0,0 +1 @@ +ba55c13d7ac2fd44df9cc8074455719a33f375b9 \ No newline at end of file diff --git a/versions.lock b/versions.lock index 98770e51109..80f63aac0d0 100644 --- a/versions.lock +++ b/versions.lock @@ -12,8 +12,8 @@ org.antlr:antlr4-runtime:4.5.1-1 (1 constraints: 6a05b240) org.apache.commons:commons-compress:1.19 (1 constraints: df04fa30) org.apache.httpcomponents:httpclient:4.5.13 (1 constraints: 3f054e3b) org.apache.httpcomponents:httpcore:4.4.13 (1 constraints: 591016a2) -org.apache.logging.log4j:log4j-api:2.13.2 (1 constraints: bb0e1b76) -org.apache.logging.log4j:log4j-core:2.13.2 (1 constraints: 3a053a3b) +org.apache.logging.log4j:log4j-api:2.15.0 (1 constraints: bb0e1f76) +org.apache.logging.log4j:log4j-core:2.15.0 (1 constraints: 3a053e3b) org.apache.opennlp:opennlp-tools:1.9.1 (1 constraints: 0d050c36) org.carrot2:morfologik-fsa:2.1.8 (1 constraints: da0d9b36) org.carrot2:morfologik-polish:2.1.8 (1 constraints: 0d050036) diff --git a/versions.props b/versions.props index 46fe0cb5115..185bcfcbccb 100644 --- a/versions.props +++ b/versions.props @@ -10,7 +10,7 @@ net.sourceforge.nekohtml:nekohtml=1.9.17 org.antlr:antlr4*=4.5.1-1 org.apache.commons:commons-compress=1.19 org.apache.httpcomponents:httpclient=4.5.13 -org.apache.logging.log4j:*=2.13.2 +org.apache.logging.log4j:*=2.15.0 org.apache.opennlp:opennlp-tools=1.9.1 org.carrot2:morfologik-*=2.1.8 org.eclipse.jetty:*=9.4.41.v20210516 From 2f634b0d95ec24283999c61ec700d9e96a854633 Mon Sep 17 00:00:00 2001 From: Tomoko Uchida Date: Sun, 12 Dec 2021 15:31:18 +0900 Subject: [PATCH 03/12] LUCENE-10309: Minimum KnnVector codec support in Luke (#535) --- .../components/DocumentsPanelProvider.java | 29 +++++++++++++++++-- .../luke/models/documents/DocumentField.java | 18 ++++++++++++ .../models/documents/TestDocumentsImpl.java | 4 +++ 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/DocumentsPanelProvider.java b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/DocumentsPanelProvider.java index d7581f67cad..613cca415eb 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/DocumentsPanelProvider.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/DocumentsPanelProvider.java @@ -35,6 +35,7 @@ import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import java.util.List; +import java.util.Locale; import java.util.Objects; import java.util.Optional; import javax.swing.BorderFactory; @@ -154,7 +155,7 @@ public final class DocumentsPanelProvider implements DocumentsTabOperator { this.tableHeaderRenderer = new HelpHeaderRenderer( "About Flags", - "Format: IdfpoNPSB#txxVDtxxxxTx/x", + "Format: IdfpoNPSB#txxVDtxxxxTx/xKxxxx/xxx", createFlagsHelpDialog(), helpDialogFactory); @@ -173,7 +174,8 @@ public final class DocumentsPanelProvider implements DocumentsTabOperator { "#txx - numeric stored values(type, precision)", "V - term vectors", "Dtxxxxx - doc values(type)", - "Tx/x - point values(num bytes/dimension)" + "Tx/x - point values(num bytes/dimension)", + "Kxxxx/xxx - knn vector values(dimension/similarity)" }; JList list = new JList<>(values); return new JScrollPane(list); @@ -1049,7 +1051,7 @@ public final class DocumentsPanelProvider implements DocumentsTabOperator { enum Column implements TableColumnInfo { FIELD("Field", 0, String.class, 150), - FLAGS("Flags", 1, String.class, 200), + FLAGS("Flags", 1, String.class, 220), NORM("Norm", 2, Long.class, 80), VALUE("Value", 3, String.class, 500); @@ -1227,6 +1229,27 @@ public final class DocumentsPanelProvider implements DocumentsTabOperator { sb.append("/"); sb.append(f.getPointDimensionCount()); } + // knn vector values + if (f.getVectorDimension() == 0) { + sb.append("---------"); + } else { + sb.append("K"); + sb.append(String.format(Locale.ENGLISH, "%04d", f.getVectorDimension())); + sb.append("/"); + switch (f.getVectorSimilarity()) { + case COSINE: + sb.append("cos"); + break; + case DOT_PRODUCT: + sb.append("dot"); + break; + case EUCLIDEAN: + sb.append("euc"); + break; + default: + sb.append("???"); + } + } return sb.toString(); } diff --git a/lucene/luke/src/java/org/apache/lucene/luke/models/documents/DocumentField.java b/lucene/luke/src/java/org/apache/lucene/luke/models/documents/DocumentField.java index a27c8dba58f..460d1422649 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/models/documents/DocumentField.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/models/documents/DocumentField.java @@ -26,6 +26,7 @@ import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexableField; import org.apache.lucene.index.MultiDocValues; import org.apache.lucene.index.NumericDocValues; +import org.apache.lucene.index.VectorSimilarityFunction; import org.apache.lucene.util.BytesRef; /** Holder for a document field's information and data. */ @@ -54,6 +55,10 @@ public final class DocumentField { private int pointDimensionCount; private int pointNumBytes; + // knn vector values + private int vectorDimension; + private VectorSimilarityFunction vectorSimilarity; + static DocumentField of(FieldInfo finfo, IndexReader reader, int docId) throws IOException { return of(finfo, null, reader, docId); } @@ -84,6 +89,9 @@ public final class DocumentField { dfield.pointDimensionCount = finfo.getPointDimensionCount(); dfield.pointNumBytes = finfo.getPointNumBytes(); + dfield.vectorDimension = finfo.getVectorDimension(); + dfield.vectorSimilarity = finfo.getVectorSimilarityFunction(); + if (field != null) { dfield.isStored = field.fieldType().stored(); dfield.stringValue = field.stringValue(); @@ -148,6 +156,14 @@ public final class DocumentField { return pointNumBytes; } + public int getVectorDimension() { + return vectorDimension; + } + + public VectorSimilarityFunction getVectorSimilarity() { + return vectorSimilarity; + } + @Override public String toString() { return "DocumentField{" @@ -164,6 +180,8 @@ public final class DocumentField { + dvType + ", pointDimensionCount=" + pointDimensionCount + + ", vectorDimension=" + + vectorDimension + '}'; } diff --git a/lucene/luke/src/test/org/apache/lucene/luke/models/documents/TestDocumentsImpl.java b/lucene/luke/src/test/org/apache/lucene/luke/models/documents/TestDocumentsImpl.java index ddddbef8fc0..8162b571ca6 100644 --- a/lucene/luke/src/test/org/apache/lucene/luke/models/documents/TestDocumentsImpl.java +++ b/lucene/luke/src/test/org/apache/lucene/luke/models/documents/TestDocumentsImpl.java @@ -68,6 +68,7 @@ public class TestDocumentsImpl extends DocumentsTestBase { assertEquals(DocValuesType.NONE, f1.getDvType()); assertEquals(0, f1.getPointDimensionCount()); assertEquals(0, f1.getPointNumBytes()); + assertEquals(0, f1.getVectorDimension()); DocumentField f2 = fields.get(1); assertEquals("author", f2.getName()); @@ -83,6 +84,7 @@ public class TestDocumentsImpl extends DocumentsTestBase { assertEquals(DocValuesType.NONE, f2.getDvType()); assertEquals(0, f2.getPointDimensionCount()); assertEquals(0, f2.getPointNumBytes()); + assertEquals(0, f2.getVectorDimension()); DocumentField f3 = fields.get(2); assertEquals("text", f3.getName()); @@ -98,6 +100,7 @@ public class TestDocumentsImpl extends DocumentsTestBase { assertEquals(DocValuesType.NONE, f3.getDvType()); assertEquals(0, f3.getPointDimensionCount()); assertEquals(0, f3.getPointNumBytes()); + assertEquals(0, f3.getVectorDimension()); DocumentField f4 = fields.get(3); assertEquals("subject", f4.getName()); @@ -113,6 +116,7 @@ public class TestDocumentsImpl extends DocumentsTestBase { assertEquals(DocValuesType.SORTED_SET, f4.getDvType()); assertEquals(0, f4.getPointDimensionCount()); assertEquals(0, f4.getPointNumBytes()); + assertEquals(0, f4.getVectorDimension()); DocumentField f5 = fields.get(4); assertEquals("downloads", f5.getName()); From 5207aae5279757bfd0d40f4995576d2af7d4ea31 Mon Sep 17 00:00:00 2001 From: Ignacio Vera Date: Mon, 13 Dec 2021 12:01:20 +0100 Subject: [PATCH 04/12] LUCENE-10310: Fix test error in TestXYDocValuesQueries#testRandomDistanceHuge (#537) We create random circles using ShapeTestUtils which is safe. --- lucene/CHANGES.txt | 3 +++ .../java/org/apache/lucene/geo/BaseXYPointTestCase.java | 7 ++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index eb0d28d29a1..c1ce6cab356 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -110,6 +110,9 @@ Other * LUCENE-10303: Upgrade log4j to 2.15.0. (Tomoko Uchida) +* LUCENE-10310: TestXYDocValuesQueries#doRandomDistanceTest does not produce random circles with radius + with '0' value any longer. + ======================= Lucene 9.0.0 ======================= New Features diff --git a/lucene/test-framework/src/java/org/apache/lucene/geo/BaseXYPointTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/geo/BaseXYPointTestCase.java index b6cc893d5d1..b533d3ebfb1 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/geo/BaseXYPointTestCase.java +++ b/lucene/test-framework/src/java/org/apache/lucene/geo/BaseXYPointTestCase.java @@ -1341,9 +1341,10 @@ public abstract class BaseXYPointTestCase extends LuceneTestCase { IndexSearcher searcher = newSearcher(reader); for (int i = 0; i < numQueries; i++) { - float x = nextX(); - float y = nextY(); - float radius = (Float.MAX_VALUE / 2) * random().nextFloat(); + XYCircle circle = ShapeTestUtil.nextCircle(); + float x = circle.getX(); + float y = circle.getY(); + float radius = circle.getRadius(); BitSet expected = new BitSet(); for (int doc = 0; doc < reader.maxDoc(); doc++) { From 9974f6ac34ac2f17bfcdf30d6df79476579ff1e0 Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Tue, 14 Dec 2021 13:49:58 +0400 Subject: [PATCH 05/12] LUCENE-10085: Fix flaky testQueryMatchesCount (#538) Five times every 10 000 tests, we did not index any documents with i between 0 and 10 (inclusive), which caused the deleted tests to fail. With this commit, we make sure that we always index at least one document between 0 and 10. --- .../apache/lucene/search/TestDocValuesFieldExistsQuery.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lucene/core/src/test/org/apache/lucene/search/TestDocValuesFieldExistsQuery.java b/lucene/core/src/test/org/apache/lucene/search/TestDocValuesFieldExistsQuery.java index 489ee0f35e9..ef400610720 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestDocValuesFieldExistsQuery.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestDocValuesFieldExistsQuery.java @@ -222,7 +222,8 @@ public class TestDocValuesFieldExistsQuery extends LuceneTestCase { for (int i = 0; i < randomNumDocs; i++) { Document doc = new Document(); - if (random().nextBoolean()) { + // ensure we index at least a document with long between 0 and 10 + if (i == 0 || random().nextBoolean()) { doc.add(new LongPoint("long", i)); doc.add(new NumericDocValuesField("long", i)); doc.add(new StringField("string", "value", Store.NO)); From 3687c71f28bf4384accffb1a907f24a9ed3f00f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20H=C3=B8ydahl?= Date: Thu, 16 Dec 2021 10:43:44 +0100 Subject: [PATCH 06/12] Add 8.11.1 --- dev-tools/doap/lucene.rdf | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/dev-tools/doap/lucene.rdf b/dev-tools/doap/lucene.rdf index ff4370c8565..63b45308749 100644 --- a/dev-tools/doap/lucene.rdf +++ b/dev-tools/doap/lucene.rdf @@ -74,6 +74,13 @@ 9.0.0 + + + lucene-8.11.1 + 2021-12-16 + 8.11.1 + + lucene-8.11.0 From 36638dcb1e2510d3272c1d2526cf8c0a9dde18e3 Mon Sep 17 00:00:00 2001 From: Dawid Weiss Date: Thu, 16 Dec 2021 11:18:34 +0100 Subject: [PATCH 07/12] LUCENE-10313: drop log4j from luke (#544) --- lucene/CHANGES.txt | 4 + .../src/binary-release/bin/luke.cmd | 2 +- .../src/binary-release/bin/luke.sh | 2 +- lucene/licenses/log4j-api-2.15.0.jar.sha1 | 1 - lucene/licenses/log4j-api-LICENSE-ASL.txt | 201 ------------------ lucene/licenses/log4j-api-NOTICE.txt | 17 -- lucene/licenses/log4j-core-2.15.0.jar.sha1 | 1 - lucene/licenses/log4j-core-LICENSE-ASL.txt | 201 ------------------ lucene/licenses/log4j-core-NOTICE.txt | 17 -- lucene/luke/build.gradle | 2 - lucene/luke/src/distribution/README.md | 2 +- .../lucene/luke/app/AbstractHandler.java | 7 +- .../apache/lucene/luke/app/IndexHandler.java | 9 +- .../lucene/luke/app/desktop/LukeMain.java | 15 +- .../desktop/components/LogsPanelProvider.java | 131 ++++++++++-- .../components/LukeWindowProvider.java | 25 +-- .../components/TabbedPaneProvider.java | 9 +- .../documents/AddDocumentDialogFactory.java | 9 +- .../menubar/CheckIndexDialogFactory.java | 5 +- .../menubar/CreateIndexDialogFactory.java | 5 +- .../menubar/ExportTermsDialogFactory.java | 7 +- .../menubar/OpenIndexDialogFactory.java | 5 +- .../app/desktop/util/ExceptionHandler.java | 7 +- .../app/desktop/util/TextAreaAppender.java | 108 ---------- .../luke/models/commits/CommitsImpl.java | 6 +- .../luke/models/documents/DocumentsImpl.java | 44 ++-- .../models/documents/TermVectorsAdapter.java | 8 +- .../lucene/luke/models/search/SearchImpl.java | 10 +- .../lucene/luke/models/util/IndexUtils.java | 33 ++- .../twentynewsgroups/MessageFilesParser.java | 9 +- .../luke/util/CircularLogBufferHandler.java | 114 ++++++++++ .../lucene/luke/util/LoggerFactory.java | 56 ++--- .../app/desktop/messages/messages.properties | 2 +- versions.lock | 2 - versions.props | 1 - 35 files changed, 349 insertions(+), 728 deletions(-) delete mode 100644 lucene/licenses/log4j-api-2.15.0.jar.sha1 delete mode 100644 lucene/licenses/log4j-api-LICENSE-ASL.txt delete mode 100644 lucene/licenses/log4j-api-NOTICE.txt delete mode 100644 lucene/licenses/log4j-core-2.15.0.jar.sha1 delete mode 100644 lucene/licenses/log4j-core-LICENSE-ASL.txt delete mode 100644 lucene/licenses/log4j-core-NOTICE.txt delete mode 100644 lucene/luke/src/java/org/apache/lucene/luke/app/desktop/util/TextAreaAppender.java create mode 100644 lucene/luke/src/java/org/apache/lucene/luke/util/CircularLogBufferHandler.java diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index c1ce6cab356..9b98105abf4 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -68,6 +68,10 @@ New Features Improvements --------------------- +* LUCENE-10313: use java util logging in Luke. Add dynamic log filtering. Drop + the persistent log previously written to ~/.luke.d/luke.log. Configure Java's default + logging handlers to persist Luke logs according to your needs. (Tomoko Uchida, Dawid Weiss) + * LUCENE-10238: Upgrade icu4j dependency to 70.1. (Dawid Weiss) * LUCENE-9820: Extract BKD tree interface and move intersecting logic to the diff --git a/lucene/distribution/src/binary-release/bin/luke.cmd b/lucene/distribution/src/binary-release/bin/luke.cmd index d5a3ce17c83..b4591aedafe 100644 --- a/lucene/distribution/src/binary-release/bin/luke.cmd +++ b/lucene/distribution/src/binary-release/bin/luke.cmd @@ -17,5 +17,5 @@ SETLOCAL SET MODULES=%~dp0.. -start javaw --module-path "%MODULES%\modules;%MODULES%\modules-thirdparty" --add-modules jdk.unsupported,org.apache.logging.log4j --module org.apache.lucene.luke +start javaw --module-path "%MODULES%\modules;%MODULES%\modules-thirdparty" --add-modules jdk.unsupported --module org.apache.lucene.luke ENDLOCAL diff --git a/lucene/distribution/src/binary-release/bin/luke.sh b/lucene/distribution/src/binary-release/bin/luke.sh index 09145328b5a..053eddacd80 100644 --- a/lucene/distribution/src/binary-release/bin/luke.sh +++ b/lucene/distribution/src/binary-release/bin/luke.sh @@ -17,4 +17,4 @@ MODULES=`dirname "$0"`/.. MODULES=`cd "$MODULES" && pwd` -java --module-path "$MODULES/modules:$MODULES/modules-thirdparty" --add-modules jdk.unsupported,org.apache.logging.log4j --module org.apache.lucene.luke +java --module-path "$MODULES/modules:$MODULES/modules-thirdparty" --add-modules jdk.unsupported --module org.apache.lucene.luke diff --git a/lucene/licenses/log4j-api-2.15.0.jar.sha1 b/lucene/licenses/log4j-api-2.15.0.jar.sha1 deleted file mode 100644 index a699db85f74..00000000000 --- a/lucene/licenses/log4j-api-2.15.0.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -4a5aa7e55a29391c6f66e0b259d5189aa11e45d0 \ No newline at end of file diff --git a/lucene/licenses/log4j-api-LICENSE-ASL.txt b/lucene/licenses/log4j-api-LICENSE-ASL.txt deleted file mode 100644 index f49a4e16e68..00000000000 --- a/lucene/licenses/log4j-api-LICENSE-ASL.txt +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. \ No newline at end of file diff --git a/lucene/licenses/log4j-api-NOTICE.txt b/lucene/licenses/log4j-api-NOTICE.txt deleted file mode 100644 index ebba5ac0018..00000000000 --- a/lucene/licenses/log4j-api-NOTICE.txt +++ /dev/null @@ -1,17 +0,0 @@ -Apache Log4j -Copyright 1999-2017 Apache Software Foundation - -This product includes software developed at -The Apache Software Foundation (http://www.apache.org/). - -ResolverUtil.java -Copyright 2005-2006 Tim Fennell - -Dumbster SMTP test server -Copyright 2004 Jason Paul Kitchen - -TypeUtil.java -Copyright 2002-2012 Ramnivas Laddad, Juergen Hoeller, Chris Beams - -picocli (http://picocli.info) -Copyright 2017 Remko Popma \ No newline at end of file diff --git a/lucene/licenses/log4j-core-2.15.0.jar.sha1 b/lucene/licenses/log4j-core-2.15.0.jar.sha1 deleted file mode 100644 index b0ab8d9f40f..00000000000 --- a/lucene/licenses/log4j-core-2.15.0.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -ba55c13d7ac2fd44df9cc8074455719a33f375b9 \ No newline at end of file diff --git a/lucene/licenses/log4j-core-LICENSE-ASL.txt b/lucene/licenses/log4j-core-LICENSE-ASL.txt deleted file mode 100644 index f49a4e16e68..00000000000 --- a/lucene/licenses/log4j-core-LICENSE-ASL.txt +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. \ No newline at end of file diff --git a/lucene/licenses/log4j-core-NOTICE.txt b/lucene/licenses/log4j-core-NOTICE.txt deleted file mode 100644 index ebba5ac0018..00000000000 --- a/lucene/licenses/log4j-core-NOTICE.txt +++ /dev/null @@ -1,17 +0,0 @@ -Apache Log4j -Copyright 1999-2017 Apache Software Foundation - -This product includes software developed at -The Apache Software Foundation (http://www.apache.org/). - -ResolverUtil.java -Copyright 2005-2006 Tim Fennell - -Dumbster SMTP test server -Copyright 2004 Jason Paul Kitchen - -TypeUtil.java -Copyright 2002-2012 Ramnivas Laddad, Juergen Hoeller, Chris Beams - -picocli (http://picocli.info) -Copyright 2017 Remko Popma \ No newline at end of file diff --git a/lucene/luke/build.gradle b/lucene/luke/build.gradle index 23c843a39ab..fe556ca9527 100644 --- a/lucene/luke/build.gradle +++ b/lucene/luke/build.gradle @@ -27,8 +27,6 @@ ext { dependencies { api project(':lucene:core') - implementation 'org.apache.logging.log4j:log4j-core' - implementation project(':lucene:codecs') implementation project(':lucene:backward-codecs') implementation project(':lucene:analysis:common') diff --git a/lucene/luke/src/distribution/README.md b/lucene/luke/src/distribution/README.md index 0548fd17df8..4ff8bc717a6 100644 --- a/lucene/luke/src/distribution/README.md +++ b/lucene/luke/src/distribution/README.md @@ -27,7 +27,7 @@ java -jar ${luke.cmd} or, using Java modules: ``` -java --module-path . --add-modules jdk.unsupported,org.apache.logging.log4j --module org.apache.lucene.luke +java --module-path . --add-modules jdk.unsupported --module org.apache.lucene.luke ``` Happy index hacking! diff --git a/lucene/luke/src/java/org/apache/lucene/luke/app/AbstractHandler.java b/lucene/luke/src/java/org/apache/lucene/luke/app/AbstractHandler.java index 5abd9d931fd..ad77385a5dc 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/app/AbstractHandler.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/app/AbstractHandler.java @@ -20,7 +20,8 @@ package org.apache.lucene.luke.app; import java.lang.invoke.MethodHandles; import java.util.ArrayList; import java.util.List; -import org.apache.logging.log4j.Logger; +import java.util.logging.Level; +import java.util.logging.Logger; import org.apache.lucene.luke.util.LoggerFactory; /** Abstract handler class */ @@ -32,8 +33,8 @@ public abstract class AbstractHandler { public void addObserver(T observer) { observers.add(observer); - if (log.isDebugEnabled()) { - log.debug("{} registered.", observer.getClass().getName()); + if (log.isLoggable(Level.FINE)) { + log.fine(observer.getClass().getName() + " registered."); } } diff --git a/lucene/luke/src/java/org/apache/lucene/luke/app/IndexHandler.java b/lucene/luke/src/java/org/apache/lucene/luke/app/IndexHandler.java index 46e2e3de4d4..f35139e46d5 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/app/IndexHandler.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/app/IndexHandler.java @@ -21,7 +21,8 @@ import java.io.IOException; import java.lang.invoke.MethodHandles; import java.nio.file.NoSuchFileException; import java.util.Objects; -import org.apache.logging.log4j.Logger; +import java.util.logging.Level; +import java.util.logging.Logger; import org.apache.lucene.index.IndexReader; import org.apache.lucene.luke.app.desktop.PreferencesFactory; import org.apache.lucene.luke.app.desktop.util.MessageUtils; @@ -75,19 +76,19 @@ public final class IndexHandler extends AbstractHandler { try { reader = IndexUtils.openIndex(indexPath, dirImpl); } catch (NoSuchFileException e) { - log.error("Error opening index", e); + log.log(Level.SEVERE, "Error opening index", e); try { // remove the non-existing index path from history. PreferencesFactory.getInstance().removeHistory(indexPath); } catch (IOException ioe) { - log.error("Preference file is deleted?", ioe); + log.log(Level.SEVERE, "Preference file is deleted?", ioe); } throw new LukeException( MessageUtils.getLocalizedMessage( "openindex.message.index_path_does_not_exist", indexPath), e); } catch (Exception e) { - log.error("Error opening index", e); + log.log(Level.SEVERE, "Error opening index", e); throw new LukeException( MessageUtils.getLocalizedMessage("openindex.message.index_path_invalid", indexPath), e); } diff --git a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/LukeMain.java b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/LukeMain.java index 78c52544091..f64ec18bd2c 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/LukeMain.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/LukeMain.java @@ -22,10 +22,10 @@ import static org.apache.lucene.luke.app.desktop.util.ExceptionHandler.handle; import java.awt.GraphicsEnvironment; import java.io.IOException; import java.lang.invoke.MethodHandles; -import java.nio.file.FileSystems; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.swing.JFrame; import javax.swing.UIManager; -import org.apache.logging.log4j.Logger; import org.apache.lucene.luke.app.desktop.components.LukeWindowProvider; import org.apache.lucene.luke.app.desktop.components.dialog.menubar.OpenIndexDialogFactory; import org.apache.lucene.luke.app.desktop.util.DialogOpener; @@ -36,15 +36,8 @@ import org.apache.lucene.luke.util.LoggerFactory; /** Entry class for desktop Luke */ public class LukeMain { - public static final String LOG_FILE = - System.getProperty("user.home") - + FileSystems.getDefault().getSeparator() - + ".luke.d" - + FileSystems.getDefault().getSeparator() - + "luke.log"; - static { - LoggerFactory.initGuiLogging(LOG_FILE); + LoggerFactory.initGuiLogging(); } private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); @@ -77,7 +70,7 @@ public class LukeMain { (factory) -> {}); } catch (IOException e) { messageBroker.showUnknownErrorMessage(); - log.error("Cannot initialize components.", e); + log.log(Level.SEVERE, "Cannot initialize components.", e); } } diff --git a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/LogsPanelProvider.java b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/LogsPanelProvider.java index 1f6bcf11d72..26bf9fb725c 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/LogsPanelProvider.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/LogsPanelProvider.java @@ -17,24 +17,28 @@ package org.apache.lucene.luke.app.desktop.components; -import java.awt.BorderLayout; -import java.awt.FlowLayout; -import javax.swing.BorderFactory; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import org.apache.lucene.luke.app.desktop.LukeMain; +import java.awt.*; +import java.awt.event.HierarchyEvent; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Locale; +import java.util.Objects; +import java.util.function.Function; +import java.util.logging.Level; +import java.util.stream.Collectors; +import javax.swing.*; import org.apache.lucene.luke.app.desktop.util.MessageUtils; +import org.apache.lucene.luke.util.CircularLogBufferHandler; +import org.apache.lucene.luke.util.LoggerFactory; /** Provider of the Logs panel */ public final class LogsPanelProvider { - private final JTextArea logTextArea; - - public LogsPanelProvider(JTextArea logTextArea) { - this.logTextArea = logTextArea; - } + public LogsPanelProvider() {} public JPanel get() { JPanel panel = new JPanel(new BorderLayout()); @@ -43,14 +47,107 @@ public final class LogsPanelProvider { JPanel header = new JPanel(new FlowLayout(FlowLayout.LEADING)); header.setOpaque(false); - header.add(new JLabel(MessageUtils.getLocalizedMessage("logs.label.see_also"))); + header.add(new JLabel(MessageUtils.getLocalizedMessage("logs.label.level"))); - JLabel logPathLabel = new JLabel(LukeMain.LOG_FILE); - header.add(logPathLabel); + JComboBox logFilter = + new JComboBox<>( + new Level[] { + Level.FINEST, + Level.FINER, + Level.FINE, + Level.CONFIG, + Level.INFO, + Level.WARNING, + Level.SEVERE, + Level.OFF + }); + logFilter.setEditable(false); + logFilter.setSelectedItem(Level.INFO); + header.add(logFilter); + + var logTextArea = createLogPanel(logFilter); panel.add(header, BorderLayout.PAGE_START); - panel.add(new JScrollPane(logTextArea), BorderLayout.CENTER); return panel; } + + /** Prepare the component responsible for displaying logs. */ + private JTextArea createLogPanel(JComboBox logFilter) { + JTextArea logTextArea = new JTextArea(); + logTextArea.setEditable(false); + + class LogRecordFormatter + implements Function { + @Override + public String apply(CircularLogBufferHandler.ImmutableLogRecord record) { + return String.format( + Locale.ROOT, + "%s [%s] %s: %s", + DateTimeFormatter.ofPattern("HH:mm:ss", Locale.ROOT) + .format(record.getInstant().atZone(ZoneId.systemDefault())), + record.getLevel(), + record.getLoggerName(), + record.getMessage() + + (record.getThrown() == null ? "" : "\n" + toString(record.getThrown()))); + } + + private String toString(Throwable t) { + try (StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw)) { + t.printStackTrace(pw); + pw.flush(); + return sw.toString(); + } catch (IOException e) { + return "Could not dump stack trace: " + e.getMessage(); + } + } + } + + // Hook into live data from the circular log buffer and update the initial state. + Function formatter = + new LogRecordFormatter(); + CircularLogBufferHandler.LogUpdateListener updater = + records -> { + // Create an immutable copy of the logs to display in the gui thread. + ArrayList clonedCopy = + new ArrayList<>(records); + SwingUtilities.invokeLater( + () -> { + Level level = (Level) Objects.requireNonNull(logFilter.getSelectedItem()); + + String logContent = + clonedCopy.stream() + .filter(record -> record.getLevel().intValue() > level.intValue()) + .map(formatter::apply) + .collect(Collectors.joining("\n")); + + logTextArea.setText(logContent); + }); + }; + + var logBuffer = Objects.requireNonNull(LoggerFactory.circularBuffer); + + // Update state on filter change. + logFilter.addActionListener( + e -> { + updater.accept(logBuffer.getLogRecords()); + }); + + // Subscribe to log events and update state only when actually displayed. + logTextArea.addHierarchyListener( + (HierarchyEvent e) -> { + if (e.getComponent() == logTextArea + && (e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0) { + if (logTextArea.isDisplayable()) { + logBuffer.addUpdateListener(updater); + updater.accept(logBuffer.getLogRecords()); + } else { + logBuffer.removeUpdateListener(updater); + } + } + }); + + return logTextArea; + } } diff --git a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/LukeWindowProvider.java b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/LukeWindowProvider.java index bbea489e937..a7a46a825ba 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/LukeWindowProvider.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/LukeWindowProvider.java @@ -17,22 +17,9 @@ package org.apache.lucene.luke.app.desktop.components; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.GridLayout; +import java.awt.*; import java.io.IOException; -import javax.swing.BorderFactory; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JMenuBar; -import javax.swing.JPanel; -import javax.swing.JTabbedPane; -import javax.swing.JTextArea; -import javax.swing.WindowConstants; +import javax.swing.*; import org.apache.lucene.luke.app.DirectoryHandler; import org.apache.lucene.luke.app.DirectoryObserver; import org.apache.lucene.luke.app.IndexHandler; @@ -44,7 +31,6 @@ import org.apache.lucene.luke.app.desktop.PreferencesFactory; import org.apache.lucene.luke.app.desktop.util.FontUtils; import org.apache.lucene.luke.app.desktop.util.ImageUtils; import org.apache.lucene.luke.app.desktop.util.MessageUtils; -import org.apache.lucene.luke.app.desktop.util.TextAreaAppender; import org.apache.lucene.util.Version; /** Provider of the root window */ @@ -74,14 +60,9 @@ public final class LukeWindowProvider implements LukeWindowOperator { private JFrame frame = new JFrame(); public LukeWindowProvider() throws IOException { - // prepare log4j appender for Logs tab. - JTextArea logTextArea = new JTextArea(); - logTextArea.setEditable(false); - TextAreaAppender.setTextArea(logTextArea); - this.prefs = PreferencesFactory.getInstance(); this.menuBar = new MenuBarProvider().get(); - this.tabbedPane = new TabbedPaneProvider(logTextArea).get(); + this.tabbedPane = new TabbedPaneProvider().get(); this.messageBroker = MessageBroker.getInstance(); this.tabSwitcher = TabSwitcherProxy.getInstance(); diff --git a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/TabbedPaneProvider.java b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/TabbedPaneProvider.java index a64d89e6604..83468ab1f7f 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/TabbedPaneProvider.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/TabbedPaneProvider.java @@ -20,7 +20,6 @@ package org.apache.lucene.luke.app.desktop.components; import java.io.IOException; import javax.swing.JPanel; import javax.swing.JTabbedPane; -import javax.swing.JTextArea; import org.apache.lucene.luke.app.DirectoryHandler; import org.apache.lucene.luke.app.DirectoryObserver; import org.apache.lucene.luke.app.IndexHandler; @@ -35,7 +34,7 @@ public final class TabbedPaneProvider implements TabSwitcherProxy.TabSwitcher { private final MessageBroker messageBroker; - private final JTabbedPane tabbedPane = new JTabbedPane(); + private final JTabbedPane tabbedPane; private final JPanel overviewPanel; @@ -49,13 +48,15 @@ public final class TabbedPaneProvider implements TabSwitcherProxy.TabSwitcher { private final JPanel logsPanel; - public TabbedPaneProvider(JTextArea logTextArea) throws IOException { + public TabbedPaneProvider() throws IOException { + this.tabbedPane = new JTabbedPane(); + this.overviewPanel = new OverviewPanelProvider().get(); this.documentsPanel = new DocumentsPanelProvider().get(); this.searchPanel = new SearchPanelProvider().get(); this.analysisPanel = new AnalysisPanelProvider().get(); this.commitsPanel = new CommitsPanelProvider().get(); - this.logsPanel = new LogsPanelProvider(logTextArea).get(); + this.logsPanel = new LogsPanelProvider().get(); this.messageBroker = MessageBroker.getInstance(); diff --git a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/documents/AddDocumentDialogFactory.java b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/documents/AddDocumentDialogFactory.java index 535dcafece6..723cd21dbb1 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/documents/AddDocumentDialogFactory.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/documents/AddDocumentDialogFactory.java @@ -33,6 +33,8 @@ import java.io.IOException; import java.lang.invoke.MethodHandles; import java.lang.reflect.Constructor; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.stream.Collectors; import java.util.stream.IntStream; import javax.swing.BorderFactory; @@ -51,7 +53,6 @@ import javax.swing.ListSelectionModel; import javax.swing.UIManager; import javax.swing.table.JTableHeader; import javax.swing.table.TableCellRenderer; -import org.apache.logging.log4j.Logger; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; @@ -399,15 +400,15 @@ public final class AddDocumentDialogFactory doc.add(toIndexableField(nf)); } } catch (NumberFormatException ex) { - log.error("Error converting field value", e); + log.log(Level.SEVERE, "Error converting field value", e); throw new LukeException("Invalid value: " + ex.getMessage(), ex); } catch (Exception ex) { - log.error("Error converting field value", e); + log.log(Level.SEVERE, "Error converting field value", e); throw new LukeException(ex.getMessage(), ex); } addDocument(doc); - log.info("Added document: {}", doc); + log.info("Added document: " + doc); } @SuppressWarnings("unchecked") diff --git a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/menubar/CheckIndexDialogFactory.java b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/menubar/CheckIndexDialogFactory.java index ba058c59b79..cd05bedaf34 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/menubar/CheckIndexDialogFactory.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/menubar/CheckIndexDialogFactory.java @@ -29,6 +29,8 @@ import java.io.IOException; import java.lang.invoke.MethodHandles; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.JButton; @@ -39,7 +41,6 @@ import javax.swing.JScrollPane; import javax.swing.JSeparator; import javax.swing.JTextArea; import javax.swing.SwingWorker; -import org.apache.logging.log4j.Logger; import org.apache.lucene.index.CheckIndex; import org.apache.lucene.luke.app.DirectoryHandler; import org.apache.lucene.luke.app.DirectoryObserver; @@ -304,7 +305,7 @@ public final class CheckIndexDialogFactory implements DialogOpener.DialogFactory } status = st; } catch (Exception e) { - log.error("Error checking index", e); + log.log(Level.SEVERE, "Error checking index", e); statusLbl.setText(MessageUtils.getLocalizedMessage("message.error.unknown")); } } diff --git a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/menubar/CreateIndexDialogFactory.java b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/menubar/CreateIndexDialogFactory.java index 995162e035b..223fc4fabf3 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/menubar/CreateIndexDialogFactory.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/menubar/CreateIndexDialogFactory.java @@ -35,6 +35,8 @@ import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.JButton; @@ -47,7 +49,6 @@ import javax.swing.JSeparator; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.SwingWorker; -import org.apache.logging.log4j.Logger; import org.apache.lucene.luke.app.IndexHandler; import org.apache.lucene.luke.app.desktop.Preferences; import org.apache.lucene.luke.app.desktop.PreferencesFactory; @@ -337,7 +338,7 @@ public class CreateIndexDialogFactory implements DialogOpener.DialogFactory { IOException ex2) { } - log.error("Cannot create index", ex); + log.log(Level.SEVERE, "Cannot create index", ex); String message = "See Logs tab or log file for more details."; JOptionPane.showMessageDialog( dialog, message, "Cannot create index", JOptionPane.ERROR_MESSAGE); diff --git a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/menubar/ExportTermsDialogFactory.java b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/menubar/ExportTermsDialogFactory.java index 87377e3bac8..3bf84a219d6 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/menubar/ExportTermsDialogFactory.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/menubar/ExportTermsDialogFactory.java @@ -31,6 +31,8 @@ import java.lang.invoke.MethodHandles; import java.util.Arrays; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.stream.Stream; import javax.swing.BorderFactory; import javax.swing.BoxLayout; @@ -42,7 +44,6 @@ import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.SwingWorker; -import org.apache.logging.log4j.Logger; import org.apache.lucene.luke.app.IndexHandler; import org.apache.lucene.luke.app.IndexObserver; import org.apache.lucene.luke.app.LukeState; @@ -249,11 +250,11 @@ public final class ExportTermsDialogFactory implements DialogOpener.DialogFactor try { filename = toolsModel.exportTerms(directory, field, selectedDelimiter); } catch (LukeException e) { - log.error("Error while exporting terms from field {}", field, e); + log.log(Level.SEVERE, "Error while exporting terms from field " + field, e); statusLbl.setText( MessageUtils.getLocalizedMessage("export.terms.label.error", e.getMessage())); } catch (Exception e) { - log.error("Error while exporting terms from field {}", field, e); + log.log(Level.SEVERE, "Error while exporting terms from field " + field, e); statusLbl.setText(MessageUtils.getLocalizedMessage("message.error.unknown")); throw e; } finally { diff --git a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/menubar/OpenIndexDialogFactory.java b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/menubar/OpenIndexDialogFactory.java index a523cd4b111..30e3d0bde59 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/menubar/OpenIndexDialogFactory.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/menubar/OpenIndexDialogFactory.java @@ -32,6 +32,8 @@ import java.nio.file.Paths; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.ButtonGroup; @@ -45,7 +47,6 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JSeparator; -import org.apache.logging.log4j.Logger; import org.apache.lucene.luke.app.DirectoryHandler; import org.apache.lucene.luke.app.IndexHandler; import org.apache.lucene.luke.app.desktop.Preferences; @@ -345,7 +346,7 @@ public final class OpenIndexDialogFactory implements DialogOpener.DialogFactory MessageUtils.getLocalizedMessage("message.error.unknown"), "Unknown Error", JOptionPane.ERROR_MESSAGE); - log.error("Error opening index or directory", cause); + log.log(Level.SEVERE, "Error opening index or directory", cause); } } diff --git a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/util/ExceptionHandler.java b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/util/ExceptionHandler.java index 481047c631d..d02e4523185 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/util/ExceptionHandler.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/util/ExceptionHandler.java @@ -18,7 +18,8 @@ package org.apache.lucene.luke.app.desktop.util; import java.lang.invoke.MethodHandles; -import org.apache.logging.log4j.Logger; +import java.util.logging.Level; +import java.util.logging.Logger; import org.apache.lucene.luke.app.desktop.MessageBroker; import org.apache.lucene.luke.models.LukeException; import org.apache.lucene.luke.util.LoggerFactory; @@ -32,10 +33,10 @@ public final class ExceptionHandler { if (t instanceof LukeException) { Throwable cause = t.getCause(); String message = (cause == null) ? t.getMessage() : t.getMessage() + " " + cause.getMessage(); - log.warn("Uncaught LukeException", t); + log.log(Level.WARNING, "Uncaught LukeException", t); messageBroker.showStatusMessage(message); } else { - log.error("Uncaught Exception", t); + log.log(Level.SEVERE, "Uncaught Exception", t); messageBroker.showUnknownErrorMessage(); } } diff --git a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/util/TextAreaAppender.java b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/util/TextAreaAppender.java deleted file mode 100644 index 3d6964ae00c..00000000000 --- a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/util/TextAreaAppender.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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.apache.lucene.luke.app.desktop.util; - -import java.io.Serializable; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import javax.swing.JTextArea; -import javax.swing.SwingUtilities; -import org.apache.logging.log4j.core.Appender; -import org.apache.logging.log4j.core.Core; -import org.apache.logging.log4j.core.Filter; -import org.apache.logging.log4j.core.LogEvent; -import org.apache.logging.log4j.core.StringLayout; -import org.apache.logging.log4j.core.appender.AbstractAppender; -import org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender; -import org.apache.logging.log4j.core.config.Property; -import org.apache.logging.log4j.core.config.plugins.Plugin; -import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory; - -/** Log appender for text areas */ -@Plugin( - name = "TextArea", - category = Core.CATEGORY_NAME, - elementType = Appender.ELEMENT_TYPE, - printObject = true) -public final class TextAreaAppender extends AbstractAppender { - - private static JTextArea textArea; - - private static final ReadWriteLock rwLock = new ReentrantReadWriteLock(); - private static final Lock readLock = rwLock.readLock(); - private static final Lock writeLock = rwLock.writeLock(); - - protected TextAreaAppender( - String name, - Filter filter, - org.apache.logging.log4j.core.Layout layout, - final boolean ignoreExceptions) { - super(name, filter, layout, ignoreExceptions, Property.EMPTY_ARRAY); - } - - public static void setTextArea(JTextArea ta) { - writeLock.lock(); - try { - if (textArea != null) { - throw new IllegalStateException("TextArea already set."); - } - textArea = ta; - } finally { - writeLock.unlock(); - } - } - - @Override - public void append(LogEvent event) { - readLock.lock(); - try { - if (textArea == null) { - // just ignore any events logged before the area is available - return; - } - - final String message = ((StringLayout) getLayout()).toSerializable(event); - SwingUtilities.invokeLater( - () -> { - textArea.append(message); - }); - } finally { - readLock.unlock(); - } - } - - /** - * Builds TextAreaAppender instances. - * - * @param The type to build - */ - public static class Builder> extends AbstractOutputStreamAppender.Builder - implements org.apache.logging.log4j.core.util.Builder { - - @Override - public TextAreaAppender build() { - return new TextAreaAppender(getName(), getFilter(), getOrCreateLayout(), true); - } - } - - @PluginBuilderFactory - public static > B newBuilder() { - return new Builder().asBuilder(); - } -} diff --git a/lucene/luke/src/java/org/apache/lucene/luke/models/commits/CommitsImpl.java b/lucene/luke/src/java/org/apache/lucene/luke/models/commits/CommitsImpl.java index 59b50a2b81d..a103eee9ce1 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/models/commits/CommitsImpl.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/models/commits/CommitsImpl.java @@ -26,8 +26,8 @@ import java.util.Locale; import java.util.Map; import java.util.Optional; import java.util.TreeMap; +import java.util.logging.Logger; import java.util.stream.Collectors; -import org.apache.logging.log4j.Logger; import org.apache.lucene.codecs.Codec; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.IndexCommit; @@ -98,7 +98,7 @@ public final class CommitsImpl extends LukeModel implements Commits { if (ic == null) { String msg = String.format(Locale.ENGLISH, "Commit generation %d not exists.", commitGen); - log.warn(msg); + log.warning(msg); return Optional.empty(); } @@ -111,7 +111,7 @@ public final class CommitsImpl extends LukeModel implements Commits { if (ic == null) { String msg = String.format(Locale.ENGLISH, "Commit generation %d not exists.", commitGen); - log.warn(msg); + log.warning(msg); return Collections.emptyList(); } diff --git a/lucene/luke/src/java/org/apache/lucene/luke/models/documents/DocumentsImpl.java b/lucene/luke/src/java/org/apache/lucene/luke/models/documents/DocumentsImpl.java index 84daec9cc2d..9e36d4ffaeb 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/models/documents/DocumentsImpl.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/models/documents/DocumentsImpl.java @@ -25,7 +25,7 @@ import java.util.List; import java.util.Locale; import java.util.Objects; import java.util.Optional; -import org.apache.logging.log4j.Logger; +import java.util.logging.Logger; import org.apache.lucene.document.Document; import org.apache.lucene.index.FieldInfo; import org.apache.lucene.index.IndexReader; @@ -80,7 +80,7 @@ public final class DocumentsImpl extends LukeModel implements Documents { @Override public List getDocumentFields(int docid) { if (!isLive(docid)) { - log.info("Doc #{} was deleted", docid); + log.info("Doc #" + docid + " was deleted"); return Collections.emptyList(); } @@ -126,7 +126,7 @@ public final class DocumentsImpl extends LukeModel implements Documents { // no such field? resetCurrentField(); resetTermsIterator(); - log.warn("Terms not available for field: {}.", field); + log.warning("Terms not available for field: " + field); return Optional.empty(); } else { setCurrentField(field); @@ -135,7 +135,7 @@ public final class DocumentsImpl extends LukeModel implements Documents { if (tenum.next() == null) { // no term available for this field resetTermsIterator(); - log.warn("No term available for field: {}.", field); + log.warning("No term available for field: " + field); return Optional.empty(); } else { return Optional.of(new Term(curField, tenum.term())); @@ -156,7 +156,7 @@ public final class DocumentsImpl extends LukeModel implements Documents { public Optional nextTerm() { if (tenum == null) { // terms enum not initialized - log.warn("Terms enum un-positioned."); + log.warning("Terms enum un-positioned."); return Optional.empty(); } @@ -164,7 +164,7 @@ public final class DocumentsImpl extends LukeModel implements Documents { if (tenum.next() == null) { // end of the iterator resetTermsIterator(); - log.info("Reached the end of the term iterator for field: {}.", curField); + log.info("Reached the end of the term iterator for field: " + curField); return Optional.empty(); } else { @@ -186,7 +186,7 @@ public final class DocumentsImpl extends LukeModel implements Documents { if (curField == null) { // field is not selected - log.warn("Field not selected."); + log.warning("Field not selected."); return Optional.empty(); } @@ -197,7 +197,7 @@ public final class DocumentsImpl extends LukeModel implements Documents { if (tenum.seekCeil(new BytesRef(termText)) == TermsEnum.SeekStatus.END) { // reached to the end of the iterator resetTermsIterator(); - log.info("Reached the end of the term iterator for field: {}.", curField); + log.info("Reached the end of the term iterator for field: " + curField); return Optional.empty(); } else { return Optional.of(new Term(curField, tenum.term())); @@ -216,7 +216,7 @@ public final class DocumentsImpl extends LukeModel implements Documents { public Optional firstTermDoc() { if (tenum == null) { // terms enum is not set - log.warn("Terms enum un-positioned."); + log.warning("Terms enum un-positioned."); return Optional.empty(); } @@ -226,10 +226,11 @@ public final class DocumentsImpl extends LukeModel implements Documents { if (penum.nextDoc() == PostingsEnum.NO_MORE_DOCS) { // no docs available for this term resetPostingsIterator(); - log.warn( - "No docs available for term: {} in field: {}.", - BytesRefUtils.decode(tenum.term()), - curField); + log.warning( + "No docs available for term: " + + BytesRefUtils.decode(tenum.term()) + + " in field: " + + curField); return Optional.empty(); } else { return Optional.of(penum.docID()); @@ -245,7 +246,7 @@ public final class DocumentsImpl extends LukeModel implements Documents { public Optional nextTermDoc() { if (penum == null) { // postings enum is not initialized - log.warn("Postings enum un-positioned for field: {}.", curField); + log.warning("Postings enum un-positioned for field: " + curField); return Optional.empty(); } @@ -253,12 +254,11 @@ public final class DocumentsImpl extends LukeModel implements Documents { if (penum.nextDoc() == PostingsEnum.NO_MORE_DOCS) { // end of the iterator resetPostingsIterator(); - if (log.isInfoEnabled()) { - log.info( - "Reached the end of the postings iterator for term: {} in field: {}", - BytesRefUtils.decode(tenum.term()), - curField); - } + log.info( + "Reached the end of the postings iterator for term: " + + BytesRefUtils.decode(tenum.term()) + + " in field: " + + curField); return Optional.empty(); } else { return Optional.of(penum.docID()); @@ -274,7 +274,7 @@ public final class DocumentsImpl extends LukeModel implements Documents { public List getTermPositions() { if (penum == null) { // postings enum is not initialized - log.warn("Postings enum un-positioned for field: {}.", curField); + log.warning("Postings enum un-positioned for field: " + curField); return Collections.emptyList(); } @@ -305,7 +305,7 @@ public final class DocumentsImpl extends LukeModel implements Documents { public Optional getDocFreq() { if (tenum == null) { // terms enum is not initialized - log.warn("Terms enum un-positioned for field: {}.", curField); + log.warning("Terms enum un-positioned for field: " + curField); return Optional.empty(); } diff --git a/lucene/luke/src/java/org/apache/lucene/luke/models/documents/TermVectorsAdapter.java b/lucene/luke/src/java/org/apache/lucene/luke/models/documents/TermVectorsAdapter.java index 64d8552a464..bfdd227d023 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/models/documents/TermVectorsAdapter.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/models/documents/TermVectorsAdapter.java @@ -22,8 +22,9 @@ import java.lang.invoke.MethodHandles; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Locale; import java.util.Objects; -import org.apache.logging.log4j.Logger; +import java.util.logging.Logger; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.Terms; import org.apache.lucene.index.TermsEnum; @@ -53,7 +54,10 @@ final class TermVectorsAdapter { Terms termVector = reader.getTermVector(docid, field); if (termVector == null) { // no term vector available - log.warn("No term vector indexed for doc: #{} and field: {}", docid, field); + log.warning( + () -> + String.format( + Locale.ROOT, "No term vector indexed for doc: #%s and field: %s", docid, field)); return Collections.emptyList(); } diff --git a/lucene/luke/src/java/org/apache/lucene/luke/models/search/SearchImpl.java b/lucene/luke/src/java/org/apache/lucene/luke/models/search/SearchImpl.java index a1122a3118d..c4b96297d18 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/models/search/SearchImpl.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/models/search/SearchImpl.java @@ -30,8 +30,8 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.logging.Logger; import java.util.stream.Collectors; -import org.apache.logging.log4j.Logger; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.index.DocValuesType; import org.apache.lucene.index.FieldInfo; @@ -230,7 +230,7 @@ public final class SearchImpl extends LukeModel implements Search { } else if (type == Float.class || type == Double.class) { pc = new PointsConfig(NumberFormat.getNumberInstance(Locale.ROOT), type); } else { - log.warn( + log.warning( String.format(Locale.ENGLISH, "Ignored invalid number type: %s.", type.getName())); continue; } @@ -344,7 +344,7 @@ public final class SearchImpl extends LukeModel implements Search { if (totalHits.value == 0 || (totalHits.relation == TotalHits.Relation.EQUAL_TO && currentPage * pageSize >= totalHits.value)) { - log.warn("No more next search results are available."); + log.warning("No more next search results are available."); return Optional.empty(); } @@ -375,7 +375,7 @@ public final class SearchImpl extends LukeModel implements Search { currentPage -= 1; if (currentPage < 0) { - log.warn("No more previous search results are available."); + log.warning("No more previous search results are available."); return Optional.empty(); } @@ -462,7 +462,7 @@ public final class SearchImpl extends LukeModel implements Search { Objects.requireNonNull(type); List candidates = guessSortTypes(name); if (candidates.isEmpty()) { - log.warn(String.format(Locale.ENGLISH, "No available sort types for: %s", name)); + log.warning(String.format(Locale.ENGLISH, "No available sort types for: %s", name)); return Optional.empty(); } diff --git a/lucene/luke/src/java/org/apache/lucene/luke/models/util/IndexUtils.java b/lucene/luke/src/java/org/apache/lucene/luke/models/util/IndexUtils.java index 27cd107b0f9..e616116114d 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/models/util/IndexUtils.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/models/util/IndexUtils.java @@ -34,9 +34,10 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.stream.Collectors; import java.util.stream.StreamSupport; -import org.apache.logging.log4j.Logger; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.core.WhitespaceAnalyzer; import org.apache.lucene.codecs.CodecUtil; @@ -84,7 +85,7 @@ public final class IndexUtils { DirectoryReader dr = DirectoryReader.open(dir); readers.add(dr); } catch (IOException e) { - log.warn("Error opening directory", e); + log.log(Level.WARNING, "Error opening directory", e); } return FileVisitResult.CONTINUE; } @@ -94,14 +95,12 @@ public final class IndexUtils { throw new RuntimeException("No valid directory at the location: " + indexPath); } - if (log.isInfoEnabled()) { - log.info( - String.format( - Locale.ENGLISH, - "IndexReaders (%d leaf readers) successfully opened. Index path=%s", - readers.size(), - indexPath)); - } + log.info( + String.format( + Locale.ENGLISH, + "IndexReaders (%d leaf readers) successfully opened. Index path=%s", + readers.size(), + indexPath)); if (readers.size() == 1) { return readers.get(0); @@ -134,11 +133,9 @@ public final class IndexUtils { public static Directory openDirectory(String dirPath, String dirImpl) throws IOException { final Path path = FileSystems.getDefault().getPath(Objects.requireNonNull(dirPath)); Directory dir = openDirectory(path, dirImpl); - if (log.isInfoEnabled()) { - log.info( - String.format( - Locale.ENGLISH, "DirectoryReader successfully opened. Directory path=%s", dirPath)); - } + log.info( + String.format( + Locale.ENGLISH, "DirectoryReader successfully opened. Directory path=%s", dirPath)); return dir; } @@ -161,7 +158,7 @@ public final class IndexUtils { dir = (Directory) constr.newInstance(path, null); } } catch (Exception e) { - log.warn("Invalid directory implementation class: {}", dirImpl, e); + log.log(Level.WARNING, "Invalid directory implementation class: " + dirImpl, e); throw new IllegalArgumentException("Invalid directory implementation class: " + dirImpl); } } @@ -180,7 +177,7 @@ public final class IndexUtils { log.info("Directory successfully closed."); } } catch (IOException e) { - log.error("Error closing directory", e); + log.log(Level.SEVERE, "Error closing directory", e); } } @@ -201,7 +198,7 @@ public final class IndexUtils { } } } catch (IOException e) { - log.error("Error closing index reader", e); + log.log(Level.SEVERE, "Error closing index reader", e); } } diff --git a/lucene/luke/src/java/org/apache/lucene/luke/models/util/twentynewsgroups/MessageFilesParser.java b/lucene/luke/src/java/org/apache/lucene/luke/models/util/twentynewsgroups/MessageFilesParser.java index c5b5d0db516..41db69b2f18 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/models/util/twentynewsgroups/MessageFilesParser.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/models/util/twentynewsgroups/MessageFilesParser.java @@ -28,7 +28,8 @@ import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.List; -import org.apache.logging.log4j.Logger; +import java.util.logging.Level; +import java.util.logging.Logger; import org.apache.lucene.luke.util.LoggerFactory; /** @@ -56,10 +57,8 @@ public class MessageFilesParser extends SimpleFileVisitor { messages.add(parse(file)); } } - } catch ( - @SuppressWarnings("unused") - IOException e) { - log.warn("Invalid file? {}", file); + } catch (IOException e) { + log.log(Level.WARNING, "Invalid file? " + file, e); } return FileVisitResult.CONTINUE; } diff --git a/lucene/luke/src/java/org/apache/lucene/luke/util/CircularLogBufferHandler.java b/lucene/luke/src/java/org/apache/lucene/luke/util/CircularLogBufferHandler.java new file mode 100644 index 00000000000..e0ad6f7dcf3 --- /dev/null +++ b/lucene/luke/src/java/org/apache/lucene/luke/util/CircularLogBufferHandler.java @@ -0,0 +1,114 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.lucene.luke.util; + +import java.time.Instant; +import java.util.ArrayDeque; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.function.Consumer; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogRecord; + +/** A {@link Handler} with a bounded buffer of recent log messages. */ +public class CircularLogBufferHandler extends Handler { + /** Provides an immutable clone of the required data from a {@link LogRecord} logged elsewhere. */ + public static final class ImmutableLogRecord { + private final String loggerName; + private final Level level; + private final String message; + private final Throwable thrown; + private final Instant instant; + + public ImmutableLogRecord(LogRecord record) { + this.loggerName = record.getLoggerName(); + this.level = record.getLevel(); + this.message = record.getMessage(); + this.thrown = record.getThrown(); + this.instant = record.getInstant(); + } + + public String getLoggerName() { + return loggerName; + } + + public Level getLevel() { + return level; + } + + public String getMessage() { + return message; + } + + public Throwable getThrown() { + return thrown; + } + + public Instant getInstant() { + return instant; + } + } + + /** Listeners receiving log state updates. */ + public interface LogUpdateListener extends Consumer> {} + + /** A bounded buffer of immutable log records that have been recently logged by the framework. */ + private final ArrayDeque buffer = new ArrayDeque<>(); + + /** + * Listeners interested in receiving log state updates. At the moment listeners receive an + * iterable with all log records in the circular buffer. We could make it incremental for each + * consumer but for Luke it really doesn't matter since the rate of updates is very small. + */ + private final List listeners = new CopyOnWriteArrayList<>(); + + @Override + public void publish(LogRecord record) { + synchronized (buffer) { + buffer.addLast(new ImmutableLogRecord(record)); + listeners.forEach(c -> c.accept(buffer)); + } + } + + @Override + public void flush() { + // Ignore. + } + + @Override + public void close() throws SecurityException { + // Ignore. + } + + public void addUpdateListener(LogUpdateListener listener) { + listeners.add(listener); + } + + public void removeUpdateListener(LogUpdateListener listener) { + listeners.remove(listener); + } + + /** @return Return a clone of the buffered records so far. */ + public Collection getLogRecords() { + synchronized (buffer) { + return new ArrayDeque<>(buffer); + } + } +} diff --git a/lucene/luke/src/java/org/apache/lucene/luke/util/LoggerFactory.java b/lucene/luke/src/java/org/apache/lucene/luke/util/LoggerFactory.java index a1a91848059..6f134a73a25 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/util/LoggerFactory.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/util/LoggerFactory.java @@ -17,54 +17,28 @@ package org.apache.lucene.luke.util; -import java.nio.charset.StandardCharsets; -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.core.Appender; -import org.apache.logging.log4j.core.LoggerContext; -import org.apache.logging.log4j.core.appender.FileAppender; -import org.apache.logging.log4j.core.config.Configurator; -import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder; -import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory; -import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration; -import org.apache.logging.log4j.core.layout.PatternLayout; -import org.apache.lucene.luke.app.desktop.util.TextAreaAppender; +import java.util.logging.Level; +import java.util.logging.Logger; -/** Logger factory. This programmatically configurates logger context (Appenders etc.) */ +/** Logger factory. This configures log interceptors for the GUI. */ public class LoggerFactory { + public static CircularLogBufferHandler circularBuffer; - public static void initGuiLogging(String logFile) { - ConfigurationBuilder builder = - ConfigurationBuilderFactory.newConfigurationBuilder(); - builder.add(builder.newRootLogger(Level.INFO)); - LoggerContext context = Configurator.initialize(builder.build()); + public static void initGuiLogging() { + if (circularBuffer != null) { + throw new RuntimeException("Double-initialization?"); + } - PatternLayout layout = - PatternLayout.newBuilder() - .withPattern("[%d{ISO8601}] %5p (%F:%L) - %m%n") - .withCharset(StandardCharsets.UTF_8) - .build(); + circularBuffer = new CircularLogBufferHandler(); + circularBuffer.setLevel(Level.FINEST); - Appender fileAppender = - FileAppender.newBuilder() - .setName("File") - .setLayout(layout) - .withFileName(logFile) - .withAppend(false) - .build(); - fileAppender.start(); - - Appender textAreaAppender = - TextAreaAppender.newBuilder().setName("TextArea").setLayout(layout).build(); - textAreaAppender.start(); - - context.getRootLogger().addAppender(fileAppender); - context.getRootLogger().addAppender(textAreaAppender); - context.updateLoggers(); + // Only capture events from Lucene logger hierarchy. + var luceneRoot = Logger.getLogger("org.apache.lucene"); + luceneRoot.setLevel(Level.FINEST); + luceneRoot.addHandler(circularBuffer); } public static Logger getLogger(Class clazz) { - return LogManager.getLogger(clazz); + return Logger.getLogger(clazz.getName()); } } diff --git a/lucene/luke/src/resources/org/apache/lucene/luke/app/desktop/messages/messages.properties b/lucene/luke/src/resources/org/apache/lucene/luke/app/desktop/messages/messages.properties index e8143297121..8e91e51bc5f 100644 --- a/lucene/luke/src/resources/org/apache/lucene/luke/app/desktop/messages/messages.properties +++ b/lucene/luke/src/resources/org/apache/lucene/luke/app/desktop/messages/messages.properties @@ -280,7 +280,7 @@ commits.label.files=Files commits.label.segments=Segments (click rows for more details) commits.label.segdetails=Segment details # Logs -logs.label.see_also=See also: +logs.label.level=Log level: # Help dialogs help.fieldtype.TextField=A field that is indexed and tokenized, without term vectors.\n\n(Example Values)\n- Hello Lucene! help.fieldtype.StringField=A field that is indexed but not tokenized: the entire String value is indexed as a single token.\n\n(Example Values)\n- Java diff --git a/versions.lock b/versions.lock index 80f63aac0d0..87c5b3f55d2 100644 --- a/versions.lock +++ b/versions.lock @@ -12,8 +12,6 @@ org.antlr:antlr4-runtime:4.5.1-1 (1 constraints: 6a05b240) org.apache.commons:commons-compress:1.19 (1 constraints: df04fa30) org.apache.httpcomponents:httpclient:4.5.13 (1 constraints: 3f054e3b) org.apache.httpcomponents:httpcore:4.4.13 (1 constraints: 591016a2) -org.apache.logging.log4j:log4j-api:2.15.0 (1 constraints: bb0e1f76) -org.apache.logging.log4j:log4j-core:2.15.0 (1 constraints: 3a053e3b) org.apache.opennlp:opennlp-tools:1.9.1 (1 constraints: 0d050c36) org.carrot2:morfologik-fsa:2.1.8 (1 constraints: da0d9b36) org.carrot2:morfologik-polish:2.1.8 (1 constraints: 0d050036) diff --git a/versions.props b/versions.props index 185bcfcbccb..c0103925617 100644 --- a/versions.props +++ b/versions.props @@ -10,7 +10,6 @@ net.sourceforge.nekohtml:nekohtml=1.9.17 org.antlr:antlr4*=4.5.1-1 org.apache.commons:commons-compress=1.19 org.apache.httpcomponents:httpclient=4.5.13 -org.apache.logging.log4j:*=2.15.0 org.apache.opennlp:opennlp-tools=1.9.1 org.carrot2:morfologik-*=2.1.8 org.eclipse.jetty:*=9.4.41.v20210516 From 8e8a94a2b73a030598fc3e1b6205f9ce7af1ae3d Mon Sep 17 00:00:00 2001 From: Tomoko Uchida Date: Thu, 16 Dec 2021 19:39:20 +0900 Subject: [PATCH 08/12] LUCENE-10303: remove unnecessary changes entry --- lucene/CHANGES.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index 9b98105abf4..ec15b4c922f 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -112,8 +112,6 @@ Other * LUCENE-10284: Upgrade morfologik-stemming to 2.1.8. (Dawid Weiss) -* LUCENE-10303: Upgrade log4j to 2.15.0. (Tomoko Uchida) - * LUCENE-10310: TestXYDocValuesQueries#doRandomDistanceTest does not produce random circles with radius with '0' value any longer. From 2b07bcef2e218debfef8007f1278d10eac111e22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20H=C3=B8ydahl?= Date: Thu, 16 Dec 2021 12:11:26 +0100 Subject: [PATCH 09/12] Add bugfix version 8.11.1 --- lucene/CHANGES.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index ec15b4c922f..5994320f2e5 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -577,6 +577,12 @@ Other * LUCENE-10024: Catch NoSuchFileException when opening index directory with Luke. (Michael Wechner, Tomoko Uchida) +======================= Lucene 8.11.1 ======================= + +Bug Fixes +--------------------- +* SOLR-15843: Update Log4J to 2.16 (Mike Drob, janhoy) + ======================= Lucene 8.11.0 ======================= API Changes From 8c48475c4d8eb3296cc2da7adbad4d8634b03116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20H=C3=B8ydahl?= Date: Thu, 16 Dec 2021 13:07:00 +0100 Subject: [PATCH 10/12] Add java version mapping for lucene 10 --- dev-tools/scripts/releaseWizard.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/scripts/releaseWizard.py b/dev-tools/scripts/releaseWizard.py index ab97ba1389f..53052705896 100755 --- a/dev-tools/scripts/releaseWizard.py +++ b/dev-tools/scripts/releaseWizard.py @@ -67,7 +67,7 @@ from consolemenu.screen import Screen from scriptutil import BranchType, Version, download, run # Lucene-to-Java version mapping -java_versions = {6: 8, 7: 8, 8: 8, 9: 11} +java_versions = {6: 8, 7: 8, 8: 8, 9: 11, 10: 11} editor = None # Edit this to add other global jinja2 variables or filters From 05cb0fd0c15c1ca07c304ac8518020a8e7fbc7bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20H=C3=B8ydahl?= Date: Thu, 16 Dec 2021 15:09:28 +0100 Subject: [PATCH 11/12] Add back-compat indices for 8.11.1 --- .../TestBackwardsCompatibility.java | 11 +++++++++-- .../backward_index/unsupported.8.11.1-cfs.zip | Bin 0 -> 26151 bytes .../backward_index/unsupported.8.11.1-nocfs.zip | Bin 0 -> 16946 bytes 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 lucene/backward-codecs/src/test/org/apache/lucene/backward_index/unsupported.8.11.1-cfs.zip create mode 100644 lucene/backward-codecs/src/test/org/apache/lucene/backward_index/unsupported.8.11.1-nocfs.zip diff --git a/lucene/backward-codecs/src/test/org/apache/lucene/backward_index/TestBackwardsCompatibility.java b/lucene/backward-codecs/src/test/org/apache/lucene/backward_index/TestBackwardsCompatibility.java index e2bf98f6ad4..442ae7355fa 100644 --- a/lucene/backward-codecs/src/test/org/apache/lucene/backward_index/TestBackwardsCompatibility.java +++ b/lucene/backward-codecs/src/test/org/apache/lucene/backward_index/TestBackwardsCompatibility.java @@ -334,13 +334,18 @@ public class TestBackwardsCompatibility extends LuceneTestCase { } } - static final String[] oldNames = {"9.0.0-cfs", "9.0.0-nocfs"}; + static final String[] oldNames = { + "9.0.0-cfs", // Force on separate lines + "9.0.0-nocfs", + }; public static String[] getOldNames() { return oldNames; } - static final String[] oldSortedNames = {"sorted.9.0.0"}; + static final String[] oldSortedNames = { + "sorted.9.0.0", // Force on separate lines + }; public static String[] getOldSortedNames() { return oldSortedNames; @@ -590,6 +595,8 @@ public class TestBackwardsCompatibility extends LuceneTestCase { "8.10.1-nocfs", "8.11.0-cfs", "8.11.0-nocfs", + "8.11.1-cfs", + "8.11.1-nocfs" }; static final int MIN_BINARY_SUPPORTED_MAJOR = Version.MIN_SUPPORTED_MAJOR - 1; diff --git a/lucene/backward-codecs/src/test/org/apache/lucene/backward_index/unsupported.8.11.1-cfs.zip b/lucene/backward-codecs/src/test/org/apache/lucene/backward_index/unsupported.8.11.1-cfs.zip new file mode 100644 index 0000000000000000000000000000000000000000..7bae78155d09d7e2775ff7fe27eab626e87ba984 GIT binary patch literal 26151 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 RNp|tN*p~u4zxWgY@L!I1Hq-zB literal 0 HcmV?d00001 diff --git a/lucene/backward-codecs/src/test/org/apache/lucene/backward_index/unsupported.8.11.1-nocfs.zip b/lucene/backward-codecs/src/test/org/apache/lucene/backward_index/unsupported.8.11.1-nocfs.zip new file mode 100644 index 0000000000000000000000000000000000000000..e5edb182e440e422081f978e0c499865fce7f582 GIT binary patch literal 16946 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 Yf29Wn{j+SMzdUtcwtF2fcL4zZ2a(wt0RR91 literal 0 HcmV?d00001 From e7b4700c5a79f2cd844059f72cfff3da49a2bb29 Mon Sep 17 00:00:00 2001 From: Tomoko Uchida Date: Thu, 16 Dec 2021 23:38:32 +0900 Subject: [PATCH 12/12] LUCENE-10313: minor clean-ups and follow-ups (#546) --- .../desktop/components/LogsPanelProvider.java | 51 ++++++------------ .../menubar/CreateIndexDialogFactory.java | 2 +- .../menubar/OpenIndexDialogFactory.java | 2 +- .../luke/util/CircularLogBufferHandler.java | 4 +- .../lucene/luke/util/LogRecordFormatter.java | 53 +++++++++++++++++++ 5 files changed, 74 insertions(+), 38 deletions(-) create mode 100644 lucene/luke/src/java/org/apache/lucene/luke/util/LogRecordFormatter.java diff --git a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/LogsPanelProvider.java b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/LogsPanelProvider.java index 26bf9fb725c..4ddd2b2db7d 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/LogsPanelProvider.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/LogsPanelProvider.java @@ -18,21 +18,19 @@ package org.apache.lucene.luke.app.desktop.components; import java.awt.*; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.StringSelection; import java.awt.event.HierarchyEvent; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.time.ZoneId; -import java.time.format.DateTimeFormatter; import java.util.ArrayList; -import java.util.Locale; import java.util.Objects; import java.util.function.Function; import java.util.logging.Level; import java.util.stream.Collectors; import javax.swing.*; +import org.apache.lucene.luke.app.desktop.util.FontUtils; import org.apache.lucene.luke.app.desktop.util.MessageUtils; import org.apache.lucene.luke.util.CircularLogBufferHandler; +import org.apache.lucene.luke.util.LogRecordFormatter; import org.apache.lucene.luke.util.LoggerFactory; /** Provider of the Logs panel */ @@ -67,6 +65,18 @@ public final class LogsPanelProvider { var logTextArea = createLogPanel(logFilter); + JButton copyBtn = + new JButton( + FontUtils.elegantIconHtml("", MessageUtils.getLocalizedMessage("button.copy"))); + copyBtn.setMargin(new Insets(3, 3, 3, 3)); + copyBtn.addActionListener( + e -> { + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + StringSelection selection = new StringSelection(logTextArea.getText()); + clipboard.setContents(selection, null); + }); + header.add(copyBtn); + panel.add(header, BorderLayout.PAGE_START); panel.add(new JScrollPane(logTextArea), BorderLayout.CENTER); return panel; @@ -77,33 +87,6 @@ public final class LogsPanelProvider { JTextArea logTextArea = new JTextArea(); logTextArea.setEditable(false); - class LogRecordFormatter - implements Function { - @Override - public String apply(CircularLogBufferHandler.ImmutableLogRecord record) { - return String.format( - Locale.ROOT, - "%s [%s] %s: %s", - DateTimeFormatter.ofPattern("HH:mm:ss", Locale.ROOT) - .format(record.getInstant().atZone(ZoneId.systemDefault())), - record.getLevel(), - record.getLoggerName(), - record.getMessage() - + (record.getThrown() == null ? "" : "\n" + toString(record.getThrown()))); - } - - private String toString(Throwable t) { - try (StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw)) { - t.printStackTrace(pw); - pw.flush(); - return sw.toString(); - } catch (IOException e) { - return "Could not dump stack trace: " + e.getMessage(); - } - } - } - // Hook into live data from the circular log buffer and update the initial state. Function formatter = new LogRecordFormatter(); @@ -118,7 +101,7 @@ public final class LogsPanelProvider { String logContent = clonedCopy.stream() - .filter(record -> record.getLevel().intValue() > level.intValue()) + .filter(record -> record.getLevel().intValue() >= level.intValue()) .map(formatter::apply) .collect(Collectors.joining("\n")); diff --git a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/menubar/CreateIndexDialogFactory.java b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/menubar/CreateIndexDialogFactory.java index 223fc4fabf3..747d5da43fc 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/menubar/CreateIndexDialogFactory.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/menubar/CreateIndexDialogFactory.java @@ -339,7 +339,7 @@ public class CreateIndexDialogFactory implements DialogOpener.DialogFactory { } log.log(Level.SEVERE, "Cannot create index", ex); - String message = "See Logs tab or log file for more details."; + String message = "See Logs tab for more details."; JOptionPane.showMessageDialog( dialog, message, "Cannot create index", JOptionPane.ERROR_MESSAGE); } finally { diff --git a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/menubar/OpenIndexDialogFactory.java b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/menubar/OpenIndexDialogFactory.java index 30e3d0bde59..0db47ab39b9 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/menubar/OpenIndexDialogFactory.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/app/desktop/components/dialog/menubar/OpenIndexDialogFactory.java @@ -337,7 +337,7 @@ public final class OpenIndexDialogFactory implements DialogOpener.DialogFactory closeDialog(); } catch (LukeException ex) { String message = - ex.getMessage() + System.lineSeparator() + "See Logs tab or log file for more details."; + ex.getMessage() + System.lineSeparator() + "See Logs tab for more details."; JOptionPane.showMessageDialog( dialog, message, "Invalid index path", JOptionPane.ERROR_MESSAGE); } catch (Throwable cause) { diff --git a/lucene/luke/src/java/org/apache/lucene/luke/util/CircularLogBufferHandler.java b/lucene/luke/src/java/org/apache/lucene/luke/util/CircularLogBufferHandler.java index e0ad6f7dcf3..7287cd5a8e0 100644 --- a/lucene/luke/src/java/org/apache/lucene/luke/util/CircularLogBufferHandler.java +++ b/lucene/luke/src/java/org/apache/lucene/luke/util/CircularLogBufferHandler.java @@ -106,9 +106,9 @@ public class CircularLogBufferHandler extends Handler { } /** @return Return a clone of the buffered records so far. */ - public Collection getLogRecords() { + public List getLogRecords() { synchronized (buffer) { - return new ArrayDeque<>(buffer); + return List.copyOf(buffer); } } } diff --git a/lucene/luke/src/java/org/apache/lucene/luke/util/LogRecordFormatter.java b/lucene/luke/src/java/org/apache/lucene/luke/util/LogRecordFormatter.java new file mode 100644 index 00000000000..8f788026b54 --- /dev/null +++ b/lucene/luke/src/java/org/apache/lucene/luke/util/LogRecordFormatter.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.lucene.luke.util; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.Locale; +import java.util.function.Function; + +public class LogRecordFormatter + implements Function { + @Override + public String apply(CircularLogBufferHandler.ImmutableLogRecord record) { + return String.format( + Locale.ROOT, + "%s [%s] %s: %s", + DateTimeFormatter.ofPattern("HH:mm:ss", Locale.ROOT) + .format(record.getInstant().atZone(ZoneId.systemDefault())), + record.getLevel(), + record.getLoggerName(), + record.getMessage() + + (record.getThrown() == null ? "" : "\n" + toString(record.getThrown()))); + } + + private String toString(Throwable t) { + try (StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw)) { + t.printStackTrace(pw); + pw.flush(); + return sw.toString(); + } catch (IOException e) { + return "Could not dump stack trace: " + e.getMessage(); + } + } +}