001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License.
018 *
019 */
020package org.apache.directory.server.core.partition.impl.btree.jdbm;
021
022
023import java.io.IOException;
024
025import org.apache.directory.api.util.Strings;
026import org.apache.directory.server.core.avltree.Marshaller;
027import org.apache.directory.server.i18n.I18n;
028
029
030/**
031 * Serializes and deserializes a BTreeRedirect object to and from a byte[]
032 * representation.  The serialized form is a fixed size byte array of length
033 * 9.  The first byte contains the magic number of value 1 for this kind of
034 * object and the last 8 bytes encode the record identifier as a long for
035 * the BTree.
036 *
037 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
038 */
039public class BTreeRedirectMarshaller implements Marshaller<BTreeRedirect>
040{
041    /** fixed byte array size of 9 for serialized form */
042    static final int SIZE = 9;
043    /** a reusable instance of this Marshaller */
044    public static final BTreeRedirectMarshaller INSTANCE = new BTreeRedirectMarshaller();
045
046
047    /**
048     * @see Marshaller#serialize(Object)
049     */
050    public final byte[] serialize( BTreeRedirect redirect ) throws IOException
051    {
052        byte[] bites = new byte[SIZE];
053
054        bites[0] = 1;
055
056        bites[1] = ( byte ) ( 0xFF & ( redirect.recId >> 56 ) );
057        bites[2] = ( byte ) ( 0xFF & ( redirect.recId >> 48 ) );
058        bites[3] = ( byte ) ( 0xFF & ( redirect.recId >> 40 ) );
059        bites[4] = ( byte ) ( 0xFF & ( redirect.recId >> 32 ) );
060        bites[5] = ( byte ) ( 0xFF & ( redirect.recId >> 24 ) );
061        bites[6] = ( byte ) ( 0xFF & ( redirect.recId >> 16 ) );
062        bites[7] = ( byte ) ( 0xFF & ( redirect.recId >> 8 ) );
063        bites[8] = ( byte ) ( 0xFF & ( redirect.recId ) );
064
065        return bites;
066    }
067
068
069    /**
070     * @see Marshaller#deserialize(byte[])
071     */
072    public final BTreeRedirect deserialize( byte[] bytes ) throws IOException
073    {
074        if ( ( bytes == null ) || ( bytes.length != SIZE ) || ( bytes[0] != 1 ) )
075        {
076            if ( bytes != null )
077            {
078                throw new IOException( I18n.err( I18n.ERR_568, Strings.dumpBytes( bytes ) ) );
079            }
080            else
081            {
082                throw new IOException( I18n.err( I18n.ERR_569 ) );
083            }
084        }
085
086        long recId = ( ( long ) ( bytes[1] & 0xFF ) << 56 )
087                | ( ( long ) ( bytes[2] & 0xFF ) << 48 )
088                | ( ( long ) ( bytes[3] & 0xFF ) << 40 )
089                | ( ( long ) ( bytes[4] & 0xFF ) << 32 )
090                | ( ( long ) ( bytes[5] & 0xFF ) << 24 )
091                | ( ( long ) ( bytes[6] & 0xFF ) << 16 )
092                | ( ( long ) ( bytes[7] & 0xFF ) << 8 )
093                | ( ( long ) ( bytes[8] & 0xFF ) );
094
095        return new BTreeRedirect( recId );
096    }
097
098
099    /**
100     * Checks to see if a byte[] contains a redirect.
101     *
102     * @param bites the bites to check for a redirect
103     * @return true if bites contain BTreeRedirect, false otherwise
104     */
105    public static boolean isRedirect( byte[] bites )
106    {
107        return ( bites != null ) && ( bites.length == SIZE ) && ( bites[0] == 1 );
108    }
109}