View Javadoc

1   /*
2    * Copyright 2000-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.jetspeed.om.registry.base;
18  
19  import org.apache.jetspeed.om.registry.RegistryEntry;
20  import org.apache.jetspeed.om.registry.InvalidEntryException;
21  import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
22  import org.apache.jetspeed.services.logging.JetspeedLogger;
23  
24  
25  import java.util.Map;
26  import java.util.TreeMap;
27  import java.util.List;
28  import java.util.Iterator;
29  import java.util.Enumeration;
30  import java.util.Vector;
31  
32  /***
33   * Provides a basic registry implementation that keep the elements
34   * ordered.
35   *
36   * @author <a href="mailto:raphael@apache.org">Raphaël Luta</a>
37   * @version $Id: BaseOrderedRegistry.java,v 1.4 2004/02/23 03:08:26 jford Exp $
38   */
39  public class BaseOrderedRegistry implements LocalRegistry
40  {
41      protected List entries = new Vector();
42  
43      protected Map idx = null;
44  
45      /***
46       * Static initialization of the logger for this class
47       */    
48      private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(BaseOrderedRegistry.class.getName());    
49      
50      /*** @see Registry#getEntryCount */
51      public int getEntryCount()
52      {
53          return this.entries.size();
54      }
55  
56      /*** @see Registry#getEntry */
57      public RegistryEntry getEntry( String name ) throws InvalidEntryException
58      {
59  
60          RegistryEntry entry = null;
61  
62          try
63          {
64              if (idx == null)
65              {
66                  synchronized (entries)
67                  {
68                      buildIdx();
69                  }
70              }
71  
72              if (name != null)
73              {
74                  synchronized (entries)
75                  {
76                      Integer pos = ((Integer)idx.get(name));
77  
78                      if (pos == null)
79                      {
80                          throw new InvalidEntryException( InvalidEntryException.ENTRY_DOES_NOT_EXIST+" "+name );
81                      }
82  
83                      entry = (RegistryEntry)entries.get(pos.intValue()) ;
84                  }
85              }
86          }
87          catch(Exception e)
88          {
89              // this will happen if for some reasons the index and vector are desynchronized.
90              // before throwing an exception, rebuild the idx to prevent further errors
91              synchronized(entries)
92              {
93                  buildIdx();
94              }
95  
96              logger.error("getEntry: index and vector are not in synch.", e);
97              throw new InvalidEntryException( InvalidEntryException.ENTRY_DOES_NOT_EXIST+" "+name );
98          }
99  
100         return entry;
101     }
102 
103     /***
104     @see Registry#setEntry
105     */
106     public void setEntry( RegistryEntry entry ) throws InvalidEntryException
107     {
108         setLocalEntry( entry );
109     }
110 
111     /***
112     @see Registry#addEntry
113     */
114     public void addEntry( RegistryEntry entry ) throws InvalidEntryException
115     {
116         addLocalEntry( entry );
117     }
118 
119     /***
120     @see Registry#removeEntry
121     */
122     public void removeEntry( String name )
123     {
124         removeLocalEntry( name );
125     }
126 
127     /***
128     @see Registry#removeEntry
129     */
130 
131     public void removeEntry( RegistryEntry entry )
132     {
133         removeLocalEntry( entry );
134     }
135 
136     /***
137        @see Registry#hasEntry
138     */
139     public boolean hasEntry( String name )
140     {
141         synchronized (entries)
142         {
143             if (idx == null)
144             {
145                 buildIdx();
146             }
147         }
148 
149         return this.idx.containsKey( name );
150     }
151 
152     /***
153        @see Registry#getEntries
154      */
155     public Enumeration getEntries()
156     {
157         Vector v = new Vector(entries);
158 
159         return v.elements();
160     }
161 
162     /***
163        @see Registry#listEntryNames
164      */
165     public Iterator listEntryNames()
166     {
167         synchronized (entries)
168         {
169             if (idx == null)
170             {
171                 buildIdx();
172             }
173         }
174 
175         return this.idx.keySet().iterator();
176     }
177 
178     /***
179        @see Registry#toArray
180      */
181     public RegistryEntry[] toArray()
182     {
183         RegistryEntry[] array = new RegistryEntry[ entries.size() ];
184 
185         return (RegistryEntry[])entries.toArray(array);
186 
187     }
188 
189     /***
190      * Creates a new RegistryEntry instance compatible with the current
191      * Registry instance implementation
192      *
193      * @return the newly created RegistryEntry
194      */
195     public RegistryEntry createEntry()
196     {
197         return new BaseRegistryEntry();
198     }
199 
200 
201     // RegistryService specific methods
202 
203     /***
204      * This method is used  to only set the entry in the local
205      * memory cache of the registry without any coherency check with
206      * persistent storage
207      *
208      * @param entry the RegistryEntry to store
209      */
210     public void setLocalEntry( RegistryEntry entry ) throws InvalidEntryException
211     {
212         synchronized (entries)
213         {
214             if (idx == null)
215             {
216                 buildIdx();
217             }
218 
219             if ( this.idx.containsKey( entry.getName() ) == false )
220             {
221                 throw new InvalidEntryException( InvalidEntryException.ENTRY_DOES_NOT_EXIST+" "+entry.getName());
222             }
223 
224             int pos = ((Integer)idx.get(entry.getName())).intValue();
225 
226             this.entries.set( pos, entry );
227         }
228     }
229 
230     /***
231      * This method is used to only add the entry in the local
232      * memory cache of the registry without any coherency check with
233      * persistent storage
234      *
235      * @param entry the RegistryEntry to store
236      */
237     public void addLocalEntry( RegistryEntry entry ) throws InvalidEntryException
238     {
239         synchronized (entries)
240         {
241             if (idx == null)
242             {
243                 buildIdx();
244             }
245 
246             if ( this.idx.containsKey( entry.getName() ) )
247             {
248                 throw new InvalidEntryException( InvalidEntryException.ENTRY_ALREADY_PRESENT );
249             }
250 
251             int pos = this.entries.size();
252             this.entries.add( entry );
253             this.idx.put( entry.getName(), new Integer(pos) );
254         }
255     }
256 
257     /***
258      * This method is used to only remove the entry from the local
259      * memory cache of the registry without any coherency check with
260      * persistent storage
261      *
262      * @param name the name of the RegistryEntry to remove
263      */
264     public void removeLocalEntry( String name )
265     {
266         synchronized(entries)
267         {
268             if (idx == null)
269             {
270                 buildIdx();
271             }
272 
273             if (this.idx.containsKey(name))
274             {
275                 int pos = ((Integer)idx.get(name)).intValue();
276                 this.entries.remove( pos );
277                 buildIdx();
278             }
279         }
280     }
281 
282     /***
283      * This method is used to only remove the entry from the local
284      * memory cache of the registry without any coherency check with
285      * persistent storage
286      *
287      * @param entry the RegistryEntry to remove
288      */
289     public void removeLocalEntry( RegistryEntry entry )
290     {
291         synchronized(entries)
292         {
293             if (entries.remove( entry ))
294             {
295                 buildIdx();
296             }
297         }
298     }
299 
300     /***
301      * Build a lookup index of entries
302      */
303     private void buildIdx()
304     {
305         Map map = new TreeMap();
306 
307         for (int i=0; i < entries.size(); i++)
308         {
309             RegistryEntry entry = (RegistryEntry)entries.get(i);
310             map.put( entry.getName(), new Integer(i));
311         }
312 
313         this.idx = map;
314     }
315 }