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.api.partition; 021 022 023import java.io.IOException; 024import java.io.OutputStream; 025 026import javax.naming.InvalidNameException; 027 028import org.apache.directory.api.ldap.model.entry.Entry; 029import org.apache.directory.api.ldap.model.exception.LdapException; 030import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException; 031import org.apache.directory.api.ldap.model.exception.LdapOtherException; 032import org.apache.directory.api.ldap.model.name.Dn; 033import org.apache.directory.api.ldap.model.schema.SchemaManager; 034import org.apache.directory.api.util.Strings; 035import org.apache.directory.server.core.api.DnFactory; 036import org.apache.directory.server.i18n.I18n; 037 038 039/** 040 * A {@link Partition} that helps users to implement their own partition. 041 * Most methods are implemented by default. Please look at the description of 042 * each methods for the detail of implementations. 043 * 044 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 045 */ 046public abstract class AbstractPartition implements Partition 047{ 048 /** <tt>true</tt> if and only if this partition is initialized. */ 049 protected boolean initialized; 050 051 /** The partition ContextEntry */ 052 protected Entry contextEntry; 053 054 /** The SchemaManager instance */ 055 protected SchemaManager schemaManager; 056 057 /** The DnFactory to use to create DN */ 058 protected DnFactory dnFactory; 059 060 /** The partition ID */ 061 protected String id; 062 063 /** The root Dn for this partition */ 064 protected Dn suffixDn; 065 066 /** the value of last successful add/update operation's CSN */ 067 private String contextCsn; 068 069 /** a flag to detect the change in context CSN */ 070 protected volatile boolean ctxCsnChanged = false; 071 072 /** 073 * {@inheritDoc} 074 */ 075 @Override 076 public void initialize() throws LdapException 077 { 078 if ( initialized ) 079 { 080 // Already initialized. 081 return; 082 } 083 084 try 085 { 086 doInit(); 087 initialized = true; 088 } 089 catch ( Exception e ) 090 { 091 throw new LdapOtherException( e.getMessage(), e ); 092 } 093 finally 094 { 095 if ( !initialized ) 096 { 097 try 098 { 099 destroy( null ); 100 } 101 catch ( Exception e ) 102 { 103 throw new LdapOtherException( e.getMessage(), e ); 104 } 105 } 106 } 107 } 108 109 110 /** 111 * {@inheritDoc} 112 */ 113 @Override 114 public void repair() throws LdapException 115 { 116 // Do nothing. It will be handled by the implementation classes 117 } 118 119 120 /** 121 * Override this method to put your initialization code. 122 * 123 * @param partitionTxn The transaction to use 124 * @throws LdapException If the destroy call failed 125 */ 126 protected abstract void doDestroy( PartitionTxn partitionTxn ) throws LdapException; 127 128 129 /** 130 * Override this method to put your initialization code. 131 * 132 * @throws LdapException If the initialization failed 133 * @throws InvalidNameException If the initialization failed 134 */ 135 protected abstract void doInit() throws InvalidNameException, LdapException; 136 137 138 /** 139 * Override this method to implement a repair method 140 * 141 * @throws LdapException If the repair failed 142 */ 143 protected abstract void doRepair() throws LdapException; 144 145 146 /** 147 * Calls <code>doDestroy()</code> where you have to put your destroy code in, 148 * and clears default properties. Once this method is invoked, <code>isInitialized()</code> 149 * will return <tt>false</tt>. 150 */ 151 @Override 152 public final void destroy( PartitionTxn partitionTxn ) throws LdapException 153 { 154 try 155 { 156 doDestroy( partitionTxn ); 157 } 158 finally 159 { 160 initialized = false; 161 } 162 } 163 164 165 /** 166 * {@inheritDoc} 167 */ 168 @Override 169 public final boolean isInitialized() 170 { 171 return initialized; 172 } 173 174 175 /** 176 * {@inheritDoc} 177 */ 178 @Override 179 public void setSchemaManager( SchemaManager schemaManager ) 180 { 181 this.schemaManager = schemaManager; 182 } 183 184 185 /** 186 * {@inheritDoc} 187 */ 188 @Override 189 public final SchemaManager getSchemaManager() 190 { 191 return schemaManager; 192 } 193 194 195 /** 196 * {@inheritDoc} 197 */ 198 @Override 199 public final String getId() 200 { 201 return id; 202 } 203 204 205 /** 206 * {@inheritDoc} 207 */ 208 @Override 209 public void setId( String id ) 210 { 211 checkInitialized( "id" ); 212 this.id = id; 213 } 214 215 216 /** 217 * {@inheritDoc} 218 */ 219 @Override 220 public final Dn getSuffixDn() 221 { 222 return suffixDn; 223 } 224 225 226 /** 227 * {@inheritDoc} 228 */ 229 @Override 230 public void setSuffixDn( Dn suffixDn ) throws LdapInvalidDnException 231 { 232 checkInitialized( "suffixDn" ); 233 234 if ( suffixDn.isSchemaAware() ) 235 { 236 this.suffixDn = suffixDn; 237 } 238 else 239 { 240 this.suffixDn = new Dn( schemaManager, suffixDn ); 241 } 242 } 243 244 245 /** 246 * {@inheritDoc} 247 */ 248 @Override 249 public void dumpIndex( PartitionTxn partitionTxn, OutputStream stream, String name ) throws IOException 250 { 251 stream.write( Strings.getBytesUtf8( "Nothing to dump for index " + name ) ); 252 } 253 254 255 /** 256 * Check that the operation is done on an initialized store 257 * 258 * @param property The property that was initialized 259 */ 260 protected void checkInitialized( String property ) 261 { 262 if ( initialized ) 263 { 264 throw new IllegalStateException( I18n.err( I18n.ERR_576, property ) ); 265 } 266 } 267 268 269 /** 270 * @return the contextEntry 271 */ 272 public Entry getContextEntry() 273 { 274 return contextEntry; 275 } 276 277 278 /** 279 * @param contextEntry the contextEntry to set 280 */ 281 public void setContextEntry( Entry contextEntry ) 282 { 283 this.contextEntry = contextEntry; 284 } 285 286 287 /** 288 * {@inheritDoc} 289 */ 290 @Override 291 public String getContextCsn( PartitionTxn partitionTxn ) 292 { 293 return contextCsn; 294 } 295 296 297 /** 298 * Replaces the current context CSN with the given CSN value if they are not same and 299 * sets the ctxCsnChanged flag to true. 300 * 301 * @param csn the CSN value 302 */ 303 protected void setContextCsn( String csn ) 304 { 305 if ( !csn.equals( contextCsn ) ) 306 { 307 contextCsn = csn; 308 ctxCsnChanged = true; 309 } 310 } 311 312 313 /** 314 * {@inheritDoc} 315 */ 316 @Override 317 public void sync() throws LdapException 318 { 319 // Do nothing by default 320 } 321}