This project has retired. For details please refer to its Attic page.
JdoTool xref
View Javadoc

1   package org.apache.archiva.redback.rbac.jdo;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   * http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.archiva.redback.rbac.Permission;
23  import org.apache.archiva.redback.rbac.RBACManagerListener;
24  import org.apache.archiva.redback.rbac.RbacManagerException;
25  import org.apache.archiva.redback.rbac.RbacObjectNotFoundException;
26  import org.apache.archiva.redback.rbac.Role;
27  import org.apache.archiva.redback.components.jdo.JdoFactory;
28  import org.apache.commons.lang.StringUtils;
29  import org.springframework.stereotype.Service;
30  
31  import javax.annotation.PostConstruct;
32  import javax.annotation.Resource;
33  import javax.jdo.Extent;
34  import javax.jdo.JDOException;
35  import javax.jdo.JDOHelper;
36  import javax.jdo.JDOObjectNotFoundException;
37  import javax.jdo.JDOUserException;
38  import javax.jdo.PersistenceManager;
39  import javax.jdo.PersistenceManagerFactory;
40  import javax.jdo.Query;
41  import javax.jdo.Transaction;
42  import javax.jdo.datastore.DataStoreCache;
43  import javax.jdo.listener.DeleteLifecycleListener;
44  import javax.jdo.listener.InstanceLifecycleEvent;
45  import javax.jdo.listener.StoreLifecycleListener;
46  import javax.jdo.spi.Detachable;
47  import javax.jdo.spi.PersistenceCapable;
48  import java.io.PrintStream;
49  import java.util.Collection;
50  import java.util.Iterator;
51  import java.util.List;
52  
53  /**
54   * JdoTool - RBAC JDO Tools.
55   *
56   * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
57   *
58   */
59  @Service("jdoTool")
60  public class JdoTool
61      implements DeleteLifecycleListener, StoreLifecycleListener
62  {
63  
64      @Resource(name="jdoFactory#users")
65      private JdoFactory jdoFactory;
66  
67      private PersistenceManagerFactory pmf;
68  
69      private RBACManagerListener listener;
70  
71      @PostConstruct
72      public void initialize()
73      {
74          pmf = jdoFactory.getPersistenceManagerFactory();
75  
76          pmf.addInstanceLifecycleListener( this, null );
77      }
78  
79      public static void dumpObjectState( PrintStream out, Object o )
80      {
81          final String STATE = "[STATE] ";
82          final String INDENT = "        ";
83  
84          if ( o == null )
85          {
86              out.println( STATE + "Object is null." );
87              return;
88          }
89  
90          out.println( STATE + "Object " + o.getClass().getName() );
91  
92          if ( !( o instanceof PersistenceCapable ) )
93          {
94              out.println( INDENT + "is NOT PersistenceCapable (not a jdo object?)" );
95              return;
96          }
97  
98          out.println( INDENT + "is PersistenceCapable." );
99          if ( o instanceof Detachable )
100         {
101             out.println( INDENT + "is Detachable" );
102         }
103 
104         out.println( INDENT + "is new : " + Boolean.toString( JDOHelper.isNew( o ) ) );
105         out.println( INDENT + "is transactional : " + Boolean.toString( JDOHelper.isTransactional( o ) ) );
106         out.println( INDENT + "is deleted : " + Boolean.toString( JDOHelper.isDeleted( o ) ) );
107         out.println( INDENT + "is detached : " + Boolean.toString( JDOHelper.isDetached( o ) ) );
108         out.println( INDENT + "is dirty : " + Boolean.toString( JDOHelper.isDirty( o ) ) );
109         out.println( INDENT + "is persistent : " + Boolean.toString( JDOHelper.isPersistent( o ) ) );
110 
111         out.println( INDENT + "object id : " + JDOHelper.getObjectId( o ) );
112     }
113 
114     public PersistenceManager getPersistenceManager()
115     {
116         PersistenceManager pm = pmf.getPersistenceManager();
117 
118         pm.getFetchPlan().setMaxFetchDepth( -1 );
119 
120         triggerInit();
121 
122         return pm;
123     }
124 
125     private boolean hasTriggeredInit = false;
126 
127     @SuppressWarnings("unchecked")
128     public void triggerInit()
129     {
130         if ( !hasTriggeredInit )
131         {
132             hasTriggeredInit = true;
133 
134             List<Role> roles = (List<Role>) getAllObjects( JdoRole.class );
135 
136             listener.rbacInit( roles.isEmpty() );
137         }
138     }
139 
140     public void enableCache( Class<?> clazz )
141     {
142         DataStoreCache cache = pmf.getDataStoreCache();
143         if ( cache.getClass().getName().equals( "org.jpox.cache.EhcacheClassBasedLevel2Cache" )
144             || cache.getClass().getName().equals( "org.jpox.cache.EhcacheLevel2Cache" ) )
145         {
146             /* Ehcache adapters don't support pinAll, the caching is handled in the configuration */
147             return;
148         }
149         cache.pinAll( clazz, false ); // Pin all objects of type clazz from now on
150     }
151 
152     public <T>T saveObject( T object )
153     {
154         return (T) saveObject( object, null );
155     }
156 
157     public <T>T saveObject( T object, String[] fetchGroups )
158     {
159         PersistenceManager pm = getPersistenceManager();
160         Transaction tx = pm.currentTransaction();
161 
162         try
163         {
164             tx.begin();
165 
166             if ( ( JDOHelper.getObjectId( object ) != null ) && !JDOHelper.isDetached( object ) )
167             {
168                 // This is a fatal error that means we need to fix our code.
169                 // Leave it as a JDOUserException, it's intentional.
170                 throw new JDOUserException( "Existing object is not detached: " + object, object );
171             }
172 
173             if ( fetchGroups != null )
174             {
175                 for ( int i = 0; i >= fetchGroups.length; i++ )
176                 {
177                     pm.getFetchPlan().addGroup( fetchGroups[i] );
178                 }
179             }
180 
181             pm.makePersistent( object );
182 
183             object = (T) pm.detachCopy( object );
184 
185             tx.commit();
186 
187             return object;
188         }
189         finally
190         {
191             rollbackIfActive( tx );
192         }
193     }
194 
195     public List<?> getAllObjects( Class<?> clazz )
196     {
197         return getAllObjects( clazz, null, null );
198     }
199 
200     public List<?> getAllObjects( Class<?> clazz, String ordering )
201     {
202         return getAllObjects( clazz, ordering, null );
203     }
204 
205     public List<?> getAllObjects( Class<?> clazz, String ordering, String fetchGroup )
206     {
207         PersistenceManager pm = getPersistenceManager();
208         Transaction tx = pm.currentTransaction();
209 
210         try
211         {
212             tx.begin();
213 
214             Extent extent = pm.getExtent( clazz, true );
215 
216             Query query = pm.newQuery( extent );
217 
218             if ( ordering != null )
219             {
220                 query.setOrdering( ordering );
221             }
222 
223             if ( fetchGroup != null )
224             {
225                 pm.getFetchPlan().addGroup( fetchGroup );
226             }
227 
228             List<?> result = (List<?>) query.execute();
229 
230             result = (List<?>) pm.detachCopyAll( result );
231 
232             tx.commit();
233 
234             return result;
235         }
236         finally
237         {
238             rollbackIfActive( tx );
239         }
240     }
241 
242     public List<?> getUserAssignmentsForRoles( Class<?> clazz, String ordering, Collection<String> roleNames )
243     {
244         PersistenceManager pm = getPersistenceManager();
245         Transaction tx = pm.currentTransaction();
246 
247         try
248         {
249             tx.begin();
250 
251             Extent extent = pm.getExtent( clazz, true );
252 
253             Query query = pm.newQuery( extent );
254 
255             if ( ordering != null )
256             {
257                 query.setOrdering( ordering );
258             }
259 
260             query.declareImports( "import java.lang.String" );
261 
262             StringBuilder filter = new StringBuilder();
263 
264             if ( roleNames.size() > 0 )
265             {
266                 Iterator<String> i = roleNames.iterator();
267 
268                 filter.append( "this.roleNames.contains(\"" ).append( i.next() ).append( "\")" );
269 
270                 while ( i.hasNext() )
271                 {
272                     filter.append( " || this.roleNames.contains(\"" ).append( i.next() ).append( "\")" );
273                 }
274 
275                 query.setFilter( filter.toString() );
276             }
277 
278             List<?> result = (List<?>) query.execute();
279 
280             result = (List<?>) pm.detachCopyAll( result );
281 
282             tx.commit();
283 
284             return result;
285         }
286         finally
287         {
288             rollbackIfActive( tx );
289         }
290     }
291 
292     public <T>T getObjectById( Class<T> clazz, String id, String fetchGroup )
293         throws RbacObjectNotFoundException, RbacManagerException
294     {
295         if ( StringUtils.isEmpty( id ) )
296         {
297             throw new RbacObjectNotFoundException(
298                 "Unable to get object '" + clazz.getName() + "' from jdo using null/empty id." );
299         }
300 
301         PersistenceManager pm = getPersistenceManager();
302         Transaction tx = pm.currentTransaction();
303 
304         try
305         {
306             tx.begin();
307 
308             if ( fetchGroup != null )
309             {
310                 pm.getFetchPlan().addGroup( fetchGroup );
311             }
312 
313             Object objectId = pm.newObjectIdInstance( clazz, id );
314 
315             Object object = pm.getObjectById( objectId );
316 
317             object = pm.detachCopy( object );
318 
319             tx.commit();
320 
321             return (T) object;
322         }
323         catch ( JDOObjectNotFoundException e )
324         {
325             throw new RbacObjectNotFoundException( "Unable to find RBAC Object '" + id + "' of type " +
326                 clazz.getName() + " using fetch-group '" + fetchGroup + "'", e, id );
327         }
328         catch ( JDOException e )
329         {
330             throw new RbacManagerException( "Error in JDO during get of RBAC object id '" + id + "' of type " +
331                 clazz.getName() + " using fetch-group '" + fetchGroup + "'", e );
332         }
333         finally
334         {
335             rollbackIfActive( tx );
336         }
337     }
338 
339     public boolean objectExists( Object object )
340     {
341         return ( JDOHelper.getObjectId( object ) != null );
342     }
343 
344     public boolean objectExistsById( Class<?> clazz, String id )
345         throws RbacManagerException
346     {
347         try
348         {
349             Object o = getObjectById( clazz, id, null );
350             return ( o != null );
351         }
352         catch ( RbacObjectNotFoundException e )
353         {
354             return false;
355         }
356     }
357 
358     public <T>T removeObject( T o )
359         throws RbacManagerException
360     {
361         if ( o == null )
362         {
363             throw new RbacManagerException( "Unable to remove null object" );
364         }
365 
366         PersistenceManager pm = getPersistenceManager();
367         Transaction tx = pm.currentTransaction();
368 
369         try
370         {
371             tx.begin();
372 
373             o = (T) pm.getObjectById( pm.getObjectId( o ) );
374 
375             pm.deletePersistent( o );
376 
377             tx.commit();
378 
379             return o;
380         }
381         finally
382         {
383             rollbackIfActive( tx );
384         }
385     }
386 
387     public void rollbackIfActive( Transaction tx )
388     {
389         PersistenceManager pm = tx.getPersistenceManager();
390 
391         try
392         {
393             if ( tx.isActive() )
394             {
395                 tx.rollback();
396             }
397         }
398         finally
399         {
400             closePersistenceManager( pm );
401         }
402     }
403 
404     public void closePersistenceManager( PersistenceManager pm )
405     {
406         try
407         {
408             pm.close();
409         }
410         catch ( JDOUserException e )
411         {
412             // ignore
413         }
414     }
415 
416     public RBACManagerListener getListener()
417     {
418         return listener;
419     }
420 
421     public void setListener( RBACManagerListener listener )
422     {
423         this.listener = listener;
424     }
425 
426     public void postDelete( InstanceLifecycleEvent evt )
427     {
428         PersistenceCapable obj = ( (PersistenceCapable) evt.getSource() );
429 
430         if ( obj == null )
431         {
432             // Do not track null objects.
433             // These events are typically a product of an internal lifecycle event.
434             return;
435         }
436 
437         if ( obj instanceof Role )
438         {
439             listener.rbacRoleRemoved( (Role) obj );
440         }
441         else if ( obj instanceof Permission )
442         {
443             listener.rbacPermissionRemoved( (Permission) obj );
444         }
445     }
446 
447     public void preDelete( InstanceLifecycleEvent evt )
448     {
449         // ignore
450     }
451 
452     public void postStore( InstanceLifecycleEvent evt )
453     {
454         PersistenceCapable obj = ( (PersistenceCapable) evt.getSource() );
455 
456         if ( obj instanceof Role )
457         {
458             listener.rbacRoleSaved( (Role) obj );
459         }
460         else if ( obj instanceof Permission )
461         {
462             listener.rbacPermissionSaved( (Permission) obj );
463         }
464     }
465 
466     public void preStore( InstanceLifecycleEvent evt )
467     {
468         // ignore
469     }
470 
471     public void removeAll( Class<?> aClass )
472     {
473         PersistenceManager pm = getPersistenceManager();
474         Transaction tx = pm.currentTransaction();
475 
476         try
477         {
478             tx.begin();
479 
480             Query query = pm.newQuery( aClass );
481             query.deletePersistentAll();
482 
483             tx.commit();
484         }
485         finally
486         {
487             rollbackIfActive( tx );
488         }
489     }
490 
491     public JdoFactory getJdoFactory()
492     {
493         return jdoFactory;
494     }
495 
496     public void setJdoFactory( JdoFactory jdoFactory )
497     {
498         this.jdoFactory = jdoFactory;
499     }
500 }