All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.maven.index.reader.ChunkWriter Maven / Gradle / Ivy

Go to download

Indexer Reader is a dependency-less library that is able to read published (remote) index with incremental update support, making usable to integrate published Maven Indexes into any engine without depending on maven-indexer-core and its transitive dependencies.

There is a newer version: 7.1.5
Show newest version
package org.apache.maven.index.reader;

/*
 * 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.
 */

import java.io.Closeable;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.zip.GZIPOutputStream;

/**
 * Maven Index published binary chunk writer, it writes raw Maven Indexer records to the transport binary format.
 * Instances of this class MUST BE handled as resources (have them closed once done with them), it is user
 * responsibility to close them, ideally in try-with-resource block.
 *
 * @since 5.1.2
 */
public class ChunkWriter
        implements Closeable
{
    private static final int F_INDEXED = 1;

    private static final int F_TOKENIZED = 2;

    private static final int F_STORED = 4;

    private final String chunkName;

    private final DataOutputStream dataOutputStream;

    private final int version;

    private final Date timestamp;

    public ChunkWriter( final String chunkName,
                        final OutputStream outputStream,
                        final int version,
                        final Date timestamp )
            throws IOException
    {
        this.chunkName = chunkName.trim();
        this.dataOutputStream = new DataOutputStream( new GZIPOutputStream( outputStream, 2 * 1024 ) );
        this.version = version;
        this.timestamp = timestamp;

        dataOutputStream.writeByte( version );
        dataOutputStream.writeLong( timestamp == null ? -1 : timestamp.getTime() );
    }

    /**
     * Returns the chunk name.
     */
    public String getName()
    {
        return chunkName;
    }

    /**
     * Returns index version. All releases so far always returned {@code 1}.
     */
    public int getVersion()
    {
        return version;
    }

    /**
     * Returns the index timestamp of last update of the index.
     */
    public Date getTimestamp()
    {
        return timestamp;
    }

    /**
     * Writes out the record iterator and returns the written record count.
     */
    public int writeChunk( final Iterator> iterator )
            throws IOException
    {
        int written = 0;
        while ( iterator.hasNext() )
        {
            writeRecord( iterator.next(), dataOutputStream );
            written++;
        }
        return written;
    }

    /**
     * Closes this reader and it's underlying input.
     */
    @Override
    public void close()
            throws IOException
    {
        dataOutputStream.close();
    }

    private static void writeRecord( final Map record, final DataOutput dataOutput )
            throws IOException
    {
        dataOutput.writeInt( record.size() );
        for ( Map.Entry entry : record.entrySet() )
        {
            writeField( entry.getKey(), entry.getValue(), dataOutput );
        }
    }

    private static void writeField( final String fieldName, final String fieldValue, final DataOutput dataOutput )
            throws IOException
    {
        boolean isIndexed = !( fieldName.equals( "i" ) || fieldName.equals( "m" ) );
        boolean isTokenized =
                !( fieldName.equals( "i" ) || fieldName.equals( "m" ) || fieldName.equals( "1" ) || fieldName.equals(
                        "px" ) );
        int flags = ( isIndexed ? F_INDEXED : 0 ) + ( isTokenized ? F_TOKENIZED : 0 ) + F_STORED;
        dataOutput.writeByte( flags );
        dataOutput.writeUTF( fieldName );
        writeUTF( fieldValue, dataOutput );
    }

    private static void writeUTF( final String str, final DataOutput dataOutput )
            throws IOException
    {
        int strlen = str.length();
        int utflen = 0;
        int c;
        // use charAt instead of copying String to char array
        for ( int i = 0; i < strlen; i++ )
        {
            c = str.charAt( i );
            if ( ( c >= 0x0001 ) && ( c <= 0x007F ) )
            {
                utflen++;
            }
            else if ( c > 0x07FF )
            {
                utflen += 3;
            }
            else
            {
                utflen += 2;
            }
        }
        dataOutput.writeInt( utflen );
        byte[] bytearr = new byte[utflen];
        int count = 0;
        int i = 0;
        for ( ; i < strlen; i++ )
        {
            c = str.charAt( i );
            if ( !( ( c >= 0x0001 ) && ( c <= 0x007F ) ) )
            {
                break;
            }
            bytearr[count++] = (byte) c;
        }
        for ( ; i < strlen; i++ )
        {
            c = str.charAt( i );
            if ( ( c >= 0x0001 ) && ( c <= 0x007F ) )
            {
                bytearr[count++] = (byte) c;

            }
            else if ( c > 0x07FF )
            {
                bytearr[count++] = (byte) ( 0xE0 | ( ( c >> 12 ) & 0x0F ) );
                bytearr[count++] = (byte) ( 0x80 | ( ( c >> 6 ) & 0x3F ) );
                bytearr[count++] = (byte) ( 0x80 | ( ( c ) & 0x3F ) );
            }
            else
            {
                bytearr[count++] = (byte) ( 0xC0 | ( ( c >> 6 ) & 0x1F ) );
                bytearr[count++] = (byte) ( 0x80 | ( ( c ) & 0x3F ) );
            }
        }
        dataOutput.write( bytearr, 0, utflen );
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy