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.changelog;
021    
022    
023    import java.io.Externalizable;
024    import java.io.IOException;
025    import java.io.ObjectInput;
026    import java.io.ObjectOutput;
027    import java.util.ArrayList;
028    import java.util.List;
029    
030    import org.apache.directory.server.core.LdapPrincipal;
031    import org.apache.directory.shared.ldap.entry.EntryAttribute;
032    import org.apache.directory.shared.ldap.ldif.LdifEntry;
033    
034    
035    /**
036     * A loggable directory change event.
037     *
038     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
039     * @version $Rev$, $Date$
040     */
041    public class ChangeLogEvent implements Externalizable
042    {
043        private static final long serialVersionUID = 1L;
044        private String zuluTime;
045        private long revision;
046        private LdifEntry forwardLdif;
047        
048        /** The revert changes. Can contain more than one single change */
049        private List<LdifEntry> reverseLdifs;
050        private LdapPrincipal committer;
051    
052    
053        /**
054         * Creates a new instance of ChangeLogEvent, used during the deserialization
055         * process
056         */
057        public ChangeLogEvent()
058        {
059        }
060    
061    
062        /**
063         * Creates a new instance of ChangeLogEvent.
064         *
065         * @param revision the revision number for the change
066         * @param zuluTime the timestamp for when the change occurred in generalizedTime format
067         */
068        public ChangeLogEvent( long revision, String zuluTime, LdapPrincipal committer, LdifEntry forwardLdif,
069                               LdifEntry reverseLdif )
070        {
071            this.zuluTime = zuluTime;
072            this.revision = revision;
073            this.forwardLdif = forwardLdif;
074            this.reverseLdifs = new ArrayList<LdifEntry>(1);
075            reverseLdifs.add( reverseLdif );
076            this.committer = committer;
077        }
078    
079    
080        /**
081         * Creates a new instance of ChangeLogEvent.
082         *
083         * @param revision the revision number for the change
084         * @param zuluTime the timestamp for when the change occurred in generalizedTime format
085         * @param committer the user who did the modification
086         * @param forwardLdif the original operation
087         * @param reverseLdifs the reverted operations
088         */
089        public ChangeLogEvent( long revision, String zuluTime, LdapPrincipal committer, LdifEntry forwardLdif,
090                               List<LdifEntry> reverseLdifs )
091        {
092            this.zuluTime = zuluTime;
093            this.revision = revision;
094            this.forwardLdif = forwardLdif;
095            this.reverseLdifs = reverseLdifs;
096            this.committer = committer;
097        }
098    
099    
100        /**
101         * @return the forwardLdif
102         */
103        public LdifEntry getForwardLdif()
104        {
105            return forwardLdif;
106        }
107    
108    
109        /**
110         * @return the reverseLdif
111         */
112        public List<LdifEntry> getReverseLdifs()
113        {
114            return reverseLdifs;
115        }
116    
117    
118        /**
119         * @return the committer
120         */
121        public LdapPrincipal getCommitterPrincipal()
122        {
123            return committer;
124        }
125    
126    
127        /**
128         * Gets the revision of this event.
129         *
130         * @return the revision
131         */
132        public long getRevision()
133        {
134            return revision;
135        }
136    
137    
138        /**
139         * Gets the generalizedTime when this event occured.
140         *
141         * @return the zuluTime when this event occured
142         */
143        public String getZuluTime()
144        {
145            return zuluTime;
146        }
147    
148    
149        public EntryAttribute get( String attributeName )
150        {
151            return forwardLdif.get( attributeName );
152        }
153    
154    
155        /**
156         * @see Externalizable#readExternal(ObjectInput)
157         * 
158         * @param in The stream from which the ChangeOlgEvent is read
159         * @throws IOException If the stream can't be read
160         * @throws ClassNotFoundException If the ChangeLogEvent can't be created 
161         */
162        public void readExternal( ObjectInput in ) throws IOException , ClassNotFoundException
163        {
164            // Read the committer
165            committer = (LdapPrincipal)in.readObject();
166            
167            // Read the revision
168            revision = in.readLong();
169            
170            // Read the time
171            boolean hasZuluTime = in.readBoolean();
172            
173            if ( hasZuluTime )
174            {
175                zuluTime = in.readUTF();
176            }
177            
178            // Read the forward LDIF
179            boolean hasForwardLdif = in.readBoolean();
180            
181            if ( hasForwardLdif )
182            {
183                forwardLdif = (LdifEntry)in.readObject();
184            }
185            
186            // Read the reverse LDIF number
187            int nbReverseLdif = in.readInt();
188            
189            if ( nbReverseLdif > 0 )
190            {
191                // Read each reverse ldif
192                reverseLdifs = new ArrayList<LdifEntry>(nbReverseLdif);
193                
194                for ( int i = 0; i < nbReverseLdif; i++ )
195                {
196                    reverseLdifs.add( (LdifEntry)in.readObject() ); 
197                }
198            }
199        }
200    
201    
202        /**
203         * @see Externalizable#readExternal(ObjectInput)<p>
204         *
205         *@param out The stream in which the ChangeLogEvent will be serialized. 
206         *
207         *@throws IOException If the serialization fail
208         */
209        public void writeExternal( ObjectOutput out ) throws IOException
210        {
211            // Write the committer
212            out.writeObject( committer );
213            
214            // write the revision
215            out.writeLong( revision );
216            
217            // write the time
218            
219            if ( zuluTime != null )
220            {
221                out.writeBoolean( true );
222                out.writeUTF( zuluTime );
223            }
224            else
225            {
226                out.writeBoolean( false );
227            }
228            
229            // write the forward LDIF
230            if ( forwardLdif != null )
231            {
232                out.writeBoolean( true );
233                out.writeObject( forwardLdif );
234            }
235            else
236            {
237                out.writeBoolean( false );
238            }
239            
240            // write the reverse LDIF
241            if ( reverseLdifs != null )
242            {
243                out.writeInt( reverseLdifs.size() );
244                
245                // write each reverse
246                for ( LdifEntry reverseLdif:reverseLdifs )
247                {
248                    out.writeObject( reverseLdif );
249                }
250            }
251            else
252            {
253                out.writeBoolean( false );
254            }
255            
256            // and flush the result
257            out.flush();
258        }
259    
260    
261        @Override
262        public String toString()
263        {
264            StringBuilder sb = new StringBuilder();
265            sb.append( "ChangeLogEvent { " );
266            
267            sb.append( "principal=" )
268            .append( getCommitterPrincipal() )
269            .append( ", " );
270            
271            sb.append( "zuluTime=" )
272              .append( getZuluTime() )
273              .append( ", " );
274            
275            sb.append( "revision=" )
276            .append( getRevision() )
277            .append( ", " );
278            
279            sb.append( "\nforwardLdif=" )
280            .append( getForwardLdif() )
281            .append( ", " );
282            
283            if ( reverseLdifs != null )
284            {
285                sb.append( "\nreverseLdif number=" ).append( reverseLdifs.size() );
286                int i = 0;
287                
288                for ( LdifEntry reverseLdif:reverseLdifs )
289                {
290                    sb.append( "\nReverse[" ).append( i++ ).append( "] :\n" );
291                    sb.append( reverseLdif );
292                }
293            }
294            
295            sb.append( " }" );
296    
297            return sb.toString();
298        }
299    }