SOLR-13255 : ClasscastException when URPs try to read a String field which returns a ByteArrayUTF8CHarSequence . This is a regression in release 7.7

This commit is contained in:
Noble Paul 2019-02-20 22:19:18 +11:00
parent 3ef6e015dd
commit a89b065c1f
6 changed files with 93 additions and 11 deletions

View File

@ -247,6 +247,10 @@ Bug Fixes
this issue reverts the default replica placement policy to the 'legacy' assignment policy that was the default until this issue reverts the default replica placement policy to the 'legacy' assignment policy that was the default until
Solr 7.4. (Gus Heck, Andrzej Bialecki, Bram Van Dam, shalin) Solr 7.4. (Gus Heck, Andrzej Bialecki, Bram Van Dam, shalin)
* SOLR-13255 : ClasscastException when URPs try to read a String field which returns a ByteArrayUTF8CHarSequence . This is a regression
in release 7.7 (noble)
Improvements Improvements
---------------------- ----------------------

View File

@ -17,16 +17,19 @@
package org.apache.solr.update.processor; package org.apache.solr.update.processor;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.util.ByteArrayUtf8CharSequence;
import org.apache.solr.core.SolrCore; import org.apache.solr.core.SolrCore;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.servlet.SolrRequestParsers;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.servlet.SolrRequestParsers;
public abstract class LanguageIdentifierUpdateProcessorFactoryTestCase extends SolrTestCaseJ4 { public abstract class LanguageIdentifierUpdateProcessorFactoryTestCase extends SolrTestCaseJ4 {
@ -383,6 +386,25 @@ public abstract class LanguageIdentifierUpdateProcessorFactoryTestCase extends S
*/ */
private SolrInputDocument process(SolrInputDocument origDoc) { private SolrInputDocument process(SolrInputDocument origDoc) {
SolrInputDocument modifiedDoc = origDoc.deepCopy(); SolrInputDocument modifiedDoc = origDoc.deepCopy();
if (random().nextBoolean()) {
modifiedDoc.forEach((s, f) -> {
Object rawVal = f.getRawValue();
if (rawVal instanceof Collection) {
Collection rawValue = (Collection) rawVal;
ArrayList<Object> newVal = new ArrayList<>(rawValue.size());
for (Object o : rawValue) {
if (o instanceof String) {
newVal.add(new ByteArrayUtf8CharSequence((String) o));
} else {
newVal.add(rawVal);
}
}
f.setValue(newVal);
} else if (rawVal instanceof String) {
f.setValue(new ByteArrayUtf8CharSequence((String) rawVal));
}
});
}
liProcessor.process(modifiedDoc); liProcessor.process(modifiedDoc);
return modifiedDoc; return modifiedDoc;
} }

View File

@ -135,7 +135,7 @@ public class DocumentBuilder {
// Load fields from SolrDocument to Document // Load fields from SolrDocument to Document
for( SolrInputField field : doc ) { for( SolrInputField field : doc ) {
if (field.getFirstValue() instanceof SolrDocumentBase) { if (field.getFirstRawValue() instanceof SolrDocumentBase) {
if (ignoreNestedDocs) { if (ignoreNestedDocs) {
continue; continue;
} }
@ -159,7 +159,9 @@ public class DocumentBuilder {
// load each field value // load each field value
boolean hasField = false; boolean hasField = false;
try { try {
for( Object v : field ) { Iterator it = field.getRawIterator();
while (it.hasNext()) {
Object v = it.next();
if( v == null ) { if( v == null ) {
continue; continue;
} }

View File

@ -21,6 +21,8 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import static org.apache.solr.common.util.ByteArrayUtf8CharSequence.convertCharSeq;
/** /**
* *
* @since solr 1.3 * @since solr 1.3
@ -111,11 +113,11 @@ public class SolrInputField implements Iterable<Object>, Serializable
if( value instanceof Collection ) { if( value instanceof Collection ) {
Collection c = (Collection<Object>)value; Collection c = (Collection<Object>)value;
if( c.size() > 0 ) { if( c.size() > 0 ) {
return c.iterator().next(); return convertCharSeq(c.iterator().next());
} }
return null; return null;
} }
return value; return convertCharSeq(value);
} }
/** /**
@ -123,6 +125,28 @@ public class SolrInputField implements Iterable<Object>, Serializable
* will be a collection. * will be a collection.
*/ */
public Object getValue() { public Object getValue() {
return convertCharSeq(value);
}
/**
* Return a value as is without converting and CharSequence Objects
*/
public Object getRawValue() {
return value;
}
/**
* Return the first value as is without converting and CharSequence Objects
*/
public Object getFirstRawValue() {
if (value instanceof Collection) {
Collection c = (Collection<Object>) value;
if (c.size() > 0) {
return c.iterator().next();
}
return null;
}
return value; return value;
} }
@ -133,11 +157,11 @@ public class SolrInputField implements Iterable<Object>, Serializable
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Collection<Object> getValues() { public Collection<Object> getValues() {
if (value instanceof Collection) { if (value instanceof Collection) {
return (Collection<Object>)value; return convertCharSeq((Collection<Object>) value);
} }
if( value != null ) { if( value != null ) {
Collection<Object> vals = new ArrayList<>(1); Collection<Object> vals = new ArrayList<>(1);
vals.add( value ); vals.add(convertCharSeq(value));
return vals; return vals;
} }
return null; return null;
@ -165,8 +189,33 @@ public class SolrInputField implements Iterable<Object>, Serializable
} }
@Override @Override
@SuppressWarnings("unchecked")
public Iterator<Object> iterator(){ public Iterator<Object> iterator(){
if( value instanceof Collection ) {
return (convertCharSeq ((Collection)value)).iterator();
}
return new Iterator<Object>() {
boolean nxt = (value!=null);
@Override
public boolean hasNext() {
return nxt;
}
@Override
public Object next() {
nxt = false;
return convertCharSeq(value);
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
@SuppressWarnings("unchecked")
public Iterator<Object> getRawIterator() {
if( value instanceof Collection ) { if( value instanceof Collection ) {
return ((Collection)value).iterator(); return ((Collection)value).iterator();
} }

View File

@ -73,6 +73,10 @@ public class ByteArrayUtf8CharSequence implements Utf8CharSequence {
return buf[offset + idx]; return buf[offset + idx];
} }
/**
* this is for internal use to get a cached string value.
* returns null if There is no cached String value
*/
public String getStringOrNull() { public String getStringOrNull() {
return utf16; return utf16;
} }
@ -209,6 +213,7 @@ public class ByteArrayUtf8CharSequence implements Utf8CharSequence {
public static Object convertCharSeq(Object o) { public static Object convertCharSeq(Object o) {
if (o == null) return null; if (o == null) return null;
if (o instanceof Utf8CharSequence) return ((Utf8CharSequence) o).toString(); if (o instanceof Utf8CharSequence) return ((Utf8CharSequence) o).toString();
if (o instanceof Collection) return convertCharSeq((Collection) o);
return o; return o;
} }

View File

@ -357,7 +357,7 @@ public class JavaBinCodec implements PushWriter {
return true; return true;
} }
if (val instanceof SolrInputField) { if (val instanceof SolrInputField) {
return writeKnownType(((SolrInputField) val).getValue()); return writeKnownType(((SolrInputField) val).getRawValue());
} }
if (val instanceof IteratorWriter) { if (val instanceof IteratorWriter) {
writeIterator((IteratorWriter) val); writeIterator((IteratorWriter) val);