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     */
020    package org.apache.directory.server.core.partition.impl.btree.jdbm;
021    
022    import java.io.ByteArrayInputStream;
023    import java.io.ByteArrayOutputStream;
024    import java.io.IOException;
025    import java.io.ObjectInputStream;
026    import java.io.ObjectOutputStream;
027    
028    import jdbm.helper.Serializer;
029    
030    import org.apache.directory.server.i18n.I18n;
031    import org.apache.directory.shared.ldap.entry.DefaultServerEntry;
032    import org.apache.directory.shared.ldap.schema.SchemaManager;
033    import org.slf4j.Logger;
034    import org.slf4j.LoggerFactory;
035    
036    
037    /**
038     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
039     * @version $Rev$, $Date$
040     */
041    public class ServerEntrySerializer implements Serializer
042    {
043        private static final long serialVersionUID = 1L;
044    
045        /** the logger for this class */
046        private static final Logger LOG = LoggerFactory.getLogger( ServerEntrySerializer.class );
047    
048        /**
049         * Speedup for logs
050         */
051        private static final boolean IS_DEBUG = LOG.isDebugEnabled();
052    
053        /** The schemaManager reference */
054        private transient SchemaManager schemaManager;
055    
056    
057        /**
058         * Creates a new instance of ServerEntrySerializer.
059         *
060         * @param schemaManager The reference to the global schemaManager
061         */
062        public ServerEntrySerializer( SchemaManager schemaManager )
063        {
064            this.schemaManager = schemaManager;
065        }
066    
067    
068        /**
069         * <p>
070         * 
071         * This is the place where we serialize entries, and all theirs
072         * elements. the reason why we don't call the underlying methods
073         * (<code>ServerAttribute.write(), Value.write()</code>) is that we need
074         * access to the registries to read back the values.
075         * <p>
076         * The structure used to store the entry is the following :
077         * <li><b>[DN length]</b> : can be -1 if we don't have a DN, 0 if the 
078         * DN is empty, otherwise contains the DN's length.<p> 
079         * <b>NOTE :</b>This should be unnecessary, as the DN should always exists
080         * <p>
081         * </li>
082         * <li>
083         * <b>DN</b> : The entry's DN. Can be empty (rootDSE)<p>
084         * </li>
085         * <li>
086         * <b>[nb attributes]</b> The number of attributes
087         * </li>
088         * <br>
089         * For each attribute :
090         * <li>
091         * <b>[upId]</b> The attribute user provided ID (it can't be null)
092         * </li>
093         * <li>
094         * <b>[nb values]</b> The number of values
095         * </li>
096         * <br>
097         * For each value :
098         * <li>
099         *  <b>[is valid]</b> if the value is valid
100         * </li>
101         * <li>
102         *  <b>[HR flag]</b> if the value is a String
103         * </li>
104         * <li>
105         *  <b>[Streamed flag]</b> if the value is streamed
106         * </li>
107         * <li>
108         *  <b>[UP value]</b> the user provided value
109         * </li>
110         * <li>
111         *  <b>[Norm value]</b> (will be null if normValue == upValue)
112         * </li>
113         */
114        public byte[] serialize( Object object ) throws IOException
115        {
116            DefaultServerEntry entry = ( DefaultServerEntry ) object;
117            
118            ByteArrayOutputStream baos = new ByteArrayOutputStream();
119            ObjectOutputStream out = new ObjectOutputStream( baos );
120    
121            entry.serialize( out );
122    
123            // Note : we don't store the ObjectClassAttribute. I has already
124            // been stored as an attribute.
125    
126            out.flush();
127    
128            if ( IS_DEBUG )
129            {
130                LOG.debug( ">------------------------------------------------" );
131                LOG.debug( "Serialize " + entry );
132            }
133    
134            return baos.toByteArray();
135        }
136    
137        
138        /**
139         *  Deserialize a ServerEntry.
140         *  
141         *  @param bytes the byte array containing the serialized entry
142         *  @return An instance of a ServerEntry object 
143         *  @throws IOException if we can't deserialize the ServerEntry
144         */
145        public Object deserialize( byte[] bytes ) throws IOException
146        {
147            ObjectInputStream in = new ObjectInputStream( new ByteArrayInputStream( bytes ) );
148    
149            DefaultServerEntry serverEntry = new DefaultServerEntry( schemaManager );
150            
151            try
152            {
153                serverEntry.deserialize( in );
154                
155                return serverEntry;
156            }
157            catch ( ClassNotFoundException cnfe )
158            {
159                LOG.error( I18n.err( I18n.ERR_134, cnfe.getLocalizedMessage() ) );
160                return null;
161            }
162        }
163    }