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.journal;
021
022 import java.io.File;
023 import java.io.FileOutputStream;
024 import java.io.IOException;
025 import java.io.OutputStreamWriter;
026 import java.io.PrintWriter;
027 import java.io.Writer;
028
029 import org.apache.directory.server.core.DirectoryService;
030 import org.apache.directory.server.core.LdapPrincipal;
031 import org.apache.directory.shared.ldap.exception.LdapException;
032 import org.apache.directory.shared.ldap.ldif.LdifEntry;
033 import org.apache.directory.shared.ldap.ldif.LdifUtils;
034
035 /**
036 *
037 * @org.apache.xbean.XBean
038 *
039 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
040 * @version $Rev$, $Date$
041 */
042 public class DefaultJournalStore implements JournalStore
043 {
044 /** The directory where the journal is stored */
045 private File workingDirectory;
046
047 /** The journal file name */
048 private String fileName;
049
050 /** The file containing the journal */
051 private File journal;
052
053 /** The stream used to write data into the journal */
054 private Writer writer;
055
056
057 /**
058 * {@inheritDoc}
059 */
060 public void destroy() throws Exception
061 {
062 if ( writer != null )
063 {
064 writer.close();
065 }
066 }
067
068
069 /**
070 * Initialize the interceptor
071 */
072 public void init( DirectoryService service ) throws Exception
073 {
074 if ( workingDirectory == null )
075 {
076 workingDirectory = service.getWorkingDirectory();
077 }
078
079 /** Load or create the journal file */
080 if ( fileName == null )
081 {
082 fileName = "journal.ldif";
083 }
084
085 journal = new File( workingDirectory, fileName );
086
087 // The new requests are added at the end of the existing journal
088 writer = new PrintWriter(
089 new OutputStreamWriter(
090 new FileOutputStream( journal, true ) ) );
091 }
092
093
094 /**
095 * Stores an event into the journal.
096 *
097 * @param principal The principal who is logging the change
098 * @param revision The operation revision
099 * @param forward The change to log
100 */
101 public boolean log( LdapPrincipal principal, long revision, LdifEntry forward )
102 {
103 synchronized ( writer )
104 {
105 try
106 {
107 // Write the LdapPrincipal
108 writer.write( "# principal: " );
109 writer.write( principal.getName() );
110 writer.write( '\n' );
111
112 // Write the timestamp
113 writer.write( "# timestamp: " );
114 writer.write( Long.toString( System.currentTimeMillis() ) );
115 writer.write( '\n' );
116
117 // Write the revision
118 writer.write( "# revision: " );
119 writer.write( Long.toString( revision ) );
120 writer.write( "\n" );
121
122 // Write the entry
123 writer.write( LdifUtils.convertToLdif( forward, 80 ) );
124 writer.flush();
125 }
126 catch ( LdapException ne )
127 {
128 return false;
129 }
130 catch ( IOException ioe )
131 {
132 return false;
133 }
134 }
135
136 return true;
137 }
138
139
140 /**
141 * Records a ack for a change
142 *
143 * @param revision The change revision which is acked
144 * @return <code>true</code> if the ack has been written
145 * @throws Exception if there are problems logging the ack
146 */
147 public boolean ack( long revision )
148 {
149 synchronized ( writer )
150 {
151 try
152 {
153 // Write the revision
154 writer.write( "# ack-revision: " );
155 writer.write( Long.toString( revision ) );
156 writer.write( "\n\n" );
157
158 writer.flush();
159 }
160 catch ( IOException ioe )
161 {
162 return false;
163 }
164 }
165
166 return true;
167 }
168
169
170 /**
171 * Records a nack for a change
172 *
173 * @param revision The change revision which is nacked
174 * @return <code>true</code> if the nack has been written
175 * @throws Exception if there are problems logging the nack
176 */
177 public boolean nack( long revision )
178 {
179 synchronized ( writer )
180 {
181 try
182 {
183 // Write the revision
184 writer.write( "# nack-revision: " );
185 writer.write( Long.toString( revision ) );
186 writer.write( "\n\n" );
187
188 writer.flush();
189 }
190 catch ( IOException ioe )
191 {
192 return false;
193 }
194 }
195
196 return true;
197 }
198
199
200 public void sync() throws Exception
201 {
202 // TODO Auto-generated method stub
203
204 }
205
206 public long getCurrentRevision()
207 {
208 // TODO Auto-generated method stub
209 return 0;
210 }
211
212
213 /**
214 * @return the fileName
215 */
216 public String getFileName()
217 {
218 return fileName;
219 }
220
221
222 /**
223 * @param fileName the fileName to set
224 */
225 public void setFileName( String fileName )
226 {
227 this.fileName = fileName;
228 }
229
230
231 /**
232 * {@inheritDoc}
233 */
234 public void setWorkingDirectory( String workingDirectoryName )
235 {
236 this.workingDirectory = new File( workingDirectoryName );
237 }
238 }