]> source.dussan.org Git - archiva.git/blob
655b682b002688636cf670312777cd4c79dcddde
[archiva.git] /
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.codehaus.plexus.util.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  * @version $Id$
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 Object saveObject( Object object )
153     {
154         return saveObject( object, null );
155     }
156
157     public Object saveObject( Object 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 = 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             StringBuffer filter = new StringBuffer();
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 Object getObjectById( Class<?> 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 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 Object removeObject( Object 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 = 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 }