source: VirtualCollectionRegistry/trunk/VirtualCollectionRegistry/src/main/java/eu/clarin/cmdi/virtualcollectionregistry/VirtualCollectionRegistryImpl.java @ 5617

Last change on this file since 5617 was 5617, checked in by Twan Goosen, 10 years ago

override annotations for registry implementation class

  • Property svn:eol-style set to native
File size: 28.4 KB
Line 
1package eu.clarin.cmdi.virtualcollectionregistry;
2
3import eu.clarin.cmdi.oai.provider.impl.OAIProvider;
4import eu.clarin.cmdi.virtualcollectionregistry.model.User;
5import eu.clarin.cmdi.virtualcollectionregistry.model.User_;
6import eu.clarin.cmdi.virtualcollectionregistry.model.VirtualCollection;
7import eu.clarin.cmdi.virtualcollectionregistry.model.VirtualCollectionList;
8import eu.clarin.cmdi.virtualcollectionregistry.pid.PersistentIdentifier;
9import eu.clarin.cmdi.virtualcollectionregistry.pid.PersistentIdentifierProvider;
10import eu.clarin.cmdi.virtualcollectionregistry.query.ParsedQuery;
11import eu.clarin.cmdi.virtualcollectionregistry.service.VirtualCollectionValidator;
12import java.security.Principal;
13import java.util.Date;
14import java.util.List;
15import java.util.concurrent.Executors;
16import java.util.concurrent.ScheduledExecutorService;
17import java.util.concurrent.ThreadFactory;
18import java.util.concurrent.TimeUnit;
19import java.util.concurrent.atomic.AtomicBoolean;
20import java.util.concurrent.atomic.AtomicInteger;
21import javax.persistence.EntityManager;
22import javax.persistence.EntityTransaction;
23import javax.persistence.LockModeType;
24import javax.persistence.NoResultException;
25import javax.persistence.TypedQuery;
26import javax.persistence.criteria.CriteriaBuilder;
27import javax.persistence.criteria.CriteriaQuery;
28import javax.persistence.criteria.Order;
29import javax.persistence.criteria.Predicate;
30import javax.persistence.criteria.Root;
31import org.slf4j.Logger;
32import org.slf4j.LoggerFactory;
33import org.springframework.beans.factory.DisposableBean;
34import org.springframework.beans.factory.InitializingBean;
35import org.springframework.beans.factory.annotation.Autowired;
36import org.springframework.beans.factory.annotation.Qualifier;
37import org.springframework.stereotype.Service;
38
39@Service
40public class VirtualCollectionRegistryImpl implements VirtualCollectionRegistry, InitializingBean, DisposableBean {
41
42    @Autowired
43    private DataStore datastore; //TODO: replace with Spring managed EM?
44    @Autowired
45    private PersistentIdentifierProvider pid_provider;
46    @Autowired
47    private OAIProvider oaiProvider;
48    @Autowired
49    @Qualifier("creation")
50    private VirtualCollectionValidator validator;
51    @Autowired
52    private AdminUsersService adminUsersService;
53
54    private static final Logger logger
55            = LoggerFactory.getLogger(VirtualCollectionRegistryImpl.class);
56    private final AtomicBoolean intialized = new AtomicBoolean(false);
57    /**
58     * Scheduled executor service for the maintenance check
59     *
60     * @see #maintenance(long)
61     */
62    private final ScheduledExecutorService maintenanceExecutor
63            = createSingleThreadScheduledExecutor("VirtualCollectionRegistry-Maintenance");
64
65    @Override
66    public void afterPropertiesSet() throws VirtualCollectionRegistryException {
67        // called by Spring directly after Bean construction
68        doInitalize();
69    }
70
71    private void doInitalize() throws VirtualCollectionRegistryException {
72        if (intialized.get()) {
73            throw new VirtualCollectionRegistryException("already initialized");
74        }
75        logger.info("Initializing virtual collection registry ...");
76        try {
77            maintenanceExecutor.scheduleWithFixedDelay(new Runnable() {
78
79                @Override
80                public void run() {
81                    maintenance(new Date().getTime());
82                }
83            }, 60, 60, TimeUnit.SECONDS);
84            this.intialized.set(true);
85            logger.info("virtual collection registry successfully intialized");
86        } catch (RuntimeException e) {
87            logger.error("error initalizing virtual collection registry", e);
88            throw e;
89        }
90    }
91
92    @Override
93    public void destroy() throws VirtualCollectionRegistryException, InterruptedException {
94        logger.info("Stopping Virtual Collection Registry maintenance schedule");
95        maintenanceExecutor.shutdown();
96        if (!maintenanceExecutor.awaitTermination(60, TimeUnit.SECONDS)) {
97            logger.warn("Timeout while waiting for maintenance thread to terminate, will try to shut down");
98        }
99
100        logger.info("Shutting down OAI provider");
101        oaiProvider.shutdown();
102    }
103
104    /**
105     * Will store the specified collection; it will also set the owner according
106     * to the specified principal and set its state to
107     * {@link VirtualCollection.State#PRIVATE}
108     *
109     * @param principal owner principal
110     * @param vc collection to store
111     * @return identifier of the persisted collection
112     * @throws VirtualCollectionRegistryException
113     */
114    @Override
115    public long createVirtualCollection(Principal principal,
116            VirtualCollection vc) throws VirtualCollectionRegistryException {
117        if (principal == null) {
118            throw new NullPointerException("principal == null");
119        }
120        if (vc == null) {
121            throw new NullPointerException("vc == null");
122        }
123
124        logger.debug("creating virtual collection");
125
126        validator.validate(vc);
127        try {
128            EntityManager em = datastore.getEntityManager();
129            em.getTransaction().begin();
130
131            // fetch user, if user does not exist create new
132            User user = fetchUser(em, principal);
133            if (user == null) {
134                user = new User(principal.getName());
135                em.persist(user);
136            }
137            vc.setOwner(user);
138
139            // force new collection to be private
140            vc.setState(VirtualCollection.State.PRIVATE);
141
142            // store virtual collection
143            logger.debug("persisting new virtual collection", vc.getId());
144            em.persist(vc);
145            em.getTransaction().commit();
146            logger.debug("virtual collection created (id={})", vc.getId());
147            return vc.getId();
148        } catch (Exception e) {
149            logger.error("error while creating virtual collection", e);
150            throw new VirtualCollectionRegistryException(
151                    "error while creating virtual collection", e);
152        }
153    }
154
155    @Override
156    public long updateVirtualCollection(Principal principal, long id,
157            VirtualCollection vc) throws VirtualCollectionRegistryException {
158        if (principal == null) {
159            throw new NullPointerException("principal == null");
160        }
161        if (id <= 0) {
162            throw new IllegalArgumentException("id <= 0");
163        }
164        if (vc == null) {
165            throw new NullPointerException("vc == null");
166        }
167
168        logger.debug("updating virtual collection (id={})", id);
169
170        validator.validate(vc);
171
172        try {
173            EntityManager em = datastore.getEntityManager();
174            em.getTransaction().begin();
175            VirtualCollection c = em.find(VirtualCollection.class,
176                    Long.valueOf(id), LockModeType.PESSIMISTIC_WRITE);
177            /*
178             * Do not check for deleted state here, as we might want to
179             * resurrect deleted virtual collections.
180             */
181            if (c == null) {
182                logger.debug("virtual collection (id={}) not found", id);
183                throw new VirtualCollectionNotFoundException(id);
184            }
185            if (!isAllowedToModify(principal, c)) {
186                throw new VirtualCollectionRegistryPermissionException(
187                        "permission denied for user \""
188                        + principal.getName() + "\"");
189            }
190
191            // update virtual collection
192            c.updateFrom(vc);
193
194            validator.validate(c);
195            em.merge(c);
196            em.getTransaction().commit();
197            logger.debug("updated virtual collection (id={})", vc.getId());
198            return c.getId();
199        } catch (VirtualCollectionRegistryException e) {
200            logger.warn("failed updating virtual collecion (id={}): {}", id,
201                    e.getMessage());
202            throw e;
203        } catch (Exception e) {
204            logger.error("error while updating virtual collection", e);
205            throw new VirtualCollectionRegistryException(
206                    "error while updating virtual collection", e);
207        }
208    }
209
210    @Override
211    public long deleteVirtualCollection(Principal principal, long id)
212            throws VirtualCollectionRegistryException {
213        if (principal == null) {
214            throw new NullPointerException("principal == null");
215        }
216        if (id <= 0) {
217            throw new IllegalArgumentException("id <= 0");
218        }
219
220        logger.debug("deleting virtual collection (id={})", id);
221
222        try {
223            EntityManager em = datastore.getEntityManager();
224            em.getTransaction().begin();
225            VirtualCollection vc = em.find(VirtualCollection.class,
226                    Long.valueOf(id), LockModeType.PESSIMISTIC_WRITE);
227            if ((vc == null) || vc.isDeleted()) {
228                logger.debug("virtual collection (id={}) not found", id);
229                throw new VirtualCollectionNotFoundException(id);
230            }
231            if (!isAllowedToModify(principal, vc)) {
232                logger.debug("virtual collection (id={}) not owned by "
233                        + "user '{}'", id, principal.getName());
234                throw new VirtualCollectionRegistryPermissionException(
235                        "permission denied for user \""
236                        + principal.getName() + "\"");
237            }
238            if (!vc.isPrivate()) {
239                logger.debug("virtual collection (id={}) cannot be "
240                        + "deleted (invalid state)", id);
241                throw new VirtualCollectionRegistryPermissionException(
242                        "virtual collection cannot be deleted");
243            }
244            vc.setState(VirtualCollection.State.DELETED);
245            em.getTransaction().commit();
246            return vc.getId();
247        } catch (VirtualCollectionRegistryException e) {
248            logger.debug("failed deleting virtual collecion (id={}): {}", id,
249                    e.getMessage());
250            throw e;
251        } catch (Exception e) {
252            logger.error("error while deleting virtual collection", e);
253            throw new VirtualCollectionRegistryException(
254                    "error while deleting virtual collection", e);
255        }
256    }
257
258    @Override
259    public VirtualCollection.State getVirtualCollectionState(long id)
260            throws VirtualCollectionRegistryException {
261        if (id <= 0) {
262            throw new IllegalArgumentException("id <= 0");
263        }
264
265        logger.debug("retrieve virtual collection state (id={})", id);
266
267        try {
268            EntityManager em = datastore.getEntityManager();
269            em.getTransaction().begin();
270            VirtualCollection vc
271                    = em.find(VirtualCollection.class, Long.valueOf(id));
272            em.getTransaction().commit();
273            if ((vc == null) || vc.isDeleted()) {
274                logger.debug("virtual collection (id={}) not found", id);
275                throw new VirtualCollectionNotFoundException(id);
276            }
277            return vc.getState();
278        } catch (VirtualCollectionRegistryException e) {
279            throw e;
280        } catch (Exception e) {
281            logger.error(
282                    "error while retrieving state of virtual collection", e);
283            throw new VirtualCollectionRegistryException(
284                    "error while retrieving state of virtual collection", e);
285        }
286    }
287
288    @Override
289    public void setVirtualCollectionState(Principal principal, long id,
290            VirtualCollection.State state)
291            throws VirtualCollectionRegistryException {
292        if (principal == null) {
293            throw new NullPointerException("principal == null");
294        }
295        if (id <= 0) {
296            throw new IllegalArgumentException("id <= 0");
297        }
298        if (state == null) {
299            throw new NullPointerException("state == null");
300        }
301        if ((state != VirtualCollection.State.PUBLIC_PENDING)
302                && (state != VirtualCollection.State.PRIVATE)) {
303            throw new IllegalArgumentException(
304                    "only PUBLIC_PENDING or PRIVATE are allowed");
305        }
306
307        logger.debug("setting state virtual collection state (id={}) to '{}'",
308                id, state);
309
310        try {
311            EntityManager em = datastore.getEntityManager();
312            em.getTransaction().begin();
313            VirtualCollection vc = em.find(VirtualCollection.class,
314                    Long.valueOf(id), LockModeType.PESSIMISTIC_WRITE);
315            if ((vc == null) || vc.isDeleted()) {
316                logger.debug("virtual collection (id={}) not found", id);
317                throw new VirtualCollectionNotFoundException(id);
318            }
319            if (!isAllowedToModify(principal, vc)) {
320                logger.debug("virtual collection (id={}) not owned by "
321                        + "user '{}'", id, principal.getName());
322                throw new VirtualCollectionRegistryPermissionException(
323                        "permission denied for user \""
324                        + principal.getName() + "\"");
325            }
326
327            /*
328             * XXX: deny update from public to private?
329             */
330            boolean update = false;
331            switch (state) {
332                case PRIVATE:
333                    update = vc.getState() != state;
334                    break;
335                case PUBLIC_PENDING:
336                    update = vc.getState() != VirtualCollection.State.PUBLIC;
337                    break;
338                default:
339                    /* silence warning; update will stay false */
340                    break;
341            }
342            if (update) {
343                vc.setState(state);
344                em.persist(vc);
345            }
346            em.getTransaction().commit();
347        } catch (VirtualCollectionRegistryException e) {
348            throw e;
349        } catch (Exception e) {
350            logger.error(
351                    "error while setting state of virtual collection", e);
352            throw new VirtualCollectionRegistryException(
353                    "error while setting state of virtual collection", e);
354        }
355    }
356
357    /**
358     *
359     * @param id identifier of the virtual collection to retrieve
360     * @return the identified virtual collection, never null
361     * @throws VirtualCollectionRegistryException if no virtual collection with
362     * the specified identifier exists
363     */
364    @Override
365    public VirtualCollection retrieveVirtualCollection(long id)
366            throws VirtualCollectionRegistryException {
367        if (id <= 0) {
368            throw new IllegalArgumentException("id <= 0");
369        }
370
371        logger.debug("retrieve virtual collection (id={})", id);
372
373        try {
374            EntityManager em = datastore.getEntityManager();
375            em.getTransaction().begin();
376            VirtualCollection vc
377                    = em.find(VirtualCollection.class, Long.valueOf(id));
378            em.getTransaction().commit();
379            if ((vc == null) || vc.isDeleted()) {
380                logger.debug("virtual collection (id={}) not found", id);
381                throw new VirtualCollectionNotFoundException(id);
382            }
383            logger.debug("virtual collection retrieved (id={})", id);
384            return vc;
385        } catch (VirtualCollectionRegistryException e) {
386            throw e;
387        } catch (Exception e) {
388            logger.error("error while retrieving virtual collection", e);
389            throw new VirtualCollectionRegistryException(
390                    "error while retrieving virtual collection", e);
391        }
392    }
393
394    @Override
395    public VirtualCollectionList getVirtualCollections(String query,
396            int offset, int count) throws VirtualCollectionRegistryException {
397        EntityManager em = datastore.getEntityManager();
398        try {
399            em.getTransaction().begin();
400
401            // setup queries
402            TypedQuery<Long> cq = null;
403            TypedQuery<VirtualCollection> q = null;
404            if (query != null) {
405                ParsedQuery parsedQuery = ParsedQuery.parseQuery(query);
406                if (logger.isDebugEnabled()) {
407                    logger.debug(parsedQuery.getPrettyPrinted());
408                }
409                cq = parsedQuery.getCountQuery(em, null, VirtualCollection.State.PUBLIC);
410                q = parsedQuery.getQuery(em, null, VirtualCollection.State.PUBLIC);
411            } else {
412                cq = em.createNamedQuery("VirtualCollection.countAllPublic",
413                        Long.class);
414                q = em.createNamedQuery("VirtualCollection.findAllPublic",
415                        VirtualCollection.class);
416            }
417
418            // commence query ...
419            List<VirtualCollection> results = null;
420            long totalCount = cq.getSingleResult();
421
422            // optimization; don't query, if we won't get any results
423            /*
424             *  FIXME: offset == -1 is temporary hack for just fetching
425             *  total count; re-factor to have fetch-count and fetch-data
426             *  methods!
427             */
428            if ((totalCount > 0) && (offset > -1)) {
429                if (offset > 0) {
430                    q.setFirstResult(offset);
431                }
432                if (count > 0) {
433                    q.setMaxResults(count);
434                }
435                results = q.getResultList();
436            }
437            return new VirtualCollectionList(results, offset, (int) totalCount);
438        } catch (Exception e) {
439            logger.error("error while enumerating virtual collections", e);
440            throw new VirtualCollectionRegistryException(
441                    "error while enumerating virtual collections", e);
442        } finally {
443            EntityTransaction tx = em.getTransaction();
444            if ((tx != null) && !tx.getRollbackOnly()) {
445                tx.commit();
446            }
447        }
448    }
449
450    @Override
451    public VirtualCollectionList getVirtualCollections(Principal principal,
452            String query, int offset, int count)
453            throws VirtualCollectionRegistryException {
454        if (principal == null) {
455            throw new NullPointerException("principal == null");
456        }
457        EntityManager em = datastore.getEntityManager();
458        try {
459            List<VirtualCollection> results = null;
460            long totalCount = 0;
461
462            em.getTransaction().begin();
463
464            /*
465             * fetch user. if user is not found, he has not yet registered any
466             * virtual collections, so just return an empty list
467             */
468            User user = fetchUser(em, principal);
469            if (user != null) {
470                // setup queries
471                TypedQuery<Long> cq = null;
472                TypedQuery<VirtualCollection> q = null;
473                if (query != null) {
474                    ParsedQuery parsedQuery = ParsedQuery.parseQuery(query);
475                    if (logger.isDebugEnabled()) {
476                        logger.debug(parsedQuery.getPrettyPrinted());
477                    }
478                    cq = parsedQuery.getCountQuery(em, user, null);
479                    q = parsedQuery.getQuery(em, user, null);
480                } else {
481                    cq = em.createNamedQuery("VirtualCollection.countByOwner",
482                            Long.class);
483                    cq.setParameter("owner", user);
484                    q = em.createNamedQuery("VirtualCollection.findByOwner",
485                            VirtualCollection.class);
486                    q.setParameter("owner", user);
487                }
488
489                // commence query ...
490                totalCount = cq.getSingleResult();
491
492                // optimization; don't query, if we won't get any results
493                /*
494                 *  FIXME: offset == -1 is temporary hack for just fetching
495                 *  total count; re-factor to have fetch-count and fetch-data
496                 *  methods!
497                 */
498                if ((totalCount > 0) && (offset > -1)) {
499                    if (offset > 0) {
500                        q.setFirstResult(offset);
501                    }
502                    if (count > 0) {
503                        q.setMaxResults(count);
504                    }
505                    results = q.getResultList();
506                }
507            }
508            return new VirtualCollectionList(results, offset, (int) totalCount);
509        } catch (Exception e) {
510            logger.error("error while enumerating virtual collections", e);
511            throw new VirtualCollectionRegistryException(
512                    "error while enumerating virtual collections", e);
513        } finally {
514            EntityTransaction tx = em.getTransaction();
515            if ((tx != null) && !tx.getRollbackOnly()) {
516                tx.commit();
517            }
518        }
519    }
520
521    @Override
522    public int getVirtualCollectionCount(QueryOptions options)
523            throws VirtualCollectionRegistryException {
524        logger.trace("Getting virtual collection count");
525        EntityManager em = datastore.getEntityManager();
526        try {
527            CriteriaBuilder cb = em.getCriteriaBuilder();
528            CriteriaQuery<Long> cq = cb.createQuery(Long.class);
529            Root<VirtualCollection> root = cq.from(VirtualCollection.class);
530            if (options != null) {
531                Predicate where = options.getWhere(cb, cq, root);
532                if (where != null) {
533                    cq.where(where);
534                }
535            }
536            em.getTransaction().begin();
537            TypedQuery<Long> query
538                    = em.createQuery(cq.select(cb.count(root)));
539            final long count = query.getSingleResult();
540            if (count >= Integer.MAX_VALUE) {
541                throw new VirtualCollectionRegistryException(
542                        "resultset too large");
543            }
544            logger.trace("Counted {} collections", count);
545            return (int) count;
546        } catch (Exception e) {
547            logger.error("error while counting virtual collections", e);
548            throw new VirtualCollectionRegistryException(
549                    "error while counting virtual collections", e);
550        } finally {
551            EntityTransaction tx = em.getTransaction();
552            if ((tx != null) && tx.isActive() && !tx.getRollbackOnly()) {
553                tx.commit();
554            }
555        }
556    }
557
558    @Override
559    public List<User> getUsers() {
560        final EntityManager em = datastore.getEntityManager();
561        try {
562            final CriteriaBuilder cb = em.getCriteriaBuilder();
563            final CriteriaQuery<User> cq = cb.createQuery(User.class);
564            final Root<User> root = cq.from(User.class);
565
566            // select all users, sort by display name then name
567            cq.select(root);
568            cq.orderBy(
569                    cb.asc(root.get(User_.displayName)),
570                    cb.asc(root.get(User_.name)));
571
572            em.getTransaction().begin();
573            final TypedQuery<User> query = em.createQuery(cq);
574            return query.getResultList();
575        } finally {
576            EntityTransaction tx = em.getTransaction();
577            if ((tx != null) && tx.isActive() && !tx.getRollbackOnly()) {
578                tx.commit();
579            }
580        }
581    }
582
583    @Override
584    public List<VirtualCollection> getVirtualCollections(
585            int first, int count, QueryOptions options)
586            throws VirtualCollectionRegistryException {
587        EntityManager em = datastore.getEntityManager();
588        try {
589            CriteriaBuilder cb = em.getCriteriaBuilder();
590            CriteriaQuery<VirtualCollection> cq
591                    = cb.createQuery(VirtualCollection.class);
592            Root<VirtualCollection> root = cq.from(VirtualCollection.class);
593            if (options != null) {
594                final Predicate where = options.getWhere(cb, cq, root);
595                if (where != null) {
596                    cq.where(where);
597                }
598                final Order[] order = options.getOrderBy(cb, root);
599                if (order != null) {
600                    cq.orderBy(order);
601                }
602            }
603            em.getTransaction().begin();
604            TypedQuery<VirtualCollection> query
605                    = em.createQuery(cq.select(root));
606            if (first > -1) {
607                query.setFirstResult(first);
608            }
609            if (count > 0) {
610                query.setMaxResults(count);
611            }
612            return query.getResultList();
613        } catch (Exception e) {
614            logger.error("error while fetching virtual collections", e);
615            throw new VirtualCollectionRegistryException(
616                    "error while fetching virtual collections", e);
617        } finally {
618            EntityTransaction tx = em.getTransaction();
619            if ((tx != null) && tx.isActive() && !tx.getRollbackOnly()) {
620                tx.commit();
621            }
622        }
623    }
624
625    private void maintenance(long now) {
626        logger.debug("Maintenance check");
627        // allocate persistent identifier roughly after 30 seconds
628        final Date nowDateAlloc = new Date(now - 30 * 1000);
629        // (for now) purge deleted collection roughly after 30 seconds
630        final Date nowDatePurge = new Date(now - 30 * 1000);
631
632        EntityManager em = datastore.getEntityManager();
633        try {
634            /*
635             * delayed allocation of persistent identifier
636             */
637            em.getTransaction().begin();
638            TypedQuery<VirtualCollection> q
639                    = em.createNamedQuery("VirtualCollection.findAllByState",
640                            VirtualCollection.class);
641            q.setParameter("state", VirtualCollection.State.PUBLIC_PENDING);
642            q.setParameter("date", nowDateAlloc);
643            q.setLockMode(LockModeType.PESSIMISTIC_WRITE);
644            for (VirtualCollection vc : q.getResultList()) {
645                if (vc.getPersistentIdentifier() == null) {
646                    PersistentIdentifier pid = pid_provider.createIdentifier(vc);
647                    vc.setPersistentIdentifier(pid);
648                }
649                vc.setState(VirtualCollection.State.PUBLIC);
650                em.persist(vc);
651                logger.info("assigned pid (identifer='{}') to virtual"
652                        + "collection (id={})",
653                        vc.getPersistentIdentifier().getIdentifier(),
654                        vc.getId());
655            }
656            em.getTransaction().commit();
657
658            /*
659             * delayed purging of deleted virtual collections
660             */
661            em.getTransaction().begin();
662            q.setParameter("state", VirtualCollection.State.DELETED);
663            q.setParameter("date", nowDatePurge);
664            q.setLockMode(LockModeType.PESSIMISTIC_WRITE);
665            for (VirtualCollection vc : q.getResultList()) {
666                vc.setState(VirtualCollection.State.DEAD);
667                em.remove(vc);
668                logger.debug("purged virtual collection (id={})", vc.getId());
669            }
670            em.getTransaction().commit();
671        } catch (VirtualCollectionRegistryException e) {
672            logger.error("error while doing maintenance", e);
673        } finally {
674            datastore.closeEntityManager();
675        }
676    }
677
678    private static User fetchUser(EntityManager em, Principal principal) {
679        User user = null;
680        try {
681            TypedQuery<User> q
682                    = em.createNamedQuery("User.findByName", User.class);
683            q.setParameter("name", principal.getName());
684            user = q.getSingleResult();
685        } catch (NoResultException e) {
686            /* IGNORE */
687        }
688        return user;
689    }
690
691    /**
692     * Creates a single thread scheduled executor with the specified thread name
693     *
694     * @param threadName name for new executor threads
695     * @return
696     */
697    private static ScheduledExecutorService createSingleThreadScheduledExecutor(final String threadName) {
698        return Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
699            // decorate default thread factory so that we can provide a
700            // custom thread name
701            final AtomicInteger i = new AtomicInteger(0);
702
703            @Override
704            public Thread newThread(Runnable r) {
705                final Thread thread = Executors.defaultThreadFactory().newThread(r);
706                thread.setName(threadName + "-" + i.addAndGet(1));
707                return thread;
708            }
709        });
710    }
711
712    private boolean isAllowedToModify(Principal principal, VirtualCollection c) {
713        // admin and owner are allowed to modify collections
714        return adminUsersService.isAdmin(principal.getName())
715                || c.getOwner().equalsPrincipal(principal);
716    }
717
718} // class VirtualCollectionRegistry
Note: See TracBrowser for help on using the repository browser.