View Javadoc

1   /*
2    *   Copyright 2004 The Apache Software Foundation
3    *
4    *   Licensed under the Apache License, Version 2.0 (the "License");
5    *   you may not use this file except in compliance with the License.
6    *   You may obtain a copy of the License at
7    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *   Unless required by applicable law or agreed to in writing, software
11   *   distributed under the License is distributed on an "AS IS" BASIS,
12   *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *   See the License for the specific language governing permissions and
14   *   limitations under the License.
15   *
16   */
17  package org.apache.ldap.server.partition;
18  
19  import java.util.ArrayList;
20  import java.util.List;
21  
22  import javax.naming.Name;
23  import javax.naming.NameNotFoundException;
24  import javax.naming.NamingEnumeration;
25  import javax.naming.NamingException;
26  import javax.naming.OperationNotSupportedException;
27  import javax.naming.directory.Attribute;
28  import javax.naming.directory.Attributes;
29  import javax.naming.directory.ModificationItem;
30  
31  import org.apache.ldap.common.name.LdapName;
32  import org.apache.ldap.server.configuration.ContextPartitionConfiguration;
33  import org.apache.ldap.server.jndi.ContextFactoryConfiguration;
34  
35  /***
36   * A {@link ContextPartition} that helps users to implement their own partition.
37   * Most methods are implemented by default.  Please look at the description of
38   * each methods for the detail of implementations.
39   *
40   * @author The Apache Directory Project
41   * @version $Rev: 264732 $, $Date: 2005-08-30 04:04:51 -0400 (Tue, 30 Aug 2005) $
42   */
43  public abstract class AbstractContextPartition implements ContextPartition
44  {
45      /*** {@link ContextFactoryConfiguration} specified at {@link #init(ContextFactoryConfiguration, ContextPartitionConfiguration)}. */
46      private ContextFactoryConfiguration factoryCfg;
47      /*** {@link ContextPartitionConfiguration} specified at {@link #init(ContextFactoryConfiguration, ContextPartitionConfiguration)}. */
48      private ContextPartitionConfiguration cfg;
49      /*** <tt>true</tt> if and only if this partition is initialized. */
50      private boolean initialized;
51      
52      protected AbstractContextPartition()
53      {
54      }
55  
56      /***
57       * Sets up default properties(<tt>factoryConfiguration</tt> and <tt>configuration</tt>) and
58       * calls {@link #doInit()} where you have to put your initialization code in.
59       * {@link #isInitialized()} will return <tt>true</tt> if {@link #doInit()} returns
60       * without any errors.  {@link #destroy()} is called automatically as a clean-up process
61       * if {@link #doInit()} throws an exception.
62       */
63      public final void init( ContextFactoryConfiguration factoryCfg, ContextPartitionConfiguration cfg ) throws NamingException
64      {
65          if( initialized )
66          {
67              // Already initialized.
68              return;
69          }
70  
71          this.factoryCfg = factoryCfg;
72          this.cfg = cfg;
73          try{
74              doInit();
75              initialized = true;
76          }
77          finally
78          {
79              if( !initialized )
80              {
81                  destroy();
82              }
83          }
84      }
85  
86      /***
87       * Override this method to put your initialization code.
88       */
89      protected void doInit() throws NamingException
90      {
91      }
92      
93      /***
94       * Calls {@link #doDestroy()} where you have to put your destroy code in,
95       * and clears default properties.  Once this method is invoked, {@link #isInitialized()}
96       * will return <tt>false</tt>.
97       */
98      public final void destroy()
99      {
100         if( cfg == null )
101         {
102             // Already destroyed.
103             return;
104         }
105 
106         try
107         {
108             doDestroy();
109         }
110         finally
111         {
112             initialized = false;
113             factoryCfg = null;
114             cfg = null;
115         }
116     }
117 
118     /***
119      * Override this method to put your initialization code.
120      */
121     protected void doDestroy()
122     {
123     }
124 
125     /***
126      * Returns <tt>true</tt> if this context partition is initialized successfully.
127      */
128     public final boolean isInitialized()
129     {
130         return initialized;
131     }
132 
133     /***
134      * Returns {@link ContextFactoryConfiguration} that is provided from
135      * {@link #init(ContextFactoryConfiguration, ContextPartitionConfiguration)}.
136      */
137     public final ContextFactoryConfiguration getFactoryConfiguration()
138     {
139         return factoryCfg;
140     }
141     
142     /***
143      * Returns {@link ContextPartitionConfiguration} that is provided from
144      * {@link #init(ContextFactoryConfiguration, ContextPartitionConfiguration)}.
145      */
146     public final ContextPartitionConfiguration getConfiguration()
147     {
148         return cfg;
149     }
150 
151     public final Name getSuffix( boolean normalized ) throws NamingException
152     {
153         if( normalized )
154         {
155             return getConfiguration().getNormalizedSuffix(
156                     getFactoryConfiguration().getGlobalRegistries().getMatchingRuleRegistry() );
157         }
158         else
159         {
160             return new LdapName( getConfiguration().getSuffix() );
161         }
162     }
163 
164     public final boolean isSuffix( Name name ) throws NamingException
165     {
166         return getSuffix( true ).equals( name ) || getSuffix( false ).equals( name );
167     }
168 
169     /***
170      * This method does nothing by default.
171      */
172     public void sync() throws NamingException
173     {
174     }
175     
176     /***
177      * This method calls {@link #lookup(Name)} and return <tt>true</tt>
178      * if it returns an entry by default.  Please override this method if
179      * there is more effective way for your implementation.
180      */
181     public boolean hasEntry( Name name ) throws NamingException
182     {
183         try
184         {
185             return lookup( name ) != null;
186         }
187         catch( NameNotFoundException e )
188         {
189             return false;
190         }
191     }
192 
193     /***
194      * This method calls {@link ContextPartition#lookup(Name, String[])}
195      * with null <tt>attributeIds</tt> by default.  Please override
196      * this method if there is more effective way for your implementation.
197      */
198     public Attributes lookup( Name name ) throws NamingException
199     {
200         return lookup( name, null );
201     }
202 
203     /***
204      * This method forwards the request to
205      * {@link ContextPartition#modify(Name, ModificationItem[])} after
206      * translating parameters to {@link ModificationItem}<tt>[]</tt> by default.
207      * Please override this method if there is more effactive way for your
208      * implementation.
209      */
210     public void modify( Name name, int modOp, Attributes mods ) throws NamingException
211     {
212         List items = new ArrayList( mods.size() );
213         NamingEnumeration e = mods.getAll();
214         while( e.hasMore() )
215         {
216             items.add( new ModificationItem( modOp, ( Attribute ) e.next() ) );
217         }
218         
219         ModificationItem[] itemsArray = new ModificationItem[ items.size() ];
220         itemsArray = ( ModificationItem[] ) items.toArray( itemsArray );
221         modify( name, itemsArray );
222     }
223 
224     /***
225      * This method calls {@link ContextPartition#move(Name, Name)} and
226      * {@link ContextPartition#modifyRn(Name, String, boolean)} subsequently
227      * by default.  Please override this method if there is more effactive
228      * way for your implementation.
229      */
230     public void move( Name oldName, Name newParentName, String newRn, boolean deleteOldRn ) throws NamingException
231     {
232         Name newName = ( Name ) newParentName.clone();
233         newName.add( newRn );
234         move( oldName, newParentName );
235         modifyRn( newName, newRn, deleteOldRn );
236     }
237 
238     /***
239      * This method throws {@link OperationNotSupportedException} by default.
240      * Please override this method to implement move operation.
241      */
242     public void move( Name oldName, Name newParentName ) throws NamingException
243     {
244         throw new OperationNotSupportedException( "Moving an entry to other parent entry is not supported." );
245     }
246 }