source: ComponentRegistry/trunk/ComponentRegistry/src/main/java/clarin/cmdi/componentregistry/impl/database/ComponentRegistryDbImpl.java @ 3451

Last change on this file since 3451 was 3451, checked in by George.Georgovassilis@mpi.nl, 11 years ago

#360 Fixes for shha lux16 environment and renaming of DAO interfaces and implementations

File size: 28.3 KB
Line 
1package clarin.cmdi.componentregistry.impl.database;
2
3import clarin.cmdi.componentregistry.CMDComponentSpecExpander;
4import clarin.cmdi.componentregistry.ComponentRegistry;
5import clarin.cmdi.componentregistry.ComponentRegistryException;
6import clarin.cmdi.componentregistry.ComponentStatus;
7import clarin.cmdi.componentregistry.Configuration;
8import clarin.cmdi.componentregistry.DeleteFailedException;
9import clarin.cmdi.componentregistry.MDMarshaller;
10import clarin.cmdi.componentregistry.Owner;
11import clarin.cmdi.componentregistry.OwnerGroup;
12import clarin.cmdi.componentregistry.OwnerUser;
13import clarin.cmdi.componentregistry.UserUnauthorizedException;
14import clarin.cmdi.componentregistry.components.CMDComponentSpec;
15import clarin.cmdi.componentregistry.impl.ComponentRegistryImplBase;
16import clarin.cmdi.componentregistry.model.AbstractDescription;
17import clarin.cmdi.componentregistry.model.Comment;
18import clarin.cmdi.componentregistry.model.ComponentDescription;
19import clarin.cmdi.componentregistry.model.ProfileDescription;
20import clarin.cmdi.componentregistry.model.RegistryUser;
21import clarin.cmdi.componentregistry.persistence.AbstractDescriptionDao;
22import clarin.cmdi.componentregistry.persistence.CommentsDao;
23import clarin.cmdi.componentregistry.persistence.ComponentDescriptionDao;
24import clarin.cmdi.componentregistry.persistence.ProfileDescriptionDao;
25import clarin.cmdi.componentregistry.persistence.UserDao;
26
27import java.io.ByteArrayInputStream;
28import java.io.ByteArrayOutputStream;
29import java.io.IOException;
30import java.io.InputStream;
31import java.io.OutputStream;
32import java.io.UnsupportedEncodingException;
33import java.security.Principal;
34import java.text.ParseException;
35import java.util.Calendar;
36import java.util.Collection;
37import java.util.Collections;
38import java.util.Date;
39import java.util.List;
40
41import javax.xml.bind.JAXBException;
42import javax.xml.transform.TransformerException;
43
44import org.slf4j.Logger;
45import org.slf4j.LoggerFactory;
46import org.springframework.beans.factory.annotation.Autowired;
47import org.springframework.beans.factory.annotation.Qualifier;
48import org.springframework.dao.DataAccessException;
49
50/**
51 * Implementation of ComponentRegistry that uses Database Acces Objects for
52 * accessing the registry (ergo: a database implementation)
53 *
54 * @author Twan Goosen <twan.goosen@mpi.nl>
55 * @author George.Georgovassilis@mpi.nl
56 */
57public class ComponentRegistryDbImpl extends ComponentRegistryImplBase
58        implements ComponentRegistry {
59
60    private final static Logger LOG = LoggerFactory
61            .getLogger(ComponentRegistryDbImpl.class);
62    private Owner registryOwner;
63    private ComponentStatus registryStatus;
64    @Autowired
65    private Configuration configuration;
66    @Autowired
67    @Qualifier("componentsCache")
68    private CMDComponentSpecCache componentsCache;
69    @Autowired
70    @Qualifier("profilesCache")
71    private CMDComponentSpecCache profilesCache;
72    // DAO's
73    @Autowired
74    private ProfileDescriptionDao profileDescriptionDao;
75    @Autowired
76    private ComponentDescriptionDao componentDescriptionDao;
77    @Autowired
78    private UserDao userDao;
79    @Autowired
80    private CommentsDao commentsDao;
81    @Autowired
82    private MDMarshaller marshaller;
83
84    /**
85     * Default constructor, to use this as a (spring) bean. The public registry
86     * by default. Use setStatus() and setOwner() to make it another kind of
87     * registry.
88     *
89     * @see setUser
90     */
91    public ComponentRegistryDbImpl() throws TransformerException {
92        this.registryStatus = ComponentStatus.PUBLISHED;
93    }
94
95    /**
96     * Creates a new ComponentRegistry (either public or not) for the provided
97     * user. Only use for test and/or make sure to inject all dao's and other
98     * services
99     *
100     * @param userId
101     *            User id of the user to create registry for. Pass null for
102     *            public
103     */
104    public ComponentRegistryDbImpl(ComponentStatus status, Owner owner) {
105        this.registryStatus = status;
106        this.registryOwner = owner;
107    }
108
109    @Override
110    public List<ProfileDescription> getProfileDescriptions()
111            throws ComponentRegistryException {
112        try {
113            switch (registryStatus) {
114            // TODO: support other status types
115            case PRIVATE:
116                if (registryOwner == null) {
117                    throw new ComponentRegistryException(
118                            "Private workspace without owner!");
119                }
120                // TODO: Support group space
121                return profileDescriptionDao
122                        .getUserspaceDescriptions(registryOwner.getId());
123            case PUBLISHED:
124                return profileDescriptionDao.getPublicProfileDescriptions();
125            default:
126                throw new ComponentRegistryException("Unsupported status type"
127                        + registryStatus);
128            }
129        } catch (DataAccessException ex) {
130            throw new ComponentRegistryException(
131                    "Database access error while trying to get profile descriptions",
132                    ex);
133        }
134    }
135
136    @Override
137    public ProfileDescription getProfileDescription(String id)
138            throws ComponentRegistryException {
139        try {
140            return profileDescriptionDao.getByCmdId(id, getUserId());
141        } catch (DataAccessException ex) {
142            throw new ComponentRegistryException(
143                    "Database access error while trying to get profile description",
144                    ex);
145        }
146    }
147
148    @Override
149    public List<ComponentDescription> getComponentDescriptions()
150            throws ComponentRegistryException {
151        try {
152            if (isPublic()) {
153                return componentDescriptionDao.getPublicComponentDescriptions();
154            } else {
155                return componentDescriptionDao
156                        .getUserspaceDescriptions(getUserId());
157            }
158        } catch (DataAccessException ex) {
159            throw new ComponentRegistryException(
160                    "Database access error while trying to get component descriptions",
161                    ex);
162        }
163    }
164
165    @Override
166    public ComponentDescription getComponentDescription(String id)
167            throws ComponentRegistryException {
168        try {
169            return componentDescriptionDao.getByCmdId(id, getUserId());
170        } catch (DataAccessException ex) {
171            throw new ComponentRegistryException(
172                    "Database access error while trying to get component description",
173                    ex);
174        }
175    }
176
177    @Override
178    public List<Comment> getCommentsInProfile(String profileId,
179            Principal principal) throws ComponentRegistryException {
180        try {
181            if (profileDescriptionDao.isInRegistry(profileId, getUserId())) {
182                final List<Comment> commentsFromProfile = commentsDao
183                        .getCommentsFromProfile(profileId);
184                setCanDeleteInComments(commentsFromProfile, principal);
185                return commentsFromProfile;
186            } else {
187                // Profile does not exist (at least not in this registry)
188                throw new ComponentRegistryException("Profile " + profileId
189                        + " does not exist in specified registry");
190            }
191        } catch (DataAccessException ex) {
192            throw new ComponentRegistryException(
193                    "Database access error while trying to get list of comments from profile",
194                    ex);
195        }
196    }
197
198    @Override
199    public Comment getSpecifiedCommentInProfile(String profileId,
200            String commentId, Principal principal)
201            throws ComponentRegistryException {
202        try {
203            Comment comment = commentsDao
204                    .getSpecifiedCommentFromProfile(commentId);
205            if (comment != null
206                    && profileId.equals(comment.getProfileDescriptionId())
207                    && profileDescriptionDao.isInRegistry(
208                            comment.getProfileDescriptionId(), getUserId())) {
209                setCanDeleteInComments(Collections.singleton(comment),
210                        principal);
211                return comment;
212            } else {
213                // Comment exists in DB, but profile is not in this registry
214                throw new ComponentRegistryException("Comment " + commentId
215                        + " cannot be found in specified registry");
216            }
217        } catch (DataAccessException ex) {
218            throw new ComponentRegistryException(
219                    "Database access error while trying to get comment from profile",
220                    ex);
221        }
222    }
223
224    @Override
225    public List<Comment> getCommentsInComponent(String componentId,
226            Principal principal) throws ComponentRegistryException {
227        try {
228            if (componentDescriptionDao.isInRegistry(componentId, getUserId())) {
229                final List<Comment> commentsFromComponent = commentsDao
230                        .getCommentsFromComponent(componentId);
231                setCanDeleteInComments(commentsFromComponent, principal);
232                return commentsFromComponent;
233            } else {
234                // Component does not exist (at least not in this registry)
235                throw new ComponentRegistryException("Component " + componentId
236                        + " does not exist in specified registry");
237            }
238        } catch (DataAccessException ex) {
239            throw new ComponentRegistryException(
240                    "Database access error while trying to get list of comments from component",
241                    ex);
242        }
243    }
244
245    @Override
246    public Comment getSpecifiedCommentInComponent(String componentId,
247            String commentId, Principal principal)
248            throws ComponentRegistryException {
249        try {
250            Comment comment = commentsDao
251                    .getSpecifiedCommentFromComponent(commentId);
252            if (comment != null
253                    && componentId.equals(comment.getComponentDescriptionId())
254                    && componentDescriptionDao.isInRegistry(
255                            comment.getComponentDescriptionId(), getUserId())) {
256                setCanDeleteInComments(Collections.singleton(comment),
257                        principal);
258                return comment;
259            } else {
260                // Comment does not exists in DB or component is not in this
261                // registry
262                throw new ComponentRegistryException(
263                        "Comment "
264                                + commentId
265                                + " cannot be found in specified registry for specified component");
266            }
267        } catch (DataAccessException ex) {
268            throw new ComponentRegistryException(
269                    "Database access error while trying to get comment from component",
270                    ex);
271        }
272    }
273
274    /**
275     * Sets the {@link Comment#setCanDelete(boolean) canDelete} property on all
276     * comments in the provided collection for the perspective of the specified
277     * principal. Comment owners (determined by {@link Comment#getUserId() }) and
278     * admins can delete, others cannot.
279     *
280     * @param comments
281     *            comments to configure
282     * @param principal
283     *            user to configure for
284     * @see Comment#isCanDelete()
285     */
286    private void setCanDeleteInComments(Collection<Comment> comments,
287            Principal principal) {
288        if (principal != null && principal.getName() != null) {
289            final RegistryUser registryUser = userDao
290                    .getByPrincipalName(principal.getName());
291            final String registryUserId = registryUser == null ? null
292                    : registryUser.getId().toString();
293            final boolean isAdmin = registryUser != null
294                    && configuration.isAdminUser(principal);
295            for (Comment comment : comments) {
296                comment.setCanDelete(isAdmin
297                        || comment.getUserId().equals(registryUserId));
298            }
299        }
300    }
301
302    @Override
303    public CMDComponentSpec getMDProfile(String id)
304            throws ComponentRegistryException {
305        if (inWorkspace(profileDescriptionDao, id)) {
306            CMDComponentSpec result = profilesCache.get(id);
307            if (result == null && !profilesCache.containsKey(id)) {
308                result = getUncachedMDProfile(id);
309                profilesCache.put(id, result);
310            }
311            return result;
312        } else {
313            // May exist, but not in this workspace
314            LOG.debug("Could not find profile '{}' in registry '{}'",
315                    new Object[] { id, this.toString() });
316            return null;
317        }
318    }
319
320    public CMDComponentSpec getUncachedMDProfile(String id)
321            throws ComponentRegistryException {
322        try {
323            return getUncachedMDComponent(id, profileDescriptionDao);
324        } catch (DataAccessException ex) {
325            throw new ComponentRegistryException(
326                    "Database access error while trying to get profile", ex);
327        }
328    }
329
330    @Override
331    public CMDComponentSpec getMDComponent(String id)
332            throws ComponentRegistryException {
333        if (inWorkspace(componentDescriptionDao, id)) {
334            CMDComponentSpec result = componentsCache.get(id);
335            if (result == null && !componentsCache.containsKey(id)) {
336                result = getUncachedMDComponent(id);
337                componentsCache.put(id, result);
338            }
339            return result;
340        } else {
341            // May exist, but not in this workspace
342            LOG.info("Could not find component '{}' was in registry '{}'",
343                    new Object[] { id, this.toString() });
344            return null;
345        }
346    }
347
348    public CMDComponentSpec getUncachedMDComponent(String id)
349            throws ComponentRegistryException {
350        try {
351            return getUncachedMDComponent(id, componentDescriptionDao);
352        } catch (DataAccessException ex) {
353            throw new ComponentRegistryException(
354                    "Database access error while trying to get component", ex);
355        }
356    }
357
358    @Override
359    public int register(AbstractDescription description, CMDComponentSpec spec) {
360        enrichSpecHeader(spec, description);
361        try {
362            String xml = componentSpecToString(spec);
363            // Convert principal name to user record id
364            Number uid = convertUserInDescription(description);
365            getDaoForDescription(description).insertDescription(description,
366                    xml, isPublic(), uid);
367            invalidateCache(description);
368            return 0;
369        } catch (DataAccessException ex) {
370            LOG.error("Database error while registering component", ex);
371            return -1;
372        } catch (JAXBException ex) {
373            LOG.error("Error while registering component", ex);
374            return -2;
375        } catch (UnsupportedEncodingException ex) {
376            LOG.error("Error while registering component", ex);
377            return -3;
378        }
379    }
380
381    @Override
382    public int registerComment(Comment comment, String principalName)
383            throws ComponentRegistryException {
384        try {
385            if (comment.getComponentDescriptionId() != null
386                    && componentDescriptionDao.isInRegistry(
387                            comment.getComponentDescriptionId(), getUserId())
388                    || comment.getProfileDescriptionId() != null
389                    && profileDescriptionDao.isInRegistry(
390                            comment.getProfileDescriptionId(), getUserId())) {
391                // Convert principal name to user record id
392                Number uid = convertUserIdInComment(comment, principalName);
393                // Set date to current date
394                comment.setCommentDate(Comment.createNewDate());
395                Number commentId = commentsDao.insertComment(comment, uid);
396                comment.setId(commentId.toString());
397            } else {
398                throw new ComponentRegistryException(
399                        "Cannot insert comment into this registry. Unknown profileId or componentId");
400            }
401            return 0;
402        } catch (DataAccessException ex) {
403            LOG.error("Database error while registering component", ex);
404            return -1;
405        }
406    }
407
408    /**
409     * Calling service sets user id to principle. Our task is to convert this to
410     * an id for later reference. If none is set and this is a user's workspace,
411     * set from that user's id.
412     *
413     * It also sets the name in the description according to the display name in
414     * the database.
415     *
416     * @param description
417     *            Description containing principle name as userId
418     * @return Id (from database)
419     * @throws DataAccessException
420     */
421    private Number convertUserInDescription(AbstractDescription description)
422            throws DataAccessException {
423        Number uid = null;
424        String name = null;
425        if (description.getUserId() != null) {
426            RegistryUser user = userDao.getByPrincipalName(description
427                    .getUserId());
428            if (user != null) {
429                uid = user.getId();
430                name = user.getName();
431            }
432        } else {
433            uid = getUserId(); // this can be null as well
434        }
435        if (uid != null) {
436            description.setUserId(uid.toString());
437        }
438        if (name != null) {
439            description.setCreatorName(name);
440        }
441        return uid;
442    }
443
444    /**
445     * Calling service sets user id to principle. Our task is to convert this to
446     * an id for later reference. If none is set and this is a user's workspace,
447     * set from that user's id.
448     *
449     * @param comment
450     *            Comment containing principle name as userId
451     * @return Id (from database)
452     * @throws DataAccessException
453     */
454    private Number convertUserIdInComment(Comment comment, String principalName)
455            throws DataAccessException, ComponentRegistryException {
456        if (principalName != null) {
457            RegistryUser user = userDao.getByPrincipalName(principalName);
458            if (user != null) {
459                Number id = user.getId();
460                if (id != null) {
461                    // Set user id in comment for convenience of calling method
462                    comment.setUserId(id.toString());
463                    // Set name to user's preferred display name
464                    comment.setUserName(user.getName());
465                    return id;
466                } else {
467                    throw new ComponentRegistryException(
468                            "Cannot find user with principal name: "
469                                    + principalName);
470                }
471            }
472        }
473        return null;
474    }
475
476    @Override
477    public int update(AbstractDescription description, CMDComponentSpec spec,
478            Principal principal, boolean forceUpdate) {
479        try {
480            checkAuthorisation(description, principal);
481            checkAge(description, principal);
482            // For public components, check if used in other components or
483            // profiles (unless forced)
484            if (!forceUpdate && this.isPublic() && !description.isProfile()) {
485                checkStillUsed(description.getId());
486            }
487            AbstractDescriptionDao<?> dao = getDaoForDescription(description);
488            dao.updateDescription(getIdForDescription(description),
489                    description, componentSpecToString(spec));
490            invalidateCache(description);
491            return 0;
492        } catch (JAXBException ex) {
493            LOG.error("Error while updating component", ex);
494            return -1;
495        } catch (UnsupportedEncodingException ex) {
496            LOG.error("Error while updating component", ex);
497            return -1;
498        } catch (IllegalArgumentException ex) {
499            LOG.error("Error while updating component", ex);
500            return -1;
501        } catch (UserUnauthorizedException e) {
502            LOG.error("Error while updating component", e);
503            return -1;
504        } catch (DeleteFailedException e) {
505            LOG.error("Error while updating component", e);
506            return -1;
507        } catch (ComponentRegistryException e) {
508            LOG.error("Error while updating component", e);
509            return -1;
510        }
511    }
512
513    @Override
514    public int publish(AbstractDescription desc, CMDComponentSpec spec,
515            Principal principal) {
516        int result = 0;
517        AbstractDescriptionDao<?> dao = getDaoForDescription(desc);
518        if (!isPublic()) { // if already in public workspace there is nothing
519                           // todo
520            desc.setHref(AbstractDescription.createPublicHref(desc.getHref()));
521            Number id = getIdForDescription(desc);
522            try {
523                // Update description & content
524                dao.updateDescription(id, desc, componentSpecToString(spec));
525                // Set to public
526                dao.setPublished(id, true);
527            } catch (DataAccessException ex) {
528                LOG.error("Database error while updating component", ex);
529                return -1;
530            } catch (JAXBException ex) {
531                LOG.error("Error while updating component", ex);
532                return -2;
533            } catch (UnsupportedEncodingException ex) {
534                LOG.error("Error while updating component", ex);
535                return -3;
536            }
537        }
538        return result;
539    }
540
541    @Override
542    public void getMDProfileAsXml(String profileId, OutputStream output)
543            throws ComponentRegistryException {
544        CMDComponentSpec expandedSpec = CMDComponentSpecExpanderDbImpl
545                .expandProfile(profileId, this);
546        writeXml(expandedSpec, output);
547    }
548
549    @Override
550    public void getMDProfileAsXsd(String profileId, OutputStream outputStream)
551            throws ComponentRegistryException {
552        CMDComponentSpec expandedSpec = CMDComponentSpecExpanderDbImpl
553                .expandProfile(profileId, this);
554        writeXsd(expandedSpec, outputStream);
555    }
556
557    @Override
558    public void getMDComponentAsXml(String componentId, OutputStream output)
559            throws ComponentRegistryException {
560        CMDComponentSpec expandedSpec = CMDComponentSpecExpanderDbImpl
561                .expandComponent(componentId, this);
562        writeXml(expandedSpec, output);
563    }
564
565    @Override
566    public void getMDComponentAsXsd(String componentId,
567            OutputStream outputStream) throws ComponentRegistryException {
568        CMDComponentSpec expandedSpec = CMDComponentSpecExpanderDbImpl
569                .expandComponent(componentId, this);
570        writeXsd(expandedSpec, outputStream);
571    }
572
573    @Override
574    public void deleteMDProfile(String profileId, Principal principal)
575            throws UserUnauthorizedException, DeleteFailedException,
576            ComponentRegistryException {
577        ProfileDescription desc = getProfileDescription(profileId);
578        if (desc != null) {
579            try {
580                checkAuthorisation(desc, principal);
581                checkAge(desc, principal);
582                profileDescriptionDao.setDeleted(desc, true);
583                invalidateCache(desc);
584            } catch (DataAccessException ex) {
585                throw new DeleteFailedException(
586                        "Database access error while trying to delete profile",
587                        ex);
588            }
589        }
590    }
591
592    @Override
593    public void deleteMDComponent(String componentId, Principal principal,
594            boolean forceDelete) throws UserUnauthorizedException,
595            DeleteFailedException, ComponentRegistryException {
596        ComponentDescription desc = componentDescriptionDao
597                .getByCmdId(componentId);
598        if (desc != null) {
599            try {
600                checkAuthorisation(desc, principal);
601                checkAge(desc, principal);
602
603                if (!forceDelete) {
604                    checkStillUsed(componentId);
605                }
606                componentDescriptionDao.setDeleted(desc, true);
607                invalidateCache(desc);
608            } catch (DataAccessException ex) {
609                throw new DeleteFailedException(
610                        "Database access error while trying to delete component",
611                        ex);
612            }
613        }
614    }
615
616    /**
617     *
618     * @return whether this is the public registry
619     * @deprecated use {@link #getStatus() } to check if this is the
620     *             {@link ComponentStatus#PUBLISHED public registry}
621     */
622    @Override
623    @Deprecated
624    public boolean isPublic() {
625        return registryStatus == ComponentStatus.PUBLISHED;
626    }
627
628    /**
629     * @return The user id, or null if there is no owner or it is not a user.
630     */
631    private Number getUserId() {
632        if (registryOwner instanceof OwnerUser) {
633            return registryOwner.getId();
634        } else {
635            return null;
636        }
637    }
638
639    /**
640     * @return The group id, or null if there is no owner or it is not a group.
641     */
642    private Number getGroupId() {
643        if (registryOwner instanceof OwnerGroup) {
644            return registryOwner.getId();
645        } else {
646            return null;
647        }
648    }
649
650    @Override
651    public Owner getOwner() {
652        return registryOwner;
653    }
654
655    /**
656     * Sets status and owner of this registry
657     *
658     * @param status
659     *            new status for registry
660     * @param owner
661     *            new owner for registry
662     */
663    public void setStatus(ComponentStatus status, Owner owner) {
664        setStatus(status);
665        this.registryOwner = owner;
666    }
667
668    public void setStatus(ComponentStatus status) {
669        this.registryStatus = status;
670    }
671
672    @Override
673    public ComponentStatus getStatus() {
674        return registryStatus;
675    }
676
677    private void invalidateCache(AbstractDescription description) {
678        if (description.isProfile()) {
679            profilesCache.remove(description.getId());
680        } else {
681            componentsCache.remove(description.getId());
682        }
683    }
684
685    private AbstractDescriptionDao<?> getDaoForDescription(
686            AbstractDescription description) {
687        return description.isProfile() ? profileDescriptionDao
688                : componentDescriptionDao;
689    }
690
691    /**
692     * Looks up description on basis of CMD Id. This will also check if such a
693     * record even exists.
694     *
695     * @param description
696     *            Description to look up
697     * @return Database id for description
698     * @throws IllegalArgumentException
699     *             If description with non-existing id is passed
700     */
701    private Number getIdForDescription(AbstractDescription description)
702            throws IllegalArgumentException {
703        Number dbId = null;
704        AbstractDescriptionDao<?> dao = getDaoForDescription(description);
705        try {
706            dbId = dao.getDbId(description.getId());
707        } catch (DataAccessException ex) {
708            LOG.error(
709                    "Error getting dbId for component with id "
710                            + description.getId(), ex);
711        }
712        if (dbId == null) {
713            throw new IllegalArgumentException(
714                    "Could not get database Id for description");
715        } else {
716            return dbId;
717        }
718    }
719
720    private String componentSpecToString(CMDComponentSpec spec)
721            throws UnsupportedEncodingException, JAXBException {
722        ByteArrayOutputStream os = new ByteArrayOutputStream();
723        getMarshaller().marshal(spec, os);
724        String xml = os.toString("UTF-8");
725        return xml;
726    }
727
728    private CMDComponentSpec getUncachedMDComponent(String id,
729            AbstractDescriptionDao dao) {
730        String xml = dao.getContent(false, id);
731        if (xml != null) {
732            try {
733                InputStream is = new ByteArrayInputStream(xml.getBytes("UTF-8"));
734                return getMarshaller().unmarshal(CMDComponentSpec.class, is,
735                        null);
736
737            } catch (JAXBException ex) {
738                LOG.error("Error while unmarshalling", ex);
739            } catch (UnsupportedEncodingException ex) {
740                LOG.error("Exception while reading XML from database", ex);
741            }
742        }
743        return null;
744    }
745
746    private void checkAuthorisation(AbstractDescription desc,
747            Principal principal) throws UserUnauthorizedException {
748        if (!isOwnerOfDescription(desc, principal.getName())
749                && !configuration.isAdminUser(principal)) {
750            throw new UserUnauthorizedException("Unauthorized operation user '"
751                    + principal.getName()
752                    + "' is not the creator (nor an administrator) of the "
753                    + (desc.isProfile() ? "profile" : "component") + "(" + desc
754                    + ").");
755        }
756    }
757
758    private void checkAuthorisationComment(Comment desc, Principal principal)
759            throws UserUnauthorizedException {
760        if (!isOwnerOfComment(desc, principal.getName())
761                && !configuration.isAdminUser(principal)) {
762            throw new UserUnauthorizedException("Unauthorized operation user '"
763                    + principal.getName()
764                    + "' is not the creator (nor an administrator) of the "
765                    + (desc.getId()) + "(" + desc + ").");
766        }
767    }
768
769    private boolean isOwnerOfDescription(AbstractDescription desc,
770            String principalName) {
771        String owner = getDaoForDescription(desc).getOwnerPrincipalName(
772                getIdForDescription(desc));
773        return owner != null // If owner is null, no one can be owner
774                && principalName.equals(owner);
775    }
776
777    private boolean isOwnerOfComment(Comment com, String principalName) {
778        String owner = commentsDao.getOwnerPrincipalName(Integer.parseInt(com
779                .getId()));
780        return owner != null // If owner is null, no one can be owner
781                && principalName.equals(owner);
782    }
783
784    private void checkAge(AbstractDescription desc, Principal principal)
785            throws DeleteFailedException {
786        if (isPublic() && !configuration.isAdminUser(principal)) {
787            try {
788                Date regDate = AbstractDescription.getDate(desc
789                        .getRegistrationDate());
790                Calendar calendar = Calendar.getInstance();
791                calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1);
792                if (regDate.before(calendar.getTime())) { // More then month old
793                    throw new DeleteFailedException(
794                            "The "
795                                    + (desc.isProfile() ? "Profile"
796                                            : "Component")
797                                    + " is more then a month old and cannot be deleted anymore. It might have been used to create metadata, deleting it would invalidate that metadata.");
798                }
799            } catch (ParseException e) {
800                LOG.error("Cannot parse date of " + desc + " Error:" + e);
801            }
802        }
803    }
804
805    private boolean inWorkspace(AbstractDescriptionDao<?> dao, String cmdId) {
806        if (isPublic()) {
807            return dao.isPublic(cmdId);
808        } else {
809            return dao.isInUserSpace(cmdId, getUserId());
810        }
811    }
812
813    @Override
814    public String getName() {
815        if (isPublic()) {
816            return ComponentRegistry.PUBLIC_NAME;
817        } else {
818            return "Registry of " + userDao.getById(getUserId()).getName();
819        }
820    }
821
822    @Override
823    public List<ProfileDescription> getDeletedProfileDescriptions() {
824        return profileDescriptionDao.getDeletedDescriptions(getUserId());
825    }
826
827    @Override
828    public List<ComponentDescription> getDeletedComponentDescriptions() {
829        return componentDescriptionDao.getDeletedDescriptions(getUserId());
830    }
831
832    @Override
833    public void deleteComment(String commentId, Principal principal)
834            throws IOException, ComponentRegistryException,
835            UserUnauthorizedException, DeleteFailedException {
836        try {
837            Comment comment = commentsDao.getById(Integer.parseInt(commentId));
838            if (comment != null
839                    // Comment must have an existing (in this registry)
840                    // componentId or profileId
841                    && (comment.getComponentDescriptionId() != null
842                            && componentDescriptionDao.isInRegistry(
843                                    comment.getComponentDescriptionId(),
844                                    getUserId()) || comment
845                            .getProfileDescriptionId() != null
846                            && profileDescriptionDao.isInRegistry(
847                                    comment.getProfileDescriptionId(),
848                                    getUserId()))) {
849                checkAuthorisationComment(comment, principal);
850                commentsDao.deleteComment(comment);
851            } else {
852                // Comment exists in DB, but component is not in this registry
853                throw new ComponentRegistryException("Comment " + commentId
854                        + " cannot be found in specified registry");
855            }
856        } catch (DataAccessException ex) {
857            throw new DeleteFailedException(
858                    "Database access error while trying to delete component",
859                    ex);
860        } catch (NumberFormatException ex) {
861            throw new DeleteFailedException(
862                    "Illegal comment ID, cannot parse integer", ex);
863        }
864    }
865
866    @Override
867    public CMDComponentSpecExpander getExpander() {
868        return new CMDComponentSpecExpanderDbImpl(this);
869    }
870
871    @Override
872    protected MDMarshaller getMarshaller() {
873        return marshaller;
874    }
875
876    @Override
877    public String toString() {
878        return getName();
879    }
880}
Note: See TracBrowser for help on using the repository browser.