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 }