diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 18272cfe6216..e87696e3e8fc 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -148,6 +148,8 @@ Bug Fixes Deprecation Removals ---------------------- +* SOLR-17957: XLSXResponseWriter has been removed. (Jan Høydahl) + * SOLR-16535: The 'jaegertracer-configurator' module is removed. Please use 'opentelemetry' (janhoy) * SOLR-16601: Removed deprecated methods on the various Solr Clients. (Eric Pugh, Kevin Risden) diff --git a/solr/core/src/java/org/apache/solr/core/SolrCore.java b/solr/core/src/java/org/apache/solr/core/SolrCore.java index 7ac546aa2558..5beca634fe37 100644 --- a/solr/core/src/java/org/apache/solr/core/SolrCore.java +++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java @@ -3097,16 +3097,6 @@ public PluginBag getResponseWriters() { m.put(OPEN_METRICS_WT, new PrometheusResponseWriter()); m.put(ReplicationAPIBase.FILE_STREAM, getFileStreamWriter()); DEFAULT_RESPONSE_WRITERS = Collections.unmodifiableMap(m); - try { - m.put( - "xlsx", - Class.forName("org.apache.solr.handler.extraction.XLSXResponseWriter") - .asSubclass(QueryResponseWriter.class) - .getDeclaredConstructor() - .newInstance()); - } catch (Exception e) { - // don't worry; extraction module not in class path - } } private static JavaBinResponseWriter getFileStreamWriter() { diff --git a/solr/modules/extraction/build.gradle b/solr/modules/extraction/build.gradle index da6ebaccd68a..655fc0360f41 100644 --- a/solr/modules/extraction/build.gradle +++ b/solr/modules/extraction/build.gradle @@ -27,8 +27,6 @@ dependencies { implementation libs.apache.lucene.core implementation libs.slf4j.api - implementation libs.apache.poi.poi - implementation libs.apache.poi.ooxml implementation libs.apache.tika.core implementation (libs.apache.tika.parsers, { exclude group: 'org.apache.cxf', module: 'cxf-rt-rs-client' diff --git a/solr/modules/extraction/src/java/org/apache/solr/handler/extraction/XLSXResponseWriter.java b/solr/modules/extraction/src/java/org/apache/solr/handler/extraction/XLSXResponseWriter.java deleted file mode 100644 index ac8e6c549603..000000000000 --- a/solr/modules/extraction/src/java/org/apache/solr/handler/extraction/XLSXResponseWriter.java +++ /dev/null @@ -1,345 +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.solr.handler.extraction; - -import java.io.CharArrayWriter; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.io.Writer; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import org.apache.lucene.index.IndexableField; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.FillPatternType; -import org.apache.poi.ss.usermodel.Font; -import org.apache.poi.ss.usermodel.IndexedColors; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.xssf.streaming.SXSSFWorkbook; -import org.apache.poi.xssf.usermodel.XSSFCellStyle; -import org.apache.solr.common.SolrDocument; -import org.apache.solr.request.SolrQueryRequest; -import org.apache.solr.response.QueryResponseWriter; -import org.apache.solr.response.SolrQueryResponse; -import org.apache.solr.response.TabularResponseWriter; -import org.apache.solr.schema.FieldType; -import org.apache.solr.schema.SchemaField; -import org.apache.solr.schema.StrField; -import org.apache.solr.search.ReturnFields; - -/** - * A .XLSX spreadsheet format {@link org.apache.solr.response.QueryResponseWriter}. - * - * @deprecated This class will be removed in a future release. - */ -@Deprecated(since = "9.10", forRemoval = true) -public class XLSXResponseWriter implements QueryResponseWriter { - - @Override - public void write( - OutputStream out, SolrQueryRequest req, SolrQueryResponse rsp, String contentType) - throws IOException { - // throw away arraywriter just to satisfy super requirements; we're grabbing - // all writes before they go to it anyway - XLSXWriter w = new XLSXWriter(new CharArrayWriter(), req, rsp); - - LinkedHashMap reqNamesMap = new LinkedHashMap<>(); - LinkedHashMap reqWidthsMap = new LinkedHashMap<>(); - - Iterator paramNamesIter = req.getParams().getParameterNamesIterator(); - while (paramNamesIter.hasNext()) { - String nextParam = paramNamesIter.next(); - if (nextParam.startsWith("colname.")) { - String field = nextParam.substring("colname.".length()); - reqNamesMap.put(field, req.getParams().get(nextParam)); - } else if (nextParam.startsWith("colwidth.")) { - String field = nextParam.substring("colwidth.".length()); - reqWidthsMap.put(field, req.getParams().getInt(nextParam)); - } - } - - try { - w.writeResponse(out, reqNamesMap, reqWidthsMap); - } finally { - w.close(); - } - } - - @Override - public String getContentType(SolrQueryRequest request, SolrQueryResponse response) { - return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; - } -} - -class XLSXWriter extends TabularResponseWriter { - - static class SerialWriteWorkbook { - SXSSFWorkbook swb; - Sheet sh; - - XSSFCellStyle headerStyle; - int rowIndex; - Row curRow; - int cellIndex; - - SerialWriteWorkbook() { - this.swb = new SXSSFWorkbook(100); - this.sh = this.swb.createSheet(); - - this.rowIndex = 0; - - this.headerStyle = (XSSFCellStyle) swb.createCellStyle(); - this.headerStyle.setFillBackgroundColor(IndexedColors.BLACK.getIndex()); - // solid fill - this.headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); - Font headerFont = swb.createFont(); - headerFont.setFontHeightInPoints((short) 14); - headerFont.setBold(true); - headerFont.setColor(IndexedColors.WHITE.getIndex()); - this.headerStyle.setFont(headerFont); - } - - void addRow() { - curRow = sh.createRow(rowIndex++); - cellIndex = 0; - } - - void setHeaderRow() { - curRow.setHeightInPoints((short) 21); - } - - // sets last created cell to have header style - void setHeaderCell() { - curRow.getCell(cellIndex - 1).setCellStyle(this.headerStyle); - } - - // set the width of the most recently created column - void setColWidth(int charWidth) { - // width in poi is units of 1/256th of a character width for some reason - this.sh.setColumnWidth(cellIndex - 1, 256 * charWidth); - } - - void writeCell(String value) { - Cell cell = curRow.createCell(cellIndex++); - cell.setCellValue(value); - } - - void flush(OutputStream out) { - try { - swb.write(out); - } catch (IOException e) { - StringWriter sw = new StringWriter(); - e.printStackTrace(new PrintWriter(sw)); - String stacktrace = sw.toString(); - } finally { - swb.dispose(); - } - } - } - - private SerialWriteWorkbook wb = new SerialWriteWorkbook(); - - static class XLField { - String name; - SchemaField sf; - } - - private Map xlFields = new LinkedHashMap(); - - public XLSXWriter(Writer writer, SolrQueryRequest req, SolrQueryResponse rsp) { - super(writer, req, rsp); - } - - public void writeResponse( - OutputStream out, - LinkedHashMap colNamesMap, - LinkedHashMap colWidthsMap) - throws IOException { - - Collection fields = getFields(); - for (String field : fields) { - if (!returnFields.wantsField(field)) { - continue; - } - if (field.equals("score")) { - XLField xlField = new XLField(); - xlField.name = "score"; - xlFields.put("score", xlField); - continue; - } - - if (shouldSkipField(field)) { - continue; - } - SchemaField sf = schema.getFieldOrNull(field); - if (sf == null) { - FieldType ft = new StrField(); - sf = new SchemaField(field, ft); - } - - XLField xlField = new XLField(); - xlField.name = field; - xlField.sf = sf; - xlFields.put(field, xlField); - } - - wb.addRow(); - // write header - for (XLField xlField : xlFields.values()) { - String printName = xlField.name; - int colWidth = 14; - - String niceName = colNamesMap.get(xlField.name); - if (niceName != null) { - printName = niceName; - } - - Integer niceWidth = colWidthsMap.get(xlField.name); - if (niceWidth != null) { - colWidth = niceWidth.intValue(); - } - - writeStr(xlField.name, printName, false); - wb.setColWidth(colWidth); - wb.setHeaderCell(); - } - wb.setHeaderRow(); - wb.addRow(); - - writeResponse(rsp.getResponse()); - - wb.flush(out); - wb = null; - } - - @Override - public void close() throws IOException { - super.close(); - } - - // NOTE: a document cannot currently contain another document - List tmpList; - - @Override - public void writeSolrDocument(String name, SolrDocument doc, ReturnFields returnFields, int idx) - throws IOException { - if (tmpList == null) { - tmpList = new ArrayList<>(1); - tmpList.add(null); - } - - for (XLField xlField : xlFields.values()) { - Object val = doc.getFieldValue(xlField.name); - int nVals = val instanceof Collection ? ((Collection) val).size() : (val == null ? 0 : 1); - if (nVals == 0) { - writeNull(xlField.name); - continue; - } - - if ((xlField.sf != null && xlField.sf.multiValued()) || nVals > 1) { - Collection values; - // normalize to a collection - if (val instanceof Collection) { - values = (Collection) val; - } else { - tmpList.set(0, val); - values = tmpList; - } - - writeArray(xlField.name, values.iterator(), false); - - } else { - // normalize to first value - if (val instanceof Collection values) { - val = values.iterator().next(); - } - writeVal(xlField.name, val); - } - } - wb.addRow(); - } - - @Override - public void writeStr(String name, String val, boolean needsEscaping) throws IOException { - wb.writeCell(val); - } - - @Override - public void writeArray(String name, Iterator val, boolean raw) throws IOException { - assert !raw; - StringBuilder output = new StringBuilder(); - while (val.hasNext()) { - Object v = val.next(); - if (v instanceof IndexableField f) { - if (v instanceof Date) { - output.append(((Date) val).toInstant().toString()).append("; "); - } else { - output.append(f.stringValue()).append("; "); - } - } else { - output.append(v.toString()).append("; "); - } - } - if (output.length() > 0) { - output.deleteCharAt(output.length() - 1); - output.deleteCharAt(output.length() - 1); - } - writeStr(name, output.toString(), false); - } - - @Override - public void writeNull(String name) throws IOException { - wb.writeCell(""); - } - - @Override - public void writeInt(String name, String val) throws IOException { - wb.writeCell(val); - } - - @Override - public void writeLong(String name, String val) throws IOException { - wb.writeCell(val); - } - - @Override - public void writeBool(String name, String val) throws IOException { - wb.writeCell(val); - } - - @Override - public void writeFloat(String name, String val) throws IOException { - wb.writeCell(val); - } - - @Override - public void writeDouble(String name, String val) throws IOException { - wb.writeCell(val); - } - - @Override - public void writeDate(String name, String val) throws IOException { - wb.writeCell(val); - } -} diff --git a/solr/modules/extraction/src/test/org/apache/solr/handler/extraction/TestXLSXResponseWriter.java b/solr/modules/extraction/src/test/org/apache/solr/handler/extraction/TestXLSXResponseWriter.java deleted file mode 100644 index 8eca2b0105c4..000000000000 --- a/solr/modules/extraction/src/test/org/apache/solr/handler/extraction/TestXLSXResponseWriter.java +++ /dev/null @@ -1,418 +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.solr.handler.extraction; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.time.Instant; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.stream.Collectors; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.xssf.usermodel.XSSFSheet; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.apache.solr.SolrTestCaseJ4; -import org.apache.solr.common.SolrDocument; -import org.apache.solr.common.SolrDocumentList; -import org.apache.solr.core.SolrCore; -import org.apache.solr.request.SolrQueryRequest; -import org.apache.solr.response.QueryResponseWriter; -import org.apache.solr.response.RawResponseWriter; -import org.apache.solr.response.SolrQueryResponse; -import org.apache.solr.search.SolrReturnFields; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -public class TestXLSXResponseWriter extends SolrTestCaseJ4 { - - private static QueryResponseWriter writerXlsx; - - @BeforeClass - public static void beforeClass() throws Exception { - System.setProperty("solr.index.updatelog.enabled", "false"); - initCore("solrconfig.xml", "schema.xml", getFile("extraction/solr").toAbsolutePath()); - createIndex(); - // find a reference to the default response writer so we can redirect its output later - SolrCore testCore = h.getCore(); - QueryResponseWriter writer = testCore.getQueryResponseWriter("xlsx"); - if (writer != null) { - writerXlsx = writer; - } else { - throw new Exception("XLSXResponseWriter not registered with solr core"); - } - } - - public static void createIndex() { - assertU( - adoc( - "id", - "1", - "foo_i", - "-1", - "foo_s", - "hi", - "foo_l", - "12345678987654321", - "foo_b", - "false", - "foo_f", - "1.414", - "foo_d", - "-1.0E300", - "foo_dt1", - "2000-01-02T03:04:05Z")); - assertU( - adoc( - "id", - "2", - "v_ss", - "hi", - "v_ss", - "there", - "v2_ss", - "nice", - "v2_ss", - "output", - "shouldbeunstored", - "foo")); - assertU(adoc("id", "3", "shouldbeunstored", "foo")); - assertU(adoc("id", "4", "foo_s1", "foo")); - assertU(adoc("id", "5", "pubyear_ii", "123", "store_iis", "12", "price_ff", "1.3")); - assertU(commit()); - } - - @AfterClass - public static void cleanupWriter() throws Exception { - writerXlsx = null; - } - - @Test - public void testStructuredDataViaBaseWriters() throws Exception { - SolrQueryResponse rsp = new SolrQueryResponse(); - // Don't send a ContentStream back, this will fall back to the configured base writer. - // But abuse the CONTENT key to ensure writer is also checking type - rsp.add(RawResponseWriter.CONTENT, "test"); - rsp.add("foo", "bar"); - - SolrQueryRequest r = req(); - - // check Content-Type - assertEquals( - "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", - writerXlsx.getContentType(r, rsp)); - - // test our basic types,and that fields come back in the requested order - XSSFSheet resultSheet = - getWSResultForQuery( - req("q", "id:1", "wt", "xlsx", "fl", "id,foo_s,foo_i,foo_l,foo_b,foo_f,foo_d,foo_dt1")); - - assertEquals( - "id,foo_s,foo_i,foo_l,foo_b,foo_f,foo_d,foo_dt1\n1,hi,-1,12345678987654321,F,1.414,-1.0E300,2000-01-02T03:04:05Z\n", - getStringFromSheet(resultSheet)); - - resultSheet = getWSResultForQuery(req("q", "id:1^0", "wt", "xlsx", "fl", "id,score,foo_s")); - // test retrieving score - assertEquals("id,score,foo_s\n1,0.0,hi\n", getStringFromSheet(resultSheet)); - - resultSheet = - getWSResultForQuery( - req( - "q", - "id:1^0", - "wt", - "xlsx", - "colname.id", - "I.D.", - "colwidth.id", - "10", - "fl", - "id,score,foo_s")); - // test override colname/width - assertEquals("I.D.,score,foo_s\n1,0.0,hi\n", getStringFromSheet(resultSheet)); - // test colwidth (value returned is in 256ths of a character as per excel standard) - assertEquals(10 * 256, resultSheet.getColumnWidth(0)); - - resultSheet = getWSResultForQuery(req("q", "id:2", "wt", "xlsx", "fl", "id,v_ss")); - // test multivalued - assertEquals("id,v_ss\n2,hi; there\n", getStringFromSheet(resultSheet)); - - // test retrieving fields from index - resultSheet = getWSResultForQuery(req("q", "*:*", "wt", "xslx", "fl", "*,score")); - String result = getStringFromSheet(resultSheet); - for (String field : - "id,foo_s,foo_i,foo_l,foo_b,foo_f,foo_d,foo_dt1,v_ss,v2_ss,score".split(",")) { - assertTrue(result.contains(field)); - } - - // test null values - resultSheet = getWSResultForQuery(req("q", "id:2", "wt", "xlsx", "fl", "id,foo_s,v_ss")); - assertEquals("id,foo_s,v_ss\n2,,hi; there\n", getStringFromSheet(resultSheet)); - - // now test SolrDocumentList - SolrDocument d = new SolrDocument(); - SolrDocument d1 = d; - d.addField("id", "1"); - d.addField("foo_i", -1); - d.addField("foo_s", "hi"); - d.addField("foo_l", "12345678987654321L"); - d.addField("foo_b", false); - d.addField("foo_f", 1.414f); - d.addField("foo_d", -1.0E300); - d.addField("foo_dt1", new Date(Instant.parse("2000-01-02T03:04:05Z").toEpochMilli())); - d.addField("score", "2.718"); - - d = new SolrDocument(); - SolrDocument d2 = d; - d.addField("id", "2"); - d.addField("v_ss", "hi"); - d.addField("v_ss", "there"); - d.addField("v2_ss", "nice"); - d.addField("v2_ss", "output"); - d.addField("score", "89.83"); - d.addField("shouldbeunstored", "foo"); - - SolrDocumentList sdl = new SolrDocumentList(); - sdl.add(d1); - sdl.add(d2); - - SolrQueryRequest req = req("q", "*:*"); - rsp = new SolrQueryResponse(); - rsp.addResponse(sdl); - - rsp.setReturnFields(new SolrReturnFields("id,foo_s", req)); - - resultSheet = getWSResultForQuery(req, rsp); - assertEquals("id,foo_s\n1,hi\n2,\n", getStringFromSheet(resultSheet)); - - // try scores - rsp.setReturnFields(new SolrReturnFields("id,score,foo_s", req)); - - resultSheet = getWSResultForQuery(req, rsp); - assertEquals("id,score,foo_s\n1,2.718,hi\n2,89.83,\n", getStringFromSheet(resultSheet)); - - // get field values from docs... should be ordered and not include score unless requested - rsp.setReturnFields(new SolrReturnFields("*", req)); - - resultSheet = getWSResultForQuery(req, rsp); - assertEquals( - "id,foo_i,foo_s,foo_l,foo_b,foo_f,foo_d,foo_dt1,v_ss,v2_ss\n" - + "1,-1,hi,12345678987654321L,false,1.414,-1.0E300,2000-01-02T03:04:05Z,,\n" - + "2,,,,,,,,hi; there,nice; output\n", - getStringFromSheet(resultSheet)); - - // get field values and scores - just check that the scores are there... we don't guarantee - // where - rsp.setReturnFields(new SolrReturnFields("*,score", req)); - resultSheet = getWSResultForQuery(req, rsp); - String s = getStringFromSheet(resultSheet); - assertTrue(s.contains("score") && s.indexOf("2.718") > 0 && s.indexOf("89.83") > 0); - - // Test field globs - rsp.setReturnFields(new SolrReturnFields("id,foo*", req)); - resultSheet = getWSResultForQuery(req, rsp); - assertEquals( - "id,foo_i,foo_s,foo_l,foo_b,foo_f,foo_d,foo_dt1\n" - + "1,-1,hi,12345678987654321L,false,1.414,-1.0E300,2000-01-02T03:04:05Z\n" - + "2,,,,,,,\n", - getStringFromSheet(resultSheet)); - - rsp.setReturnFields(new SolrReturnFields("id,*_d*", req)); - resultSheet = getWSResultForQuery(req, rsp); - assertEquals( - "id,foo_d,foo_dt1\n" + "1,-1.0E300,2000-01-02T03:04:05Z\n" + "2,,\n", - getStringFromSheet(resultSheet)); - - // Test function queries - rsp.setReturnFields(new SolrReturnFields("sum(1,1),id,exists(foo_s1),div(9,1),foo_f", req)); - resultSheet = getWSResultForQuery(req, rsp); - assertEquals( - "sum(1,1),id,exists(foo_s1),div(9,1),foo_f\n" + ",1,,,1.414\n" + ",2,,,\n", - getStringFromSheet(resultSheet)); - - // Test transformers - rsp.setReturnFields(new SolrReturnFields("mydocid:[docid],[explain]", req)); - resultSheet = getWSResultForQuery(req, rsp); - assertEquals("mydocid,[explain]\n" + ",\n" + ",\n", getStringFromSheet(resultSheet)); - - req.close(); - } - - @Test - public void testPseudoFields() throws Exception { - // Use Pseudo Field - SolrQueryRequest req = req("q", "id:1", "wt", "xlsx", "fl", "XXX:id,foo_s"); - XSSFSheet resultSheet = getWSResultForQuery(req); - assertEquals("XXX,foo_s\n1,hi\n", getStringFromSheet(resultSheet)); - - String txt = - getStringFromSheet( - getWSResultForQuery( - req("q", "id:1", "wt", "xlsx", "fl", "XXX:id,YYY:[docid],FOO:foo_s"))); - String[] lines = txt.split("\n"); - assertEquals(2, lines.length); - assertEquals("XXX,YYY,FOO", lines[0]); - assertEquals("1,0,hi", lines[1]); - - // assertions specific to multiple pseudofields functions like abs, div, exists, etc.. - // (SOLR-5423) - String funcText = - getStringFromSheet( - getWSResultForQuery( - req("df", "text", "q", "*", "wt", "xlsx", "fl", "XXX:id,YYY:exists(foo_s1)"))); - String[] funcLines = funcText.split("\n"); - assertEquals(6, funcLines.length); - assertEquals("XXX,YYY", funcLines[0]); - assertEquals("1,false", funcLines[1]); - assertEquals("3,false", funcLines[3]); - - // assertions specific to single function without alias (SOLR-5423) - String singleFuncText = - getStringFromSheet( - getWSResultForQuery( - req("df", "text", "q", "*", "wt", "xlsx", "fl", "exists(foo_s1),XXX:id"))); - String[] singleFuncLines = singleFuncText.split("\n"); - assertEquals(6, singleFuncLines.length); - assertEquals("exists(foo_s1),XXX", singleFuncLines[0]); - assertEquals("false,1", singleFuncLines[1]); - assertEquals("false,3", singleFuncLines[3]); - - // pseudo-fields with * in fl - txt = - getStringFromSheet( - getWSResultForQuery( - req("df", "text", "q", "id:4", "wt", "xlsx", "fl", "*,YYY:[docid],FOO:foo_s1"))); - lines = txt.split("\n"); - assertEquals(2, lines.length); - assertEquals( - sortHeader( - "foo_i,foo_l,FOO,foo_s,pubyear_ii,store_iis," - + "v2_ss,multiDefault,timestamp,foo_dt1,foo_b,YYY,foo_d,id,foo_f,v_ss,foo_s1,intDefault"), - sortHeader(lines[0])); - } - - @Test - public void testForDVEnabledFields() throws Exception { - // for dv enabled and useDocValueAsStored=true - // returns pubyear_ii, store_iis but not price_ff - String singleFuncText = - getStringFromSheet(getWSResultForQuery(req("df", "text", "q", "id:5", "wt", "xlsx"))); - String sortedHeader = - sortHeader( - "foo_i,foo_l,foo_s,pubyear_ii,store_iis," - + "v2_ss,multiDefault,timestamp,foo_dt1,foo_b,foo_d,id,foo_f,v_ss,foo_s1,intDefault"); - String[] singleFuncLines = singleFuncText.split("\n"); - assertEquals(2, singleFuncLines.length); - assertEquals(sortedHeader, sortHeader(singleFuncLines[0])); - List actualVal = - Arrays.stream(singleFuncLines[1].trim().split(",")) - .filter(val -> !val.trim().isEmpty() && !val.trim().equals("\"\"")) - .collect(Collectors.toList()); - assertTrue(actualVal.containsAll(Arrays.asList("5", "123", "12"))); - - // explicit fl=* - singleFuncText = - getStringFromSheet( - getWSResultForQuery(req("df", "text", "q", "id:5", "wt", "xlsx", "fl", "*"))); - singleFuncLines = singleFuncText.split("\n"); - assertEquals(2, singleFuncLines.length); - assertEquals(sortedHeader, sortHeader(singleFuncLines[0])); - actualVal = - Arrays.stream(singleFuncLines[1].trim().split(",")) - .filter(val -> !val.trim().isEmpty() && !val.trim().equals("\"\"")) - .collect(Collectors.toList()); - assertTrue(actualVal.containsAll(Arrays.asList("5", "123", "12"))); - - // explicit price_ff - singleFuncText = - getStringFromSheet( - getWSResultForQuery(req("df", "text", "q", "id:5", "wt", "xlsx", "fl", "price_ff"))); - singleFuncLines = singleFuncText.split("\n"); - assertEquals(2, singleFuncLines.length); - assertEquals("price_ff", singleFuncLines[0]); - assertEquals("1.3", singleFuncLines[1]); - - // explicit price_ff with fl=* - singleFuncText = - getStringFromSheet( - getWSResultForQuery( - req( - "df", - "text", - "q", - "id:5", - "wt", - "xlsx", - "csv.header", - "true", - "fl", - "*,price_ff"))); - sortedHeader = - sortHeader( - "foo_i,foo_l,foo_b,foo_s,pubyear_ii,store_iis," - + "v2_ss,multiDefault,timestamp,foo_dt1,id,foo_d,foo_f,v_ss,foo_s1,intDefault,price_ff"); - singleFuncLines = singleFuncText.split("\n"); - assertEquals(2, singleFuncLines.length); - assertEquals(sortedHeader, sortHeader(singleFuncLines[0])); - actualVal = - Arrays.stream(singleFuncLines[1].trim().split(",")) - .filter(val -> !val.trim().isEmpty() && !val.trim().equals("\"\"")) - .collect(Collectors.toList()); - assertTrue(actualVal.containsAll(Arrays.asList("5", "123", "12", "1.3"))); - } - - // returns first worksheet as XLSXResponseWriter only returns one sheet - private XSSFSheet getWSResultForQuery(SolrQueryRequest req) throws Exception { - SolrQueryResponse rsp = h.queryAndResponse("", req); - return getWSResultForQuery(req, rsp); - } - - private XSSFSheet getWSResultForQuery(SolrQueryRequest req, SolrQueryResponse rsp) - throws Exception { - ByteArrayOutputStream xmlBout = new ByteArrayOutputStream(); - writerXlsx.write(xmlBout, req, rsp); - XSSFWorkbook output = new XSSFWorkbook(new ByteArrayInputStream(xmlBout.toByteArray())); - XSSFSheet sheet = output.getSheetAt(0); - req.close(); - output.close(); - return sheet; - } - - private String getStringFromSheet(XSSFSheet sheet) { - StringBuilder output = new StringBuilder(); - for (Row row : sheet) { - for (Cell cell : row) { - output.append(cell.getStringCellValue()); - output.append(","); - } - output.setLength(output.length() - 1); - output.append("\n"); - } - return output.toString(); - } - - /* - * Utility method to sort a comma separated list of strings, for easier comparison regardless of platform - */ - private String sortHeader(String input) { - String[] output = input.trim().split(","); - Arrays.sort(output); - return Arrays.toString(output); - } -} diff --git a/solr/solr-ref-guide/modules/query-guide/pages/response-writers.adoc b/solr/solr-ref-guide/modules/query-guide/pages/response-writers.adoc index ac86adbbceb8..b4f29b8e6815 100644 --- a/solr/solr-ref-guide/modules/query-guide/pages/response-writers.adoc +++ b/solr/solr-ref-guide/modules/query-guide/pages/response-writers.adoc @@ -30,7 +30,6 @@ The list below describe shows the most common settings for the `wt` parameter, w * <> * <> * <> -* <> * <> * <> @@ -387,25 +386,3 @@ else: == Smile Response Writer The Smile format is a JSON-compatible binary format, described in detail here: https://en.wikipedia.org/wiki/Smile_%28data_interchange_format%29[https://en.wikipedia.org/wiki/Smile_(data_interchange_format)] - -== XLSX Response Writer - -Use this to get the response as a spreadsheet in the .xlsx (Microsoft Excel) format. -It accepts parameters in the form `colwidth.` and `colname.` which helps you customize the column widths and column names. - -This response writer has been added as part of the extraction library, and will only work if the extraction module is present in the server classpath. -Defining the classpath with the `lib` directive is not sufficient. -Instead, you will need to copy the necessary .jars to the Solr webapp's `lib` directory manually. -You can run these commands from your `$SOLR_INSTALL` directory: - -[source,bash] ----- -cp modules/extraction/lib/*.jar server/solr-webapp/webapp/WEB-INF/lib/ ----- - -Once the libraries are in place, you can add `wt=xlsx` to your request, and results will be returned as an XLSX sheet. - -[IMPORTANT] -==== -The `XLSXResponseWriter` is deprecated and will be removed in a future release. -==== diff --git a/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc b/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc index 01a86b161b4e..bcd10974008f 100644 --- a/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc +++ b/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc @@ -141,6 +141,8 @@ To share resource intensive objects across multiple cores in components you shou * The language specific Response Writers, which were deprecated in 9.8 in favour of more widely used formats like JSON have been removed. The removed writer types (invoked as part of the `wt` parameter) include `python`, `ruby`, `php`, and `phps`. +* The XLSX Response Writer (`wt=xlsx`), which was deprecated in 9.10, has been removed. Users needing Excel export functionality should use CSV format (`wt=csv`) and convert it to Excel format using external tools or libraries. + * The deprecated support for configuring replication using master/slave terminology is removed. Use leader/follower. * Support for the `` directive, which historically could be used in solrconfig.xml to add JARs on a core-by-core basis, was deprecated in 9.8 and has now been removed.