V1DatabaseReader extends DatabaseReader { @NotNull @Override public IndexedDatabase from( @NotNull final Buffer buffer, @NotNull final ArrayBitSetPool bitSetPool, final boolean checksum) { for (int i = 0; i < V1DatabaseFormat.MAGIC.length; i++) if (buffer.get() != V1DatabaseFormat.MAGIC[i]) { throw new IllegalArgumentException("Wrong magic"); } final int dbFeatures = buffer.getInt(); final int unknownFeatures = V1DatabaseFormat.Feature.clearSupported(dbFeatures, SUPPORTED_FEATURES); if (unknownFeatures != 0) { throw new IllegalArgumentException( "Encountered unknown features: <" + Integer.toBinaryString(unknownFeatures) + ">. Supported features: <" + supportedFormatsString() + ">."); } final int documentCount = buffer.getInt(); if (documentCount < 0) { throw new IllegalArgumentException("Wrong document count " + documentCount); } if (buffer.remaining() < V1DatabaseFormat.getDigestSizeInBytes()) { throw new IllegalArgumentException("Too small buffer"); } final Buffer body = buffer.slice( buffer.remaining() - V1DatabaseFormat.getDigestSizeInBytes()); if (checksum) { final Buffer originalDigest = buffer.slice( buffer.position() + body.remaining(), V1DatabaseFormat.getDigestSizeInBytes()); final Buffer currentDigest = calculateDigest(body); if (!currentDigest.equals(originalDigest)) { throw new IllegalArgumentException( "The database is corrupted"); } } final Map<String, FilterableIndex> filters = new HashMap<>(); final Map<String, SortableIndex> sorters = new HashMap<>(); final Map<String, StoredIndex> storers = new HashMap<>(); while (body.hasRemaining()) { final long size = body.getLong(); final int type = body.getInt(); final Buffer segmentBuffer = body.slice(size); final Segment segment = SegmentRegistry.read(type, segmentBuffer); if (segment instanceof FilterableIndex) { final FilterableIndex index = (FilterableIndex) segment; final String name = index.getFieldName(); assert !filters.containsKey(name) : "Duplicate filterable index for field <" + name + ">"; filters.put(name, index); } if (segment instanceof SortableIndex) { final SortableIndex index = (SortableIndex) segment; final String name = index.getFieldName(); assert !sorters.containsKey(name) : "Duplicate sortable index for field <" + name + ">"; sorters.put(name, index); } if (segment instanceof StoredIndex) { final StoredIndex index = (StoredIndex) segment; final String name = index.getFieldName(); assert !storers.containsKey(name) : "Duplicate stored index for field <" + name + ">"; storers.put(name, index); } body.position(body.position() + size); } return new V1Database(documentCount, filters, sorters, storers, bitSetPool); }  @NotNull @Override IndexedDatabase from(
            @NotNull
            final Buffer buffer,
            @NotNull
            final ArrayBitSetPool bitSetPool,
            final boolean checksum); @NotNull @Override Database composite(
            @NotNull
            final Collection<? extends IndexedDatabase> databases,
            @NotNull
            final ArrayBitSetPool bitSetPool); static final V1DatabaseFormat.Feature[] SUPPORTED_FEATURES; }
@Test(expected = NoSuchAlgorithmException.class) public void wrongDigestAlgorithm() throws Throwable { final Buffer buffer = Buffer.from(buildDatabase()); final String originalAlgorithm = getMessageDigestAlgorithm(); final int originalSize = getDigestSizeInBytes(); try { setMessageDigestAlgorithm("WRONG"); INSTANCE.from(buffer); } catch (Exception e) { throw e.getCause(); } finally { setDigestSizeInBytes(originalSize); setMessageDigestAlgorithm(originalAlgorithm); } }
@Test(expected = IllegalArgumentException.class) public void wrongMagic() throws IOException { final byte[] bytes = buildDatabase(); bytes[0] = (byte) ~MAGIC[0]; INSTANCE.from(Buffer.from(bytes)); }
@Test(expected = IllegalArgumentException.class) public void wrongFormat() throws IOException { final byte[] bytes = buildDatabase(); bytes[MAGIC.length] = (byte) ~bytes[MAGIC.length]; INSTANCE.from(Buffer.from(bytes)); }
@Test(expected = IllegalArgumentException.class) public void negativeDocuments() throws IOException { final byte[] bytes = buildDatabase(); final byte[] negative = Ints.toByteArray(-1); System.arraycopy(negative, 0, bytes, MAGIC.length + Ints.BYTES, negative.length); INSTANCE.from(Buffer.from(bytes)); }
@Test(expected = IllegalArgumentException.class) public void tooSmall() throws IOException { final byte[] bytes = Arrays.copyOf( buildDatabase(), MAGIC.length + getDigestSizeInBytes() - 1); INSTANCE.from(Buffer.from(bytes)); }