http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d9a661cf/ranger_solrj/src/main/java/org/apache/solr/common/util/JavaBinCodec.java ---------------------------------------------------------------------- diff --git a/ranger_solrj/src/main/java/org/apache/solr/common/util/JavaBinCodec.java b/ranger_solrj/src/main/java/org/apache/solr/common/util/JavaBinCodec.java deleted file mode 100644 index 687525c..0000000 --- a/ranger_solrj/src/main/java/org/apache/solr/common/util/JavaBinCodec.java +++ /dev/null @@ -1,820 +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.common.util; - -import org.apache.solr.common.EnumFieldValue; -import org.noggit.CharArr; -import org.apache.solr.common.SolrDocument; -import org.apache.solr.common.SolrDocumentList; -import org.apache.solr.common.SolrInputDocument; -import org.apache.solr.common.SolrInputField; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.*; -import java.util.Map.Entry; -import java.nio.ByteBuffer; - -/** - * The class is designed to optimaly serialize/deserialize any supported types in Solr response. As we know there are only a limited type of - * items this class can do it with very minimal amount of payload and code. There are 15 known types and if there is an - * object in the object tree which does not fall into these types, It must be converted to one of these. Implement an - * ObjectResolver and pass it over It is expected that this class is used on both end of the pipes. The class has one - * read method and one write method for each of the datatypes - * <p> - * Note -- Never re-use an instance of this class for more than one marshal or unmarshall operation. Always create a new - * instance. - */ -public class JavaBinCodec { - - public static final byte - NULL = 0, - BOOL_TRUE = 1, - BOOL_FALSE = 2, - BYTE = 3, - SHORT = 4, - DOUBLE = 5, - INT = 6, - LONG = 7, - FLOAT = 8, - DATE = 9, - MAP = 10, - SOLRDOC = 11, - SOLRDOCLST = 12, - BYTEARR = 13, - ITERATOR = 14, - /** - * this is a special tag signals an end. No value is associated with it - */ - END = 15, - - SOLRINPUTDOC = 16, - SOLRINPUTDOC_CHILDS = 17, - ENUM_FIELD_VALUE = 18, - MAP_ENTRY = 19, - // types that combine tag + length (or other info) in a single byte - TAG_AND_LEN = (byte) (1 << 5), - STR = (byte) (1 << 5), - SINT = (byte) (2 << 5), - SLONG = (byte) (3 << 5), - ARR = (byte) (4 << 5), // - ORDERED_MAP = (byte) (5 << 5), // SimpleOrderedMap (a NamedList subclass, and more common) - NAMED_LST = (byte) (6 << 5), // NamedList - EXTERN_STRING = (byte) (7 << 5); - - - private static byte VERSION = 2; - private ObjectResolver resolver; - protected FastOutputStream daos; - - public JavaBinCodec() { - } - - public JavaBinCodec(ObjectResolver resolver) { - this.resolver = resolver; - } - - public void marshal(Object nl, OutputStream os) throws IOException { - init(FastOutputStream.wrap(os)); - try { - daos.writeByte(VERSION); - writeVal(nl); - } finally { - daos.flushBuffer(); - } - } - - /** expert: sets a new output stream */ - public void init(FastOutputStream os) { - daos = os; - } - - byte version; - - public Object unmarshal(InputStream is) throws IOException { - FastInputStream dis = FastInputStream.wrap(is); - version = dis.readByte(); - if (version != VERSION) { - throw new RuntimeException("Invalid version (expected " + VERSION + - ", but " + version + ") or the data in not in 'javabin' format"); - } - return readVal(dis); - } - - - public SimpleOrderedMap<Object> readOrderedMap(DataInputInputStream dis) throws IOException { - int sz = readSize(dis); - SimpleOrderedMap<Object> nl = new SimpleOrderedMap<>(); - for (int i = 0; i < sz; i++) { - String name = (String) readVal(dis); - Object val = readVal(dis); - nl.add(name, val); - } - return nl; - } - - public NamedList<Object> readNamedList(DataInputInputStream dis) throws IOException { - int sz = readSize(dis); - NamedList<Object> nl = new NamedList<>(); - for (int i = 0; i < sz; i++) { - String name = (String) readVal(dis); - Object val = readVal(dis); - nl.add(name, val); - } - return nl; - } - - public void writeNamedList(NamedList<?> nl) throws IOException { - writeTag(nl instanceof SimpleOrderedMap ? ORDERED_MAP : NAMED_LST, nl.size()); - for (int i = 0; i < nl.size(); i++) { - String name = nl.getName(i); - writeExternString(name); - Object val = nl.getVal(i); - writeVal(val); - } - } - - public void writeVal(Object val) throws IOException { - if (writeKnownType(val)) { - return; - } else { - Object tmpVal = val; - if (resolver != null) { - tmpVal = resolver.resolve(val, this); - if (tmpVal == null) return; // null means the resolver took care of it fully - if (writeKnownType(tmpVal)) return; - } - } - - writeVal(val.getClass().getName() + ':' + val.toString()); - } - - protected static final Object END_OBJ = new Object(); - - protected byte tagByte; - - public Object readVal(DataInputInputStream dis) throws IOException { - tagByte = dis.readByte(); - - // if ((tagByte & 0xe0) == 0) { - // if top 3 bits are clear, this is a normal tag - - // OK, try type + size in single byte - switch (tagByte >>> 5) { - case STR >>> 5: - return readStr(dis); - case SINT >>> 5: - return readSmallInt(dis); - case SLONG >>> 5: - return readSmallLong(dis); - case ARR >>> 5: - return readArray(dis); - case ORDERED_MAP >>> 5: - return readOrderedMap(dis); - case NAMED_LST >>> 5: - return readNamedList(dis); - case EXTERN_STRING >>> 5: - return readExternString(dis); - } - - switch (tagByte) { - case NULL: - return null; - case DATE: - return new Date(dis.readLong()); - case INT: - return dis.readInt(); - case BOOL_TRUE: - return Boolean.TRUE; - case BOOL_FALSE: - return Boolean.FALSE; - case FLOAT: - return dis.readFloat(); - case DOUBLE: - return dis.readDouble(); - case LONG: - return dis.readLong(); - case BYTE: - return dis.readByte(); - case SHORT: - return dis.readShort(); - case MAP: - return readMap(dis); - case SOLRDOC: - return readSolrDocument(dis); - case SOLRDOCLST: - return readSolrDocumentList(dis); - case BYTEARR: - return readByteArray(dis); - case ITERATOR: - return readIterator(dis); - case END: - return END_OBJ; - case SOLRINPUTDOC: - return readSolrInputDocument(dis); - case ENUM_FIELD_VALUE: - return readEnumFieldValue(dis); - case MAP_ENTRY: - return readMapEntry(dis); - } - - throw new RuntimeException("Unknown type " + tagByte); - } - - public boolean writeKnownType(Object val) throws IOException { - if (writePrimitive(val)) return true; - if (val instanceof NamedList) { - writeNamedList((NamedList<?>) val); - return true; - } - if (val instanceof SolrDocumentList) { // SolrDocumentList is a List, so must come before List check - writeSolrDocumentList((SolrDocumentList) val); - return true; - } - if (val instanceof Collection) { - writeArray((Collection) val); - return true; - } - if (val instanceof Object[]) { - writeArray((Object[]) val); - return true; - } - if (val instanceof SolrDocument) { - //this needs special treatment to know which fields are to be written - if (resolver == null) { - writeSolrDocument((SolrDocument) val); - } else { - Object retVal = resolver.resolve(val, this); - if (retVal != null) { - if (retVal instanceof SolrDocument) { - writeSolrDocument((SolrDocument) retVal); - } else { - writeVal(retVal); - } - } - } - return true; - } - if (val instanceof SolrInputDocument) { - writeSolrInputDocument((SolrInputDocument)val); - return true; - } - if (val instanceof Map) { - writeMap((Map) val); - return true; - } - if (val instanceof Iterator) { - writeIterator((Iterator) val); - return true; - } - if (val instanceof Iterable) { - writeIterator(((Iterable) val).iterator()); - return true; - } - if (val instanceof EnumFieldValue) { - writeEnumFieldValue((EnumFieldValue) val); - return true; - } - if (val instanceof Map.Entry) { - writeMapEntry((Map.Entry)val); - return true; - } - return false; - } - - public void writeTag(byte tag) throws IOException { - daos.writeByte(tag); - } - - public void writeTag(byte tag, int size) throws IOException { - if ((tag & 0xe0) != 0) { - if (size < 0x1f) { - daos.writeByte(tag | size); - } else { - daos.writeByte(tag | 0x1f); - writeVInt(size - 0x1f, daos); - } - } else { - daos.writeByte(tag); - writeVInt(size, daos); - } - } - - public void writeByteArray(byte[] arr, int offset, int len) throws IOException { - writeTag(BYTEARR, len); - daos.write(arr, offset, len); - } - - public byte[] readByteArray(DataInputInputStream dis) throws IOException { - byte[] arr = new byte[readVInt(dis)]; - dis.readFully(arr); - return arr; - } - - public void writeSolrDocument(SolrDocument doc) throws IOException { - List<SolrDocument> children = doc.getChildDocuments(); - int sz = doc.size() + (children==null ? 0 : children.size()); - writeTag(SOLRDOC); - writeTag(ORDERED_MAP, sz); - for (Map.Entry<String, Object> entry : doc) { - String name = entry.getKey(); - writeExternString(name); - Object val = entry.getValue(); - writeVal(val); - } - if (children != null) { - for (SolrDocument child : children) { - writeSolrDocument(child); - } - } - } - - public SolrDocument readSolrDocument(DataInputInputStream dis) throws IOException { - tagByte = dis.readByte(); - int size = readSize(dis); - SolrDocument doc = new SolrDocument(); - for (int i = 0; i < size; i++) { - String fieldName; - Object obj = readVal(dis); // could be a field name, or a child document - if (obj instanceof SolrDocument) { - doc.addChildDocument((SolrDocument)obj); - continue; - } else { - fieldName = (String)obj; - } - Object fieldVal = readVal(dis); - doc.setField(fieldName, fieldVal); - } - return doc; - } - - public SolrDocumentList readSolrDocumentList(DataInputInputStream dis) throws IOException { - SolrDocumentList solrDocs = new SolrDocumentList(); - List list = (List) readVal(dis); - solrDocs.setNumFound((Long) list.get(0)); - solrDocs.setStart((Long) list.get(1)); - solrDocs.setMaxScore((Float) list.get(2)); - - @SuppressWarnings("unchecked") - List<SolrDocument> l = (List<SolrDocument>) readVal(dis); - solrDocs.addAll(l); - return solrDocs; - } - - public void writeSolrDocumentList(SolrDocumentList docs) - throws IOException { - writeTag(SOLRDOCLST); - List<Number> l = new ArrayList<>(3); - l.add(docs.getNumFound()); - l.add(docs.getStart()); - l.add(docs.getMaxScore()); - writeArray(l); - writeArray(docs); - } - - public SolrInputDocument readSolrInputDocument(DataInputInputStream dis) throws IOException { - int sz = readVInt(dis); - float docBoost = (Float)readVal(dis); - SolrInputDocument sdoc = new SolrInputDocument(); - sdoc.setDocumentBoost(docBoost); - for (int i = 0; i < sz; i++) { - float boost = 1.0f; - String fieldName; - Object obj = readVal(dis); // could be a boost, a field name, or a child document - if (obj instanceof Float) { - boost = (Float)obj; - fieldName = (String)readVal(dis); - } else if (obj instanceof SolrInputDocument) { - sdoc.addChildDocument((SolrInputDocument)obj); - continue; - } else { - fieldName = (String)obj; - } - Object fieldVal = readVal(dis); - sdoc.setField(fieldName, fieldVal, boost); - } - return sdoc; - } - - public void writeSolrInputDocument(SolrInputDocument sdoc) throws IOException { - List<SolrInputDocument> children = sdoc.getChildDocuments(); - int sz = sdoc.size() + (children==null ? 0 : children.size()); - writeTag(SOLRINPUTDOC, sz); - writeFloat(sdoc.getDocumentBoost()); - for (SolrInputField inputField : sdoc.values()) { - if (inputField.getBoost() != 1.0f) { - writeFloat(inputField.getBoost()); - } - writeExternString(inputField.getName()); - writeVal(inputField.getValue()); - } - if (children != null) { - for (SolrInputDocument child : children) { - writeSolrInputDocument(child); - } - } - } - - - public Map<Object,Object> readMap(DataInputInputStream dis) - throws IOException { - int sz = readVInt(dis); - Map<Object,Object> m = new LinkedHashMap<>(); - for (int i = 0; i < sz; i++) { - Object key = readVal(dis); - Object val = readVal(dis); - m.put(key, val); - - } - return m; - } - - public void writeIterator(Iterator iter) throws IOException { - writeTag(ITERATOR); - while (iter.hasNext()) { - writeVal(iter.next()); - } - writeVal(END_OBJ); - } - - public List<Object> readIterator(DataInputInputStream fis) throws IOException { - ArrayList<Object> l = new ArrayList<>(); - while (true) { - Object o = readVal(fis); - if (o == END_OBJ) break; - l.add(o); - } - return l; - } - - public void writeArray(List l) throws IOException { - writeTag(ARR, l.size()); - for (int i = 0; i < l.size(); i++) { - writeVal(l.get(i)); - } - } - - public void writeArray(Collection coll) throws IOException { - writeTag(ARR, coll.size()); - for (Object o : coll) { - writeVal(o); - } - - } - - public void writeArray(Object[] arr) throws IOException { - writeTag(ARR, arr.length); - for (int i = 0; i < arr.length; i++) { - Object o = arr[i]; - writeVal(o); - } - } - - public List<Object> readArray(DataInputInputStream dis) throws IOException { - int sz = readSize(dis); - ArrayList<Object> l = new ArrayList<>(sz); - for (int i = 0; i < sz; i++) { - l.add(readVal(dis)); - } - return l; - } - - /** - * write {@link EnumFieldValue} as tag+int value+string value - * @param enumFieldValue to write - */ - public void writeEnumFieldValue(EnumFieldValue enumFieldValue) throws IOException { - writeTag(ENUM_FIELD_VALUE); - writeInt(enumFieldValue.toInt()); - writeStr(enumFieldValue.toString()); - } - - public void writeMapEntry(Entry<Object,Object> val) throws IOException { - writeTag(MAP_ENTRY); - writeVal(val.getKey()); - writeVal(val.getValue()); - } - - /** - * read {@link EnumFieldValue} (int+string) from input stream - * @param dis data input stream - * @return {@link EnumFieldValue} - */ - public EnumFieldValue readEnumFieldValue(DataInputInputStream dis) throws IOException { - Integer intValue = (Integer) readVal(dis); - String stringValue = (String) readVal(dis); - return new EnumFieldValue(intValue, stringValue); - } - - - public Map.Entry<Object,Object> readMapEntry(DataInputInputStream dis) throws IOException { - final Object key = readVal(dis); - final Object value = readVal(dis); - return new Map.Entry<Object,Object>() { - - @Override - public Object getKey() { - return key; - } - - @Override - public Object getValue() { - return value; - } - - @Override - public String toString() { - return "MapEntry[" + key.toString() + ":" + value.toString() + "]"; - } - - @Override - public Object setValue(Object value) { - throw new UnsupportedOperationException(); - } - - @Override - public int hashCode() { - int result = 31; - result *=31 + getKey().hashCode(); - result *=31 + getValue().hashCode(); - return result; - } - - @Override - public boolean equals(Object obj) { - if(this == obj) { - return true; - } - if(!(obj instanceof Entry)) { - return false; - } - Map.Entry<Object, Object> entry = (Entry<Object, Object>) obj; - return (this.getKey().equals(entry.getKey()) && this.getValue().equals(entry.getValue())); - } - }; - } - - /** - * write the string as tag+length, with length being the number of UTF-8 bytes - */ - public void writeStr(String s) throws IOException { - if (s == null) { - writeTag(NULL); - return; - } - int end = s.length(); - int maxSize = end * 4; - if (bytes == null || bytes.length < maxSize) bytes = new byte[maxSize]; - int sz = ByteUtils.UTF16toUTF8(s, 0, end, bytes, 0); - - writeTag(STR, sz); - daos.write(bytes, 0, sz); - } - - byte[] bytes; - CharArr arr = new CharArr(); - - public String readStr(DataInputInputStream dis) throws IOException { - int sz = readSize(dis); - if (bytes == null || bytes.length < sz) bytes = new byte[sz]; - dis.readFully(bytes, 0, sz); - - arr.reset(); - ByteUtils.UTF8toUTF16(bytes, 0, sz, arr); - return arr.toString(); - } - - public void writeInt(int val) throws IOException { - if (val > 0) { - int b = SINT | (val & 0x0f); - - if (val >= 0x0f) { - b |= 0x10; - daos.writeByte(b); - writeVInt(val >>> 4, daos); - } else { - daos.writeByte(b); - } - - } else { - daos.writeByte(INT); - daos.writeInt(val); - } - } - - public int readSmallInt(DataInputInputStream dis) throws IOException { - int v = tagByte & 0x0F; - if ((tagByte & 0x10) != 0) - v = (readVInt(dis) << 4) | v; - return v; - } - - - public void writeLong(long val) throws IOException { - if ((val & 0xff00000000000000L) == 0) { - int b = SLONG | ((int) val & 0x0f); - if (val >= 0x0f) { - b |= 0x10; - daos.writeByte(b); - writeVLong(val >>> 4, daos); - } else { - daos.writeByte(b); - } - } else { - daos.writeByte(LONG); - daos.writeLong(val); - } - } - - public long readSmallLong(DataInputInputStream dis) throws IOException { - long v = tagByte & 0x0F; - if ((tagByte & 0x10) != 0) - v = (readVLong(dis) << 4) | v; - return v; - } - - public void writeFloat(float val) throws IOException { - daos.writeByte(FLOAT); - daos.writeFloat(val); - } - - public boolean writePrimitive(Object val) throws IOException { - if (val == null) { - daos.writeByte(NULL); - return true; - } else if (val instanceof String) { - writeStr((String) val); - return true; - } else if (val instanceof Number) { - - if (val instanceof Integer) { - writeInt(((Integer) val).intValue()); - return true; - } else if (val instanceof Long) { - writeLong(((Long) val).longValue()); - return true; - } else if (val instanceof Float) { - writeFloat(((Float) val).floatValue()); - return true; - } else if (val instanceof Double) { - daos.writeByte(DOUBLE); - daos.writeDouble(((Double) val).doubleValue()); - return true; - } else if (val instanceof Byte) { - daos.writeByte(BYTE); - daos.writeByte(((Byte) val).intValue()); - return true; - } else if (val instanceof Short) { - daos.writeByte(SHORT); - daos.writeShort(((Short) val).intValue()); - return true; - } - return false; - - } else if (val instanceof Date) { - daos.writeByte(DATE); - daos.writeLong(((Date) val).getTime()); - return true; - } else if (val instanceof Boolean) { - if ((Boolean) val) daos.writeByte(BOOL_TRUE); - else daos.writeByte(BOOL_FALSE); - return true; - } else if (val instanceof byte[]) { - writeByteArray((byte[]) val, 0, ((byte[]) val).length); - return true; - } else if (val instanceof ByteBuffer) { - ByteBuffer buf = (ByteBuffer) val; - writeByteArray(buf.array(),buf.position(),buf.limit() - buf.position()); - return true; - } else if (val == END_OBJ) { - writeTag(END); - return true; - } - return false; - } - - - public void writeMap(Map<?,?> val) throws IOException { - writeTag(MAP, val.size()); - for (Map.Entry<?,?> entry : val.entrySet()) { - Object key = entry.getKey(); - if (key instanceof String) { - writeExternString((String) key); - } else { - writeVal(key); - } - writeVal(entry.getValue()); - } - } - - - public int readSize(DataInputInputStream in) throws IOException { - int sz = tagByte & 0x1f; - if (sz == 0x1f) sz += readVInt(in); - return sz; - } - - - /** - * Special method for variable length int (copied from lucene). Usually used for writing the length of a - * collection/array/map In most of the cases the length can be represented in one byte (length < 127) so it saves 3 - * bytes/object - * - * @throws IOException If there is a low-level I/O error. - */ - public static void writeVInt(int i, FastOutputStream out) throws IOException { - while ((i & ~0x7F) != 0) { - out.writeByte((byte) ((i & 0x7f) | 0x80)); - i >>>= 7; - } - out.writeByte((byte) i); - } - - /** - * The counterpart for {@link #writeVInt(int, FastOutputStream)} - * - * @throws IOException If there is a low-level I/O error. - */ - public static int readVInt(DataInputInputStream in) throws IOException { - byte b = in.readByte(); - int i = b & 0x7F; - for (int shift = 7; (b & 0x80) != 0; shift += 7) { - b = in.readByte(); - i |= (b & 0x7F) << shift; - } - return i; - } - - - public static void writeVLong(long i, FastOutputStream out) throws IOException { - while ((i & ~0x7F) != 0) { - out.writeByte((byte) ((i & 0x7f) | 0x80)); - i >>>= 7; - } - out.writeByte((byte) i); - } - - public static long readVLong(DataInputInputStream in) throws IOException { - byte b = in.readByte(); - long i = b & 0x7F; - for (int shift = 7; (b & 0x80) != 0; shift += 7) { - b = in.readByte(); - i |= (long) (b & 0x7F) << shift; - } - return i; - } - - private int stringsCount = 0; - private Map<String, Integer> stringsMap; - private List<String> stringsList; - - public void writeExternString(String s) throws IOException { - if (s == null) { - writeTag(NULL); - return; - } - Integer idx = stringsMap == null ? null : stringsMap.get(s); - if (idx == null) idx = 0; - writeTag(EXTERN_STRING, idx); - if (idx == 0) { - writeStr(s); - if (stringsMap == null) stringsMap = new HashMap<>(); - stringsMap.put(s, ++stringsCount); - } - - } - - public String readExternString(DataInputInputStream fis) throws IOException { - int idx = readSize(fis); - if (idx != 0) {// idx != 0 is the index of the extern string - return stringsList.get(idx - 1); - } else {// idx == 0 means it has a string value - String s = (String) readVal(fis); - if (stringsList == null) stringsList = new ArrayList<>(); - stringsList.add(s); - return s; - } - } - - - public static interface ObjectResolver { - public Object resolve(Object o, JavaBinCodec codec) throws IOException; - } - - -}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d9a661cf/ranger_solrj/src/main/java/org/apache/solr/common/util/JsonRecordReader.java ---------------------------------------------------------------------- diff --git a/ranger_solrj/src/main/java/org/apache/solr/common/util/JsonRecordReader.java b/ranger_solrj/src/main/java/org/apache/solr/common/util/JsonRecordReader.java deleted file mode 100644 index c3afde7..0000000 --- a/ranger_solrj/src/main/java/org/apache/solr/common/util/JsonRecordReader.java +++ /dev/null @@ -1,586 +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.common.util; - - -import java.io.IOException; -import java.io.Reader; -import java.util.*; - -import org.noggit.JSONParser; - -import static org.noggit.JSONParser.*; - -/** - * A Streaming parser for json to emit one record at a time. - */ - -public class JsonRecordReader { - public static final String DELIM = "."; - - private Node rootNode = new Node("/", (Node) null); - - public static JsonRecordReader getInst(String split, List<String> fieldMappings) { - - JsonRecordReader jsonRecordReader = new JsonRecordReader(split); - for (String s : fieldMappings) { - String path = s; - int idx = s.indexOf(':'); - String fieldName = null; - if (idx > 0) { - fieldName = s.substring(0, idx); - path = s.substring(idx + 1); - } - jsonRecordReader.addField(path, fieldName, true, false); - } - return jsonRecordReader; - } - - /** - * A constructor called with a '|' separated list of path expressions - * which define sub sections of the JSON stream that are to be emitted as - * separate records. - * - * @param splitPath The PATH for which a record is emitted. Once the - * path tag is encountered, the Node.getInst method starts collecting wanted - * fields and at the close of the tag, a record is emitted containing all - * fields collected since the tag start. Once - * emitted the collected fields are cleared. Any fields collected in the - * parent tag or above will also be included in the record, but these are - * not cleared after emitting the record. - * <p> - * It uses the ' | ' syntax of PATH to pass in multiple paths. - */ - private JsonRecordReader(String splitPath) { - String[] splits = splitPath.split("\\|"); - for (String split : splits) { - split = split.trim(); - if (split.startsWith("//")) - throw new RuntimeException("split cannot start with '//': " + split); - if (split.length() == 0) - continue; - // The created Node has a name set to the full split attribute path - addField(split, split, false, true); - } - } - - /** - * Splits the path into a List of segments and calls build() to - * construct a tree of Nodes representing path segments. The resulting - * tree structure ends up describing all the paths we are interested in. - * - * @param path The path expression for this field - * @param fieldName The name for this field in the emitted record - * @param multiValued If 'true' then the emitted record will have values in - * a List<String> - * @param isRecord Flags that this PATH is from a forEach statement - */ - private void addField(String path, String fieldName, boolean multiValued, boolean isRecord) { - if (!path.startsWith("/")) throw new RuntimeException("All paths must start with '/' " + path); - List<String> paths = splitEscapeQuote(path); - if (paths.size() == 0) { - if (isRecord) rootNode.isRecord = true; - return;//the patrh is "/" - } - // deal with how split behaves when seperator starts a string! - if ("".equals(paths.get(0).trim())) - paths.remove(0); - rootNode.build(paths, fieldName, multiValued, isRecord, path); - rootNode.buildOptimize(); - } - - /** - * Uses {@link #streamRecords streamRecords} to getInst the JSON source but with - * a handler that collects all the emitted records into a single List which - * is returned upon completion. - * - * @param r the stream reader - * @return results a List of emitted records - */ - public List<Map<String, Object>> getAllRecords(Reader r) throws IOException { - final List<Map<String, Object>> results = new ArrayList<>(); - streamRecords(r, new Handler() { - @Override - public void handle(Map<String, Object> record, String path) { - results.add(record); - } - }); - return results; - } - - /** - * Creates an JSONParser on top of whatever reader has been - * configured. Then calls getInst() with a handler which is - * invoked forEach record emitted. - * - * @param r the stream reader - * @param handler The callback instance - */ - public void streamRecords(Reader r, Handler handler) throws IOException { - streamRecords(new JSONParser(r), handler); - } - - public void streamRecords(JSONParser parser, Handler handler) throws IOException { - rootNode.parse(parser, handler, - new LinkedHashMap<String, Object>(), - new Stack<Set<String>>(), false); - } - - - /** - * For each node/leaf in the Node tree there is one object of this class. - * This tree of objects represents all the Paths we are interested in. - * For each path segment of interest we create a node. In most cases the - * node (branch) is rather basic , but for the final portion (leaf) of any - * path we add more information to the Node. When parsing the JSON document - * we step though this tree as we stream records from the reader. If the JSON - * document departs from this tree we skip start tags till we are back on - * the tree. - */ - private static class Node { - String name; // generally: segment of the path represented by this Node - String fieldName; // the fieldname in the emitted record (key of the map) - String splitPath; // the full path from the forEach entity attribute - final LinkedHashMap<String, Node> childNodes = new LinkedHashMap<>(); // List of immediate child Nodes of this node - Node parent; // parent Node in the tree - boolean isLeaf = false; // flag: store/emit streamed text for this node - boolean isRecord = false; //flag: this Node starts a new record - Node wildCardChild; - Node recursiveWildCardChild; - private boolean useFqn = false; - - - public Node(String name, Node p) { - // Create a basic Node, suitable for the mid portions of any path. - // Node.pathName and Node.name are set to same value. - this.name = name; - parent = p; - } - - public Node(String name, String fieldName) { - // This is only called from build() when describing an attribute. - this.name = name; // a segment from the path - this.fieldName = fieldName; // name to store collected values against - } - - - /** - * Walk the Node tree propagating any wildDescentant information to - * child nodes. - */ - private void buildOptimize() { - if (parent != null && parent.recursiveWildCardChild != null && this.recursiveWildCardChild == null) { - this.recursiveWildCardChild = parent.recursiveWildCardChild; - } - for (Node n : childNodes.values()) n.buildOptimize(); - } - static final String WILDCARD_PATH = "*"; - static final String RECURSIVE_WILDCARD_PATH = "**"; - - /** - * Build a Node tree structure representing all paths of intrest to us. - * This must be done before parsing of the JSON stream starts. Each node - * holds one portion of an path. Taking each path segment in turn this - * method walks the Node tree and finds where the new segment should be - * inserted. It creates a Node representing a field's name, PATH and - * some flags and inserts the Node into the Node tree. - */ - private void build( - List<String> paths, // a List of segments from the split paths - String fieldName, // the fieldName assoc with this path - boolean multiValued, // flag if this fieldName is multiValued or not - boolean record, // is this path a record or a field - String path) { - // recursively walk the paths Lists adding new Nodes as required - String segment = paths.remove(0); // shift out next path segment - - if (segment.length() < 1) throw new RuntimeException("all pieces in path must be non empty " + path); - - // does this "name" already exist as a child node. - Node n = getOrAddNode(segment, childNodes); - if (paths.isEmpty()) { - // We have emptied paths, we are for the moment a leaf of the tree. - // When parsing the actual input we have traversed to a position - // where we actutally have to do something. getOrAddNode() will - // have created and returned a new minimal Node with name and - // pathName already populated. We need to add more information. - if (record) { - //wild cards cannot be used in split - assert !WILDCARD_PATH.equals(n.name); - assert !RECURSIVE_WILDCARD_PATH.equals(n.name); - // split attribute - n.isRecord = true; // flag: split attribute, prepare to emit rec - n.splitPath = fieldName; // the full split attribute path - } else { - if (n.name.equals(WILDCARD_PATH)) { - wildCardChild = n; - } - if (n.name.equals(RECURSIVE_WILDCARD_PATH)) { - recursiveWildCardChild = n.recursiveWildCardChild = n; - } - - // path with content we want to store and return - n.isLeaf = true; // we have to store text found here - n.fieldName = fieldName; // name to store collected text against - if ("$FQN".equals(n.fieldName)) { - n.fieldName = null; - n.useFqn = true; - } - } - } else { - //wildcards must only come at the end - if (WILDCARD_PATH.equals(name) || RECURSIVE_WILDCARD_PATH.equals(name)) - throw new RuntimeException("wild cards are allowed only in the end " + path); - // recurse to handle next paths segment - n.build(paths, fieldName, multiValued, record, path); - } - } - - private Node getOrAddNode(String pathName, Map<String, Node> children) { - Node n = children.get(pathName); - if (n != null) return n; - // new territory! add a new node for this path bitty - children.put(pathName, n = new Node(pathName, this)); - return n; - } - - /** - * Copies a supplied Map to a new Map which is returned. Used to copy a - * records values. If a fields value is a List then they have to be - * deep-copied for thread safety - */ - private static Map<String, Object> getDeepCopy(Map<String, Object> values) { - Map<String, Object> result = new LinkedHashMap<>(); - for (Map.Entry<String, Object> entry : values.entrySet()) { - if (entry.getValue() instanceof List) { - result.put(entry.getKey(), new ArrayList((List) entry.getValue())); - } else { - result.put(entry.getKey(), entry.getValue()); - } - } - return result; - } - - private void parse(JSONParser parser, - Handler handler, - Map<String, Object> values, - Stack<Set<String>> stack, // lists of values to purge - boolean recordStarted) throws IOException { - - int event = -1; - for (; ; ) { - event = parser.nextEvent(); - if (event == EOF) break; - if (event == OBJECT_START) { - handleObjectStart(parser, new HashSet<Node>(), handler, values, stack, recordStarted, null); - } else if (event == ARRAY_START) { - for (; ; ) { - event = parser.nextEvent(); - if (event == ARRAY_END) break; - if (event == OBJECT_START) { - handleObjectStart(parser, new HashSet<Node>(), handler, values, stack, recordStarted, null); - } - } - } - } - - } - - /** - * If a new tag is encountered, check if it is of interest or not by seeing - * if it matches against our node tree. If we have deperted from the node - * tree then walk back though the tree's ancestor nodes checking to see if - * any // expressions exist for the node and compare them against the new - * tag. If matched then "jump" to that node, otherwise ignore the tag. - * <p> - * Note, the list of // expressions found while walking back up the tree - * is chached in the HashMap decends. Then if the new tag is to be skipped, - * any inner chil tags are compared against the cache and jumped to if - * matched. - */ - private void handleObjectStart(final JSONParser parser, final Set<Node> childrenFound, - final Handler handler, final Map<String, Object> values, - final Stack<Set<String>> stack, boolean recordStarted, - MethodFrameWrapper frameWrapper) - throws IOException { - - final boolean isRecordStarted = recordStarted || isRecord; - Set<String> valuesAddedinThisFrame = null; - if (isRecord) { - // This Node is a match for an PATH from a forEach attribute, - // prepare for the clean up that will occurr when the record - // is emitted after its END_ELEMENT is matched - valuesAddedinThisFrame = new HashSet<>(); - stack.push(valuesAddedinThisFrame); - } else if (recordStarted) { - // This node is a child of some parent which matched against forEach - // attribute. Continue to add values to an existing record. - valuesAddedinThisFrame = stack.peek(); - } - - class Wrapper extends MethodFrameWrapper { - Wrapper(Node node, MethodFrameWrapper parent, String name) { - this.node = node; - this.parent = parent; - this.name = name; - } - - @Override - public void walk(int event) throws IOException { - if (event == OBJECT_START) { - node.handleObjectStart(parser, childrenFound, handler, values, stack, isRecordStarted, this); - } else if (event == ARRAY_START) { - for (; ; ) { - event = parser.nextEvent(); - if (event == ARRAY_END) break; - if (event == OBJECT_START) { - node.handleObjectStart(parser, childrenFound, handler, values, stack, isRecordStarted, this); - } - } - } - - } - } - - try { - for (; ; ) { - int event = parser.nextEvent(); - if (event == OBJECT_END) { - if (isRecord()) { - handler.handle(getDeepCopy(values), splitPath); - } - return; - } - assert event == STRING; - assert parser.wasKey(); - String name = parser.getString(); - - Node node = childNodes.get(name); - if (node == null) node = wildCardChild; - if (node == null) node = recursiveWildCardChild; - - if (node != null) { - if (node.isLeaf) {//this is a leaf collect data here - event = parser.nextEvent(); - String nameInRecord = node.fieldName == null ? getNameInRecord(name, frameWrapper, node) : node.fieldName; - MethodFrameWrapper runnable = null; - if (event == OBJECT_START || event == ARRAY_START) { - if (node.recursiveWildCardChild != null) runnable = new Wrapper(node, frameWrapper, name); - } - Object val = parseSingleFieldValue(event, parser, runnable); - if (val != null) { - putValue(values, nameInRecord, val); - if (isRecordStarted) valuesAddedinThisFrame.add(nameInRecord); - } - - } else { - event = parser.nextEvent(); - new Wrapper(node, frameWrapper, name).walk(event); - } - } else { - //this is not something we are interested in . skip it - event = parser.nextEvent(); - if (event == STRING || - event == LONG || - event == NUMBER || - event == BIGNUMBER || - event == BOOLEAN || - event == NULL) { - continue; - } - if (event == ARRAY_START) { - consumeTillMatchingEnd(parser, 0, 1); - continue; - } - if (event == OBJECT_START) { - consumeTillMatchingEnd(parser, 1, 0); - continue; - } else throw new RuntimeException("unexpected token " + event); - - } - } - } finally { - if ((isRecord() || !isRecordStarted) && !stack.empty()) { - Set<String> cleanThis = stack.pop(); - if (cleanThis != null) { - for (String fld : cleanThis) { - values.remove(fld); - } - } - } - } - } - - private String getNameInRecord(String name, MethodFrameWrapper frameWrapper, Node n) { - if (frameWrapper == null || !n.useFqn) return name; - StringBuilder sb = new StringBuilder(); - frameWrapper.prependName(sb); - return sb.append(DELIM).append(name).toString(); - } - - private boolean isRecord() { - return isRecord; - } - - - private void putValue(Map<String, Object> values, String fieldName, Object o) { - if (o == null) return; - Object val = values.get(fieldName); - if (val == null) { - values.put(fieldName, o); - return; - } - if (val instanceof List) { - List list = (List) val; - list.add(o); - return; - } - ArrayList l = new ArrayList(); - l.add(val); - l.add(o); - values.put(fieldName, l); - } - - - @Override - public String toString() { - return name; - } - } // end of class Node - - - /** - * The path is split into segments using the '/' as a seperator. However - * this method deals with special cases where there is a slash '/' character - * inside the attribute value e.g. x/@html='text/html'. We split by '/' but - * then reassemble things were the '/' appears within a quoted sub-string. - * <p> - * We have already enforced that the string must begin with a seperator. This - * method depends heavily on how split behaves if the string starts with the - * seperator or if a sequence of multiple seperator's appear. - */ - private static List<String> splitEscapeQuote(String str) { - List<String> result = new LinkedList<>(); - String[] ss = str.split("/"); - for (int i = 0; i < ss.length; i++) { // i=1: skip seperator at start of string - StringBuilder sb = new StringBuilder(); - int quoteCount = 0; - while (true) { - sb.append(ss[i]); - for (int j = 0; j < ss[i].length(); j++) - if (ss[i].charAt(j) == '\'') quoteCount++; - // have we got a split inside quoted sub-string? - if ((quoteCount % 2) == 0) break; - // yes!; replace the '/' and loop to concat next token - i++; - sb.append("/"); - } - result.add(sb.toString()); - } - return result; - } - - - /** - * Implement this interface to stream records as and when one is found. - */ - public static interface Handler { - /** - * @param record The record map. The key is the field name as provided in - * the addField() methods. The value can be a single String (for single - * valued fields) or a List<String> (for multiValued). - * @param path The forEach path for which this record is being emitted - * If there is any change all parsing will be aborted and the Exception - * is propagated up - */ - public void handle(Map<String, Object> record, String path); - } - - public static Object parseSingleFieldValue(int ev, JSONParser parser, MethodFrameWrapper runnable) throws IOException { - switch (ev) { - case STRING: - return parser.getString(); - case LONG: - return parser.getLong(); - case NUMBER: - return parser.getDouble(); - case BIGNUMBER: - return parser.getNumberChars().toString(); - case BOOLEAN: - return parser.getBoolean(); - case NULL: - parser.getNull(); - return null; - case ARRAY_START: - return parseArrayFieldValue(ev, parser, runnable); - case OBJECT_START: - if (runnable != null) { - runnable.walk(OBJECT_START); - return null; - } - consumeTillMatchingEnd(parser, 1, 0); - return null; - default: - throw new RuntimeException("Error parsing JSON field value. Unexpected " + JSONParser.getEventString(ev)); - } - } - - static abstract class MethodFrameWrapper { - Node node; - MethodFrameWrapper parent; - String name; - - void prependName(StringBuilder sb) { - if (parent != null) { - parent.prependName(sb); - sb.append(DELIM); - } - sb.append(name); - } - - public abstract void walk(int event) throws IOException; - } - - public static List<Object> parseArrayFieldValue(int ev, JSONParser parser, MethodFrameWrapper runnable) throws IOException { - assert ev == ARRAY_START; - - ArrayList lst = new ArrayList(2); - for (; ; ) { - ev = parser.nextEvent(); - if (ev == ARRAY_END) { - if (lst.isEmpty()) return null; - return lst; - } - Object val = parseSingleFieldValue(ev, parser, runnable); - if (val != null) lst.add(val); - } - } - - public static void consumeTillMatchingEnd(JSONParser parser, int obj, int arr) throws IOException { - for (; ; ) { - int event = parser.nextEvent(); - if (event == OBJECT_START) obj++; - if (event == OBJECT_END) obj--; - assert obj >= 0; - if (event == ARRAY_START) arr++; - if (event == ARRAY_END) arr--; - assert arr >= 0; - if (obj == 0 && arr == 0) break; - } - } - -} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d9a661cf/ranger_solrj/src/main/java/org/apache/solr/common/util/NamedList.java ---------------------------------------------------------------------- diff --git a/ranger_solrj/src/main/java/org/apache/solr/common/util/NamedList.java b/ranger_solrj/src/main/java/org/apache/solr/common/util/NamedList.java deleted file mode 100644 index c539b2b..0000000 --- a/ranger_solrj/src/main/java/org/apache/solr/common/util/NamedList.java +++ /dev/null @@ -1,708 +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.common.util; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import org.apache.solr.common.SolrException; - -/** - * A simple container class for modeling an ordered list of name/value pairs. - * - * <p> - * Unlike Maps: - * </p> - * <ul> - * <li>Names may be repeated</li> - * <li>Order of elements is maintained</li> - * <li>Elements may be accessed by numeric index</li> - * <li>Names and Values can both be null</li> - * </ul> - * - * <p> - * A NamedList provides fast access by element number, but not by name. - * </p> - * <p> - * When a NamedList is serialized, order is considered more important than access - * by key, so ResponseWriters that output to a format such as JSON will normally - * choose a data structure that allows order to be easily preserved in various - * clients (i.e. not a straight map). - * If access by key is more important for serialization, see {@link SimpleOrderedMap}, - * or simply use a regular {@link Map} - * </p> - * - */ -public class NamedList<T> implements Cloneable, Serializable, Iterable<Map.Entry<String,T>> { - - private static final long serialVersionUID = 1957981902839867821L; - protected final List<Object> nvPairs; - - /** Creates an empty instance */ - public NamedList() { - nvPairs = new ArrayList<>(); - } - - /** - * Creates a NamedList instance containing the "name,value" pairs contained in the - * Entry[]. - * - * <p> - * Modifying the contents of the Entry[] after calling this constructor may change - * the NamedList (in future versions of Solr), but this is not guaranteed and should - * not be relied upon. To modify the NamedList, refer to {@link #add(String, Object)} - * or {@link #remove(String)}. - * </p> - * - * @param nameValuePairs the name value pairs - */ - public NamedList(Map.Entry<String, ? extends T>[] nameValuePairs) { - nvPairs = nameValueMapToList(nameValuePairs); - } - - /** - * Creates a NamedList instance containing the "name,value" pairs contained in the - * Map. - * - * <p> - * Modifying the contents of the Map after calling this constructor may change - * the NamedList (in future versions of Solr), but this is not guaranteed and should - * not be relied upon. To modify the NamedList, refer to {@link #add(String, Object)} - * or {@link #remove(String)}. - * </p> - * - * @param nameValueMap the name value pairs - */ - public NamedList(Map<String,? extends T> nameValueMap) { - if (null == nameValueMap) { - nvPairs = new ArrayList<>(); - } else { - nvPairs = new ArrayList<>(nameValueMap.size()); - for (Map.Entry<String,? extends T> ent : nameValueMap.entrySet()) { - nvPairs.add(ent.getKey()); - nvPairs.add(ent.getValue()); - } - } - } - - /** - * Creates an instance backed by an explicitly specified list of - * pairwise names/values. - * - * <p> - * When using this constructor, runtime type safety is only guaranteed if - * all even numbered elements of the input list are of type "T". - * </p> - * - * @param nameValuePairs underlying List which should be used to implement a NamedList - * @deprecated Use {@link #NamedList(java.util.Map.Entry[])} for the NamedList instantiation - */ - @Deprecated - public NamedList(List<Object> nameValuePairs) { - nvPairs=nameValuePairs; - } - - /** - * Method to serialize Map.Entry<String, ?> to a List in which the even - * indexed elements (0,2,4. ..etc) are Strings and odd elements (1,3,5,) are of - * the type "T". - * - * @return Modified List as per the above description - * @deprecated This a temporary placeholder method until the guts of the class - * are actually replaced by List<String, ?>. - * @see <a href="https://issues.apache.org/jira/browse/SOLR-912">SOLR-912</a> - */ - @Deprecated - private List<Object> nameValueMapToList(Map.Entry<String, ? extends T>[] nameValuePairs) { - List<Object> result = new ArrayList<>(); - for (Map.Entry<String, ?> ent : nameValuePairs) { - result.add(ent.getKey()); - result.add(ent.getValue()); - } - return result; - } - - /** The total number of name/value pairs */ - public int size() { - return nvPairs.size() >> 1; - } - - /** - * The name of the pair at the specified List index - * - * @return null if no name exists - */ - public String getName(int idx) { - return (String)nvPairs.get(idx << 1); - } - - /** - * The value of the pair at the specified List index - * - * @return may be null - */ - @SuppressWarnings("unchecked") - public T getVal(int idx) { - return (T)nvPairs.get((idx << 1) + 1); - } - - /** - * Adds a name/value pair to the end of the list. - */ - public void add(String name, T val) { - nvPairs.add(name); - nvPairs.add(val); - } - - /** - * Modifies the name of the pair at the specified index. - */ - public void setName(int idx, String name) { - nvPairs.set(idx<<1, name); - } - - /** - * Modifies the value of the pair at the specified index. - * - * @return the value that used to be at index - */ - public T setVal(int idx, T val) { - int index = (idx<<1)+1; - @SuppressWarnings("unchecked") - T old = (T)nvPairs.get( index ); - nvPairs.set(index, val); - return old; - } - - /** - * Removes the name/value pair at the specified index. - * - * @return the value at the index removed - */ - public T remove(int idx) { - int index = (idx<<1); - nvPairs.remove(index); - @SuppressWarnings("unchecked") - T result = (T)nvPairs.remove(index); // same index, as things shifted in previous remove - return result; - } - - /** - * Scans the list sequentially beginning at the specified index and - * returns the index of the first pair with the specified name. - * - * @param name name to look for, may be null - * @param start index to begin searching from - * @return The index of the first matching pair, -1 if no match - */ - public int indexOf(String name, int start) { - int sz = size(); - for (int i=start; i<sz; i++) { - String n = getName(i); - if (name==null) { - if (n==null) return i; // matched null - } else if (name.equals(n)) { - return i; - } - } - return -1; - } - - /** - * Gets the value for the first instance of the specified name - * found. - * <p> - * NOTE: this runs in linear time (it scans starting at the - * beginning of the list until it finds the first pair with - * the specified name). - * - * @return null if not found or if the value stored was null. - * @see #indexOf - * @see #get(String,int) - * - */ - public T get(String name) { - return get(name,0); - } - - /** - * Gets the value for the first instance of the specified name - * found starting at the specified index. - * <p> - * NOTE: this runs in linear time (it scans starting at the - * specified position until it finds the first pair with - * the specified name). - * - * @return null if not found or if the value stored was null. - * @see #indexOf - */ - public T get(String name, int start) { - int sz = size(); - for (int i=start; i<sz; i++) { - String n = getName(i); - if (name==null) { - if (n==null) return getVal(i); - } else if (name.equals(n)) { - return getVal(i); - } - } - return null; - } - - /** - * Gets the values for the the specified name - * - * @param name Name - * @return List of values - */ - public List<T> getAll(String name) { - List<T> result = new ArrayList<>(); - int sz = size(); - for (int i = 0; i < sz; i++) { - String n = getName(i); - if (name==n || (name!=null && name.equals(n))) { - result.add(getVal(i)); - } - } - return result; - } - - /** - * Removes all values matching the specified name - * - * @param name Name - */ - private void killAll(String name) { - int sz = size(); - // Go through the list backwards, removing matches as found. - for (int i = sz - 1; i >= 0; i--) { - String n = getName(i); - if (name==n || (name!=null && name.equals(n))) { - remove(i); - } - } - } - - /** - * Recursively parses the NamedList structure to arrive at a specific element. - * As you descend the NamedList tree, the last element can be any type, - * including NamedList, but the previous elements MUST be NamedList objects - * themselves. A null value is returned if the indicated hierarchy doesn't - * exist, but NamedList allows null values so that could be the actual value - * at the end of the path. - * - * This method is particularly useful for parsing the response from Solr's - * /admin/mbeans handler, but it also works for any complex structure. - * - * Explicitly casting the return value is recommended. An even safer option is - * to accept the return value as an object and then check its type. - * - * Usage examples: - * - * String coreName = (String) response.findRecursive - * ("solr-mbeans", "CORE", "core", "stats", "coreName"); - * long numDoc = (long) response.findRecursive - * ("solr-mbeans", "CORE", "searcher", "stats", "numDocs"); - * - * @param args - * One or more strings specifying the tree to navigate. - * @return the last entry in the given path hierarchy, null if not found. - */ - public Object findRecursive(String... args) { - NamedList<?> currentList = null; - Object value = null; - for (int i = 0; i < args.length; i++) { - String key = args[i]; - /* - * The first time through the loop, the current list is null, so we assign - * it to this list. Then we retrieve the first key from this list and - * assign it to value. - * - * On the next loop, we check whether the retrieved value is a NamedList. - * If it is, then we drop down to that NamedList, grab the value of the - * next key, and start the loop over. If it is not a NamedList, then we - * assign the value to null and break out of the loop. - * - * Assigning the value to null and then breaking out of the loop seems - * like the wrong thing to do, but there's a very simple reason that it - * works: If we have reached the last key, then the loop ends naturally - * after we retrieve the value, and that code is never executed. - */ - if (currentList == null) { - currentList = this; - } else { - if (value instanceof NamedList) { - currentList = (NamedList<?>) value; - } else { - value = null; - break; - } - } - /* - * We do not need to do a null check on currentList for the following - * assignment. The instanceof check above will fail if the current list is - * null, and if that happens, the loop will end before this point. - */ - value = currentList.get(key, 0); - } - return value; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append('{'); - int sz = size(); - for (int i=0; i<sz; i++) { - if (i != 0) sb.append(','); - sb.append(getName(i)); - sb.append('='); - sb.append(getVal(i)); - } - sb.append('}'); - - return sb.toString(); - } - - public NamedList getImmutableCopy() { - NamedList copy = clone(); - return new NamedList<>( Collections.unmodifiableList(copy.nvPairs)); - } - - public Map asMap(int maxDepth) { - LinkedHashMap result = new LinkedHashMap(); - for(int i=0;i<size();i++){ - Object val = getVal(i); - if (val instanceof NamedList && maxDepth> 0) { - //the maxDepth check is to avoid stack overflow due to infinite recursion - val = ((NamedList) val).asMap(maxDepth-1); - } - Object old = result.put(getName(i), val); - if(old!=null){ - if (old instanceof List) { - List list = (List) old; - list.add(val); - result.put(getName(i),old); - } else { - ArrayList l = new ArrayList(); - l.add(old); - l.add(val); - result.put(getName(i), l); - } - } - } - return result; - } - - /** - * - * Helper class implementing Map.Entry<String, T> to store the key-value - * relationship in NamedList (the keys of which are String-s) - */ - public static final class NamedListEntry<T> implements Map.Entry<String,T> { - - public NamedListEntry() { - - } - - public NamedListEntry(String _key, T _value) { - key = _key; - value = _value; - } - - @Override - public String getKey() { - return key; - } - - @Override - public T getValue() { - return value; - } - - @Override - public T setValue(T _value) { - T oldValue = value; - value = _value; - return oldValue; - } - - private String key; - - private T value; - } - - /** - * Iterates over the Map and sequentially adds its key/value pairs - */ - public boolean addAll(Map<String,T> args) { - for (Map.Entry<String, T> entry : args.entrySet() ) { - add(entry.getKey(), entry.getValue()); - } - return args.size()>0; - } - - /** Appends the elements of the given NamedList to this one. */ - public boolean addAll(NamedList<T> nl) { - nvPairs.addAll(nl.nvPairs); - return nl.size()>0; - } - - /** - * Makes a <i>shallow copy</i> of the named list. - */ - @Override - public NamedList<T> clone() { - ArrayList<Object> newList = new ArrayList<>(nvPairs.size()); - newList.addAll(nvPairs); - return new NamedList<>(newList); - } - - //---------------------------------------------------------------------------- - // Iterable interface - //---------------------------------------------------------------------------- - - /** - * Support the Iterable interface - */ - @Override - public Iterator<Map.Entry<String,T>> iterator() { - - final NamedList<T> list = this; - - Iterator<Map.Entry<String,T>> iter = new Iterator<Map.Entry<String,T>>() { - - int idx = 0; - - @Override - public boolean hasNext() { - return idx < list.size(); - } - - @Override - public Map.Entry<String,T> next() { - final int index = idx++; - Map.Entry<String,T> nv = new Map.Entry<String,T>() { - @Override - public String getKey() { - return list.getName( index ); - } - - @Override - public T getValue() { - return list.getVal( index ); - } - - @Override - public String toString() { - return getKey()+"="+getValue(); - } - - @Override - public T setValue(T value) { - return list.setVal(index, value); - } - }; - return nv; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - return iter; - } - - /** - * NOTE: this runs in linear time (it scans starting at the - * beginning of the list until it finds the first pair with - * the specified name). - */ - public T remove(String name) { - int idx = indexOf(name, 0); - if(idx != -1) return remove(idx); - return null; - } - - /** - * Removes and returns all values for the specified name. Returns null if - * no matches found. This method will return all matching objects, - * regardless of data type. If you are parsing Solr config options, the - * {@link #removeConfigArgs(String)} or {@link #removeBooleanArg(String)} - * methods will probably work better. - * - * @param name Name - * @return List of values - */ - public List<T> removeAll(String name) { - List<T> result = new ArrayList<>(); - result = getAll(name); - if (result.size() > 0 ) { - killAll(name); - return result; - } - return null; - } - - /** - * Used for getting a boolean argument from a NamedList object. If the name - * is not present, returns null. If there is more than one value with that - * name, or if the value found is not a Boolean or a String, throws an - * exception. If there is only one value present and it is a Boolean or a - * String, the value is removed and returned as a Boolean. If an exception - * is thrown, the NamedList is not modified. See {@link #removeAll(String)} - * and {@link #removeConfigArgs(String)} for additional ways of gathering - * configuration information from a NamedList. - * - * @param name - * The key to look up in the NamedList. - * @return The boolean value found. - * @throws SolrException - * If multiple values are found for the name or the value found is - * not a Boolean or a String. - */ - public Boolean removeBooleanArg(final String name) { - Boolean bool = getBooleanArg(name); - if (null != bool) { - remove(name); - } - return bool; - } - - /** - * Used for getting a boolean argument from a NamedList object. If the name - * is not present, returns null. If there is more than one value with that - * name, or if the value found is not a Boolean or a String, throws an - * exception. If there is only one value present and it is a Boolean or a - * String, the value is returned as a Boolean. The NamedList is not - * modified. See {@link #remove(String)}, {@link #removeAll(String)} - * and {@link #removeConfigArgs(String)} for additional ways of gathering - * configuration information from a NamedList. - * - * @param name The key to look up in the NamedList. - * @return The boolean value found. - * @throws SolrException - * If multiple values are found for the name or the value found is - * not a Boolean or a String. - */ - public Boolean getBooleanArg(final String name) { - Boolean bool; - List<T> values = getAll(name); - if (0 == values.size()) { - return null; - } - if (values.size() > 1) { - throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, - "Only one '" + name + "' is allowed"); - } - Object o = get(name); - if (o instanceof Boolean) { - bool = (Boolean)o; - } else if (o instanceof CharSequence) { - bool = Boolean.parseBoolean(o.toString()); - } else { - throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, - "'" + name + "' must have type Boolean or CharSequence; found " + o.getClass()); - } - return bool; - } - - /** - * Used for getting one or many arguments from NamedList objects that hold - * configuration parameters. Finds all entries in the NamedList that match - * the given name. If they are all strings or arrays of strings, remove them - * from the NamedList and return the individual elements as a {@link Collection}. - * Parameter order will be preserved if the returned collection is handled as - * an {@link ArrayList}. Throws SolrException if any of the values associated - * with the name are not strings or arrays of strings. If exception is - * thrown, the NamedList is not modified. Returns an empty collection if no - * matches found. If you need to remove and retrieve all matching items from - * the NamedList regardless of data type, use {@link #removeAll(String)} instead. - * The {@link #removeBooleanArg(String)} method can be used for retrieving a - * boolean argument. - * - * @param name - * The key to look up in the NamedList. - * @return A collection of the values found. - * @throws SolrException - * If values are found for the input key that are not strings or - * arrays of strings. - */ - @SuppressWarnings("rawtypes") - public Collection<String> removeConfigArgs(final String name) - throws SolrException { - List<T> objects = getAll(name); - List<String> collection = new ArrayList<>(size() / 2); - final String err = "init arg '" + name + "' must be a string " - + "(ie: 'str'), or an array (ie: 'arr') containing strings; found: "; - - for (Object o : objects) { - if (o instanceof String) { - collection.add((String) o); - continue; - } - - // If it's an array, convert to List (which is a Collection). - if (o instanceof Object[]) { - o = Arrays.asList((Object[]) o); - } - - // If it's a Collection, collect each value. - if (o instanceof Collection) { - for (Object item : (Collection) o) { - if (!(item instanceof String)) { - throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, err + item.getClass()); - } - collection.add((String) item); - } - continue; - } - throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, err + o.getClass()); - } - - if (collection.size() > 0) { - killAll(name); - } - - return collection; - } - - public void clear() { - nvPairs.clear(); - } - - @Override - public int hashCode() { - return nvPairs.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof NamedList)) return false; - NamedList<?> nl = (NamedList<?>) obj; - return this.nvPairs.equals(nl.nvPairs); - } -} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d9a661cf/ranger_solrj/src/main/java/org/apache/solr/common/util/ObjectReleaseTracker.java ---------------------------------------------------------------------- diff --git a/ranger_solrj/src/main/java/org/apache/solr/common/util/ObjectReleaseTracker.java b/ranger_solrj/src/main/java/org/apache/solr/common/util/ObjectReleaseTracker.java deleted file mode 100644 index 8be12df..0000000 --- a/ranger_solrj/src/main/java/org/apache/solr/common/util/ObjectReleaseTracker.java +++ /dev/null @@ -1,62 +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.common.util; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -public class ObjectReleaseTracker { - public static Map<Object,String> OBJECTS = new ConcurrentHashMap<>(); - - public static boolean track(Object object) { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - new ObjectTrackerException().printStackTrace(pw); - OBJECTS.put(object, sw.toString()); - return true; - } - - public static boolean release(Object object) { - OBJECTS.remove(object); - return true; - } - - public static boolean clearObjectTrackerAndCheckEmpty() { - Set<Entry<Object,String>> entries = OBJECTS.entrySet(); - boolean empty = entries.isEmpty(); - if (entries.size() > 0) { - System.err.println("ObjectTracker found objects that were not released!!!"); - } - - for (Entry<Object,String> entry : entries) { - System.err.println(entry.getValue()); - } - - OBJECTS.clear(); - - return empty; - } - - private static class ObjectTrackerException extends RuntimeException { - - } -} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d9a661cf/ranger_solrj/src/main/java/org/apache/solr/common/util/RetryUtil.java ---------------------------------------------------------------------- diff --git a/ranger_solrj/src/main/java/org/apache/solr/common/util/RetryUtil.java b/ranger_solrj/src/main/java/org/apache/solr/common/util/RetryUtil.java deleted file mode 100644 index e3a0c5b..0000000 --- a/ranger_solrj/src/main/java/org/apache/solr/common/util/RetryUtil.java +++ /dev/null @@ -1,43 +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.common.util; - -import java.util.concurrent.TimeUnit; - -public class RetryUtil { - interface RetryCmd { - void execute() throws Throwable; - } - - public static void retryOnThrowable(Class clazz, long timeoutms, long intervalms, RetryCmd cmd) throws Throwable { - long timeout = System.nanoTime() + TimeUnit.NANOSECONDS.convert(timeoutms, TimeUnit.MILLISECONDS); - while (true) { - try { - cmd.execute(); - } catch (Throwable t) { - if (clazz.isInstance(t) && System.nanoTime() < timeout) { - Thread.sleep(intervalms); - continue; - } - throw t; - } - // success - break; - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d9a661cf/ranger_solrj/src/main/java/org/apache/solr/common/util/SimpleOrderedMap.java ---------------------------------------------------------------------- diff --git a/ranger_solrj/src/main/java/org/apache/solr/common/util/SimpleOrderedMap.java b/ranger_solrj/src/main/java/org/apache/solr/common/util/SimpleOrderedMap.java deleted file mode 100644 index 1a217e7..0000000 --- a/ranger_solrj/src/main/java/org/apache/solr/common/util/SimpleOrderedMap.java +++ /dev/null @@ -1,67 +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.common.util; - -import java.util.*; - - -/** <code>SimpleOrderedMap</code> is a {@link NamedList} where access by key is more - * important than maintaining order when it comes to representing the - * held data in other forms, as ResponseWriters normally do. - * It's normally not a good idea to repeat keys or use null keys, but this - * is not enforced. If key uniqueness enforcement is desired, use a regular {@link Map}. - * <p> - * For example, a JSON response writer may choose to write a SimpleOrderedMap - * as {"foo":10,"bar":20} and may choose to write a NamedList as - * ["foo",10,"bar",20]. An XML response writer may choose to render both - * the same way. - * </p> - * <p> - * This class does not provide efficient lookup by key, its main purpose is - * to hold data to be serialized. It aims to minimize overhead and to be - * efficient at adding new elements. - * </p> - */ -public class SimpleOrderedMap<T> extends NamedList<T> { - /** Creates an empty instance */ - public SimpleOrderedMap() { - super(); - } - - /** - * Creates an instance backed by an explicitly specified list of - * pairwise names/values. - * - * @param nameValuePairs underlying List which should be used to implement a SimpleOrderedMap; modifying this List will affect the SimpleOrderedMap. - */ - @Deprecated - public SimpleOrderedMap(List<Object> nameValuePairs) { - super(nameValuePairs); - } - - public SimpleOrderedMap(Map.Entry<String, T>[] nameValuePairs) { - super(nameValuePairs); - } - - @Override - public SimpleOrderedMap<T> clone() { - ArrayList<Object> newList = new ArrayList<>(nvPairs.size()); - newList.addAll(nvPairs); - return new SimpleOrderedMap<>(newList); - } -} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d9a661cf/ranger_solrj/src/main/java/org/apache/solr/common/util/SolrjNamedThreadFactory.java ---------------------------------------------------------------------- diff --git a/ranger_solrj/src/main/java/org/apache/solr/common/util/SolrjNamedThreadFactory.java b/ranger_solrj/src/main/java/org/apache/solr/common/util/SolrjNamedThreadFactory.java deleted file mode 100644 index 46e462d..0000000 --- a/ranger_solrj/src/main/java/org/apache/solr/common/util/SolrjNamedThreadFactory.java +++ /dev/null @@ -1,51 +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.common.util; - -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; - - -public class SolrjNamedThreadFactory implements ThreadFactory { - private static final AtomicInteger poolNumber = new AtomicInteger(1); - private final ThreadGroup group; - private final AtomicInteger threadNumber = new AtomicInteger(1); - private final String prefix; - - public SolrjNamedThreadFactory(String namePrefix) { - SecurityManager s = System.getSecurityManager(); - group = (s != null)? s.getThreadGroup() : - Thread.currentThread().getThreadGroup(); - prefix = namePrefix + "-" + - poolNumber.getAndIncrement() + - "-thread-"; - } - - @Override - public Thread newThread(Runnable r) { - Thread t = new Thread(group, r, - prefix + threadNumber.getAndIncrement(), - 0); - - t.setDaemon(false); - - if (t.getPriority() != Thread.NORM_PRIORITY) - t.setPriority(Thread.NORM_PRIORITY); - return t; - } -}