source: ComponentRegistry/trunk/ComponentRegistry/src/main/java/clarin/cmdi/componentregistry/rest/ComponentRegistryRestService.java @ 5553

Last change on this file since 5553 was 5553, checked in by olhsha@mpi.nl, 10 years ago

fixing serialisation issues for List<String>. Adding unit tests for goup service

File size: 84.1 KB
Line 
1package clarin.cmdi.componentregistry.rest;
2
3import clarin.cmdi.componentregistry.AllowedAttributetypesXML;
4import clarin.cmdi.componentregistry.AuthenticationFailException;
5import clarin.cmdi.componentregistry.ComponentRegistry;
6import clarin.cmdi.componentregistry.ComponentRegistryException;
7import clarin.cmdi.componentregistry.ComponentRegistryFactory;
8import clarin.cmdi.componentregistry.DeleteFailedException;
9import clarin.cmdi.componentregistry.ItemNotFoundException;
10import clarin.cmdi.componentregistry.MDMarshaller;
11import clarin.cmdi.componentregistry.RegistrySpace;
12import clarin.cmdi.componentregistry.UserCredentials;
13import clarin.cmdi.componentregistry.UserUnauthorizedException;
14import clarin.cmdi.componentregistry.components.CMDComponentSpec;
15import clarin.cmdi.componentregistry.components.CMDComponentType;
16import clarin.cmdi.componentregistry.impl.ComponentUtils;
17import clarin.cmdi.componentregistry.impl.database.GroupService;
18import clarin.cmdi.componentregistry.impl.database.ValidationException;
19import clarin.cmdi.componentregistry.model.BaseDescription;
20import clarin.cmdi.componentregistry.model.Comment;
21import clarin.cmdi.componentregistry.model.CommentResponse;
22import clarin.cmdi.componentregistry.model.ComponentDescription;
23import clarin.cmdi.componentregistry.model.Group;
24import clarin.cmdi.componentregistry.model.ProfileDescription;
25import clarin.cmdi.componentregistry.model.RegisterResponse;
26import clarin.cmdi.componentregistry.rss.Rss;
27import clarin.cmdi.componentregistry.rss.RssCreatorComments;
28import clarin.cmdi.componentregistry.rss.RssCreatorDescriptions;
29import com.google.common.collect.Lists;
30
31import com.sun.jersey.api.core.InjectParam;
32import com.sun.jersey.multipart.FormDataParam;
33
34import java.io.IOException;
35import java.io.InputStream;
36import java.io.OutputStream;
37import java.net.URI;
38import java.security.Principal;
39import java.text.ParseException;
40import java.util.ArrayList;
41import java.util.Arrays;
42import java.util.Collections;
43import java.util.Date;
44import java.util.List;
45
46import javax.servlet.ServletContext;
47import javax.servlet.http.HttpServletRequest;
48import javax.servlet.http.HttpServletResponse;
49import javax.ws.rs.Consumes;
50import javax.ws.rs.DELETE;
51import javax.ws.rs.DefaultValue;
52import javax.ws.rs.FormParam;
53import javax.ws.rs.GET;
54import javax.ws.rs.POST;
55import javax.ws.rs.Path;
56import javax.ws.rs.PathParam;
57import javax.ws.rs.Produces;
58import javax.ws.rs.QueryParam;
59import javax.ws.rs.WebApplicationException;
60import javax.ws.rs.core.Context;
61import javax.ws.rs.core.GenericEntity;
62import javax.ws.rs.core.MediaType;
63import javax.ws.rs.core.Response;
64import javax.ws.rs.core.Response.Status;
65import javax.ws.rs.core.SecurityContext;
66import javax.ws.rs.core.StreamingOutput;
67import javax.ws.rs.core.UriInfo;
68import javax.xml.bind.JAXBException;
69import javax.xml.bind.annotation.XmlElement;
70import javax.xml.bind.annotation.XmlRootElement;
71
72import org.slf4j.Logger;
73import org.slf4j.LoggerFactory;
74import org.springframework.beans.factory.annotation.Autowired;
75import org.springframework.stereotype.Service;
76import org.springframework.transaction.annotation.Transactional;
77
78/**
79 * Handles CRUD operations on
80 * {@link ComponentDescription}, {@link ProfileDescription} and {@link Comment}s
81 *
82 * @author twago@mpi.nl
83 * @author olsha@mpi.nl
84 * @author george.georgovassilis@mpi.nl
85 *
86 */
87@Path("/registry")
88@Service
89@Transactional(rollbackFor = {Exception.class, ValidationException.class})
90public class ComponentRegistryRestService implements
91        IComponentRegistryRestService {
92
93    private final static Logger LOG = LoggerFactory
94            .getLogger(IComponentRegistryRestService.class);
95    @Context
96    private UriInfo uriInfo;
97    @Context
98    private SecurityContext security;
99    @Context
100    private HttpServletRequest request;
101    @Context
102    private HttpServletResponse response;
103    @Context
104    private ServletContext servletContext;
105    @InjectParam(value = "componentRegistryFactory")
106    private ComponentRegistryFactory componentRegistryFactory;
107    @InjectParam(value = "mdMarshaller")
108    private MDMarshaller marshaller;
109    @Autowired
110    private GroupService groupService;
111
112    private ComponentRegistry getBaseRegistry() throws AuthenticationFailException {
113        Principal userPrincipal = this.checkAndGetUserPrincipal();
114        UserCredentials userCredentials = this.getUserCredentials(userPrincipal);
115        return componentRegistryFactory.getBaseRegistry(userCredentials);
116    }
117
118    private ComponentRegistry getRegistry(RegistrySpace space, Number groupId) {
119        Principal userPrincipal = security.getUserPrincipal();
120        UserCredentials userCredentials = this.getUserCredentials(userPrincipal);
121        try {
122            return componentRegistryFactory.getComponentRegistry(space, null, userCredentials, groupId);
123        } catch (UserUnauthorizedException uuEx) {
124            LOG.warn("Unauthorized access to {} registry by user {}", space,
125                    userCredentials);
126            LOG.debug("Details for unauthorized access", uuEx);
127            throw new WebApplicationException(uuEx, Status.FORBIDDEN);
128        }
129    }
130
131    /**
132     *
133     * @return Principal of current request
134     * @throws IllegalArgumentException If no user principal found
135     */
136    private Principal checkAndGetUserPrincipal()
137            throws AuthenticationFailException {
138        Principal principal = security.getUserPrincipal();
139        if (principal == null) {
140            throw new AuthenticationFailException("No user principal found.");
141        }
142        return principal;
143    }
144
145    private UserCredentials getUserCredentials(Principal userPrincipal) {
146        UserCredentials userCredentials = null;
147        if (userPrincipal != null) {
148            userCredentials = new UserCredentials(userPrincipal);
149        }
150        return userCredentials;
151    }
152
153    private ComponentRegistry initialiseRegistry(String space, String groupId) throws AuthenticationFailException {
154        //checking credentials
155        RegistrySpace regSpace = RegistrySpace.valueOf(space.toUpperCase());
156        UserCredentials user = this.getUserCredentials(this.checkAndGetUserPrincipal());
157        // initializing the registry
158        Number groupIdNumber = null;
159        if (groupId != null && !groupId.isEmpty()) {
160            groupIdNumber = Integer.parseInt(groupId);
161        }
162
163        return this.getRegistry(regSpace, groupIdNumber);
164    }
165
166    private boolean checkRegistrySpaceString(String registrySpace) {
167        return (registrySpace.equalsIgnoreCase("group") || registrySpace.equalsIgnoreCase("private") || registrySpace.equalsIgnoreCase("published"));
168    }
169
170    @Override
171    @GET
172    @Path("/components")
173    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
174        MediaType.APPLICATION_JSON})
175    public List<ComponentDescription> getRegisteredComponents(
176            @QueryParam(REGISTRY_SPACE_PARAM) @DefaultValue("published") String registrySpace,
177            @QueryParam(GROUPID_PARAM) String groupId)
178            throws ComponentRegistryException, IOException {
179        long start = System.currentTimeMillis();
180
181        if (!checkRegistrySpaceString(registrySpace)) {
182            response.sendError(Status.NOT_FOUND.getStatusCode(), "illegal registry space");
183            return new ArrayList<ComponentDescription>();
184        }
185
186        try {
187            ComponentRegistry cr = this.initialiseRegistry(registrySpace, groupId);
188            List<ComponentDescription> result = cr.getComponentDescriptions();
189            LOG.debug(
190                    "Releasing {} registered components into the world ({} millisecs)",
191                    result.size(), (System.currentTimeMillis() - start));
192
193            return result;
194        } catch (AuthenticationFailException e) {
195            response.sendError(Status.UNAUTHORIZED.getStatusCode(), e.toString());
196            return new ArrayList<ComponentDescription>();
197
198        } catch (UserUnauthorizedException e) {
199            response.sendError(Status.FORBIDDEN.getStatusCode(), e.toString());
200            return new ArrayList<ComponentDescription>();
201
202        }
203
204    }
205
206    @Override
207    @GET
208    @Path("/profiles")
209    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
210        MediaType.APPLICATION_JSON})
211    public List<ProfileDescription> getRegisteredProfiles(
212            @QueryParam(REGISTRY_SPACE_PARAM) @DefaultValue("published") String registrySpace,
213            @QueryParam(METADATA_EDITOR_PARAM) @DefaultValue("false") boolean metadataEditor,
214            @QueryParam(GROUPID_PARAM) String groupId)
215            throws ComponentRegistryException, IOException {
216
217        long start = System.currentTimeMillis();
218
219        if (!checkRegistrySpaceString(registrySpace)) {
220            response.sendError(Status.NOT_FOUND.getStatusCode(), "illegal registry space");
221            return new ArrayList<ProfileDescription>();
222        }
223        try {
224            ComponentRegistry cr = this.initialiseRegistry(registrySpace, groupId);
225            List<ProfileDescription> result = (metadataEditor) ? cr.getProfileDescriptionsForMetadaEditor() : cr.getProfileDescriptions();
226            LOG.debug(
227                    "Releasing {} registered components into the world ({} millisecs)",
228                    result.size(), (System.currentTimeMillis() - start));
229
230            return result;
231        } catch (AuthenticationFailException e) {
232            response.sendError(Status.UNAUTHORIZED.getStatusCode(), e.toString());
233            return new ArrayList<ProfileDescription>();
234
235        } catch (UserUnauthorizedException e) {
236            response.sendError(Status.FORBIDDEN.getStatusCode(), e.toString());
237            return new ArrayList<ProfileDescription>();
238        }
239    }
240
241    @Override
242    @GET
243    @Path("/components/{componentId}")
244    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
245        MediaType.APPLICATION_JSON})
246    public Response getRegisteredComponent(
247            @PathParam("componentId") String componentId) throws IOException {
248        LOG.debug("Component with id: {} is requested.", componentId);
249        try {
250            CMDComponentSpec mdComponent = this.getBaseRegistry().getMDComponentAccessControlled(componentId);
251            return Response.ok(mdComponent).build();
252        } catch (ItemNotFoundException e) {
253            return Response.status(Status.NOT_FOUND).build();
254        } catch (ComponentRegistryException e1) {
255            return Response.serverError().status(Status.CONFLICT).build();
256        } catch (AuthenticationFailException e) {
257            return Response.serverError().status(Status.UNAUTHORIZED).build();
258        } catch (UserUnauthorizedException e) {
259            return Response.serverError().status(Status.FORBIDDEN).build();
260        }
261    }
262
263    @Override
264    @GET
265    @Path("/profiles/{profileId}")
266    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
267        MediaType.APPLICATION_JSON})
268    public Response getRegisteredProfile(
269            @PathParam("profileId") String profileId) throws IOException {
270        LOG.debug("Profile with id {} is requested.", profileId);
271        try {
272            CMDComponentSpec mdProfile = this.getBaseRegistry().getMDProfileAccessControled(profileId);
273            return Response.ok(mdProfile).build();
274        } catch (ItemNotFoundException e) {
275            return Response.status(Status.NOT_FOUND).build();
276        } catch (ComponentRegistryException e1) {
277            return Response.serverError().status(Status.CONFLICT).build();
278        } catch (UserUnauthorizedException e) {
279            return Response.serverError().status(Status.FORBIDDEN).build();
280        } catch (AuthenticationFailException e) {
281            return Response.serverError().status(Status.UNAUTHORIZED).build();
282        }
283    }
284
285    @Override
286    @GET
287    @Path("/components/{componentId}/{rawType}")
288    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML})
289    public Response getRegisteredComponentRawType(
290            @PathParam("componentId") final String componentId, @PathParam("rawType") String rawType) throws ComponentRegistryException {
291
292        LOG.debug("Component with id: {} and rawType: {} is requested.", componentId, rawType);
293        try {
294            final ComponentRegistry registry = this.getBaseRegistry();
295            try {
296                ComponentDescription desc = registry.getComponentDescriptionAccessControlled(componentId);
297                StreamingOutput result = null;
298                String fileName = desc.getName() + "." + rawType;
299                if ("xml".equalsIgnoreCase(rawType)) {
300                    result = new StreamingOutput() {
301                        @Override
302                        public void write(OutputStream output) throws IOException,
303                                WebApplicationException {
304                            try {
305                                try {
306                                    try {
307                                        registry.getMDComponentAsXml(componentId, output);
308                                    } catch (ItemNotFoundException e1) {
309                                        LOG.warn("Could not retrieve component {}",
310                                                componentId);
311                                        LOG.debug("Details", e1);
312                                        throw new WebApplicationException(e1, Response
313                                                .serverError()
314                                                .status(Status.INTERNAL_SERVER_ERROR)
315                                                .build());
316                                    }
317                                } catch (ComponentRegistryException e) {
318                                    LOG.warn("Could not retrieve component {}",
319                                            componentId);
320                                    LOG.debug("Details", e);
321                                    throw new WebApplicationException(e, Response
322                                            .serverError()
323                                            .status(Status.INTERNAL_SERVER_ERROR)
324                                            .build());
325                                }
326
327                            } catch (UserUnauthorizedException e2) {
328                                LOG.error(e2.toString());
329                            }
330                        }
331                    };
332                    return createDownloadResponse(result, fileName);
333                } else if ("xsd".equalsIgnoreCase(rawType)) {
334                    result = new StreamingOutput() {
335                        @Override
336                        public void write(OutputStream output) throws IOException,
337                                WebApplicationException {
338                            try {
339                                try {
340                                    try {
341                                        registry.getMDComponentAsXsd(componentId, output);
342                                    } catch (ItemNotFoundException e1) {
343                                        LOG.warn("Could not retrieve component {}",
344                                                componentId);
345                                        LOG.debug("Details", e1);
346                                        throw new WebApplicationException(e1, Response
347                                                .serverError()
348                                                .status(Status.INTERNAL_SERVER_ERROR)
349                                                .build());
350                                    }
351                                } catch (ComponentRegistryException e) {
352                                    LOG.warn("Could not retrieve component {}",
353                                            componentId);
354                                    LOG.debug("Details", e);
355                                    throw new WebApplicationException(e, Response
356                                            .serverError()
357                                            .status(Status.INTERNAL_SERVER_ERROR)
358                                            .build());
359                                }
360                            } catch (UserUnauthorizedException e2) {
361                                LOG.error(e2.toString());
362                            }
363
364                        }
365                    };
366                    return createDownloadResponse(result, fileName);
367                } else {
368                    return Response.status(Status.NOT_FOUND).entity("Usupported raw type " + rawType).build();
369                }
370
371
372            } catch (UserUnauthorizedException e2) {
373                return Response.status(Status.FORBIDDEN).build();
374            }
375        } catch (ItemNotFoundException e3) {
376            return Response.status(Status.NOT_FOUND).build();
377        } catch (AuthenticationFailException e) {
378            return Response.serverError().status(Status.UNAUTHORIZED).build();
379        }
380    }
381
382    @Override
383    @GET
384    @Path("/components/usage/{componentId}")
385    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
386        MediaType.APPLICATION_JSON})
387    public List<BaseDescription> getComponentUsage(
388            @PathParam("componentId") String componentId) throws ComponentRegistryException, IOException {
389
390        final long start = System.currentTimeMillis();
391        try {
392            ComponentRegistry registry = this.getBaseRegistry();
393            List<ComponentDescription> components = registry.getUsageInComponents(componentId);
394            List<ProfileDescription> profiles = registry.getUsageInProfiles(componentId);
395
396            LOG.debug(
397                    "Found {} components and {} profiles that use component {} ({} millisecs)",
398                    components.size(), profiles.size(), componentId,
399                    (System.currentTimeMillis() - start));
400
401            List<BaseDescription> usages = new ArrayList<BaseDescription>(components.size() + profiles.size());
402            usages.addAll(components);
403            usages.addAll(profiles);
404
405            return usages;
406        } catch (ComponentRegistryException e) {
407            LOG.warn("Could not retrieve profile usage {}", componentId);
408            LOG.debug("Details", e);
409            return new ArrayList<BaseDescription>();
410        } catch (AuthenticationFailException e1) {
411            response.sendError(Status.UNAUTHORIZED.getStatusCode());
412            return new ArrayList<BaseDescription>();
413        }
414    }
415
416    @Override
417    @GET
418    @Path("/profiles/{profileId}/comments")
419    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
420        MediaType.APPLICATION_JSON})
421    public List<Comment> getCommentsFromProfile(
422            @PathParam("profileId") String profileId)
423            throws IOException {
424        long start = System.currentTimeMillis();
425        try {
426            List<Comment> comments = this.getBaseRegistry().getCommentsInProfile(profileId);
427            LOG.debug(
428                    "Releasing {} registered comments in profile into the world ({} millisecs)",
429                    comments.size(), (System.currentTimeMillis() - start));
430            return comments;
431        } catch (ComponentRegistryException e) {
432            response.sendError(Status.INTERNAL_SERVER_ERROR.getStatusCode(), e.getMessage());
433            return new ArrayList<Comment>();
434        } catch (ItemNotFoundException e) {
435            response.sendError(Status.NOT_FOUND.getStatusCode(), e.getMessage());
436            return new ArrayList<Comment>();
437        } catch (UserUnauthorizedException e) {
438            response.sendError(Status.FORBIDDEN.getStatusCode(), e.getMessage());
439            return new ArrayList<Comment>();
440        } catch (AuthenticationFailException e1) {
441            response.sendError(Status.UNAUTHORIZED.getStatusCode(), e1.getMessage());
442            return new ArrayList<Comment>();
443        }
444    }
445
446    @Override
447    @GET
448    @Path("/components/{componentId}/comments")
449    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
450        MediaType.APPLICATION_JSON})
451    public List<Comment> getCommentsFromComponent(
452            @PathParam("componentId") String componentId)
453            throws IOException {
454        long start = System.currentTimeMillis();
455        try {
456            List<Comment> comments = this.getBaseRegistry().getCommentsInComponent(componentId);
457            LOG.debug(
458                    "Releasing {} registered comments in Component into the world ({} millisecs)",
459                    comments.size(), (System.currentTimeMillis() - start));
460            return comments;
461        } catch (ComponentRegistryException e) {
462            response.sendError(Status.INTERNAL_SERVER_ERROR.getStatusCode(), e.getMessage());
463            return new ArrayList<Comment>();
464        } catch (ItemNotFoundException e) {
465            response.sendError(Status.NOT_FOUND.getStatusCode(), e.getMessage());
466            return new ArrayList<Comment>();
467        } catch (UserUnauthorizedException e1) {
468            response.sendError(Status.FORBIDDEN.getStatusCode(), e1.getMessage());
469            return new ArrayList<Comment>();
470        } catch (AuthenticationFailException e1) {
471            response.sendError(Status.UNAUTHORIZED.getStatusCode(), e1.getMessage());
472            return new ArrayList<Comment>();
473        }
474    }
475
476    @Override
477    @GET
478    @Path("/profiles/{profileId}/comments/{commentId}")
479    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
480        MediaType.APPLICATION_JSON})
481    public Comment getSpecifiedCommentFromProfile(
482            @PathParam("profileId") String profileId,
483            @PathParam("commentId") String commentId)
484            throws IOException {
485
486        LOG.debug("Comments of profile with id {} are requested.", commentId);
487        try {
488
489            return this.getBaseRegistry().getSpecifiedCommentInProfile(profileId, commentId);
490        } catch (ComponentRegistryException e) {
491            response.sendError(Status.INTERNAL_SERVER_ERROR.getStatusCode(), e.getMessage());
492            return new Comment();
493        } catch (ItemNotFoundException e) {
494            response.sendError(Status.NOT_FOUND.getStatusCode(), e.getMessage());
495            return new Comment();
496        } catch (UserUnauthorizedException e1) {
497            response.sendError(Status.FORBIDDEN.getStatusCode(), e1.getMessage());
498            return new Comment();
499        } catch (AuthenticationFailException e1) {
500            response.sendError(Status.UNAUTHORIZED.getStatusCode(), e1.getMessage());
501            return new Comment();
502        }
503    }
504
505    @Override
506    @GET
507    @Path("/components/{componentId}/comments/{commentId}")
508    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
509        MediaType.APPLICATION_JSON})
510    public Comment getSpecifiedCommentFromComponent(
511            @PathParam("componentId") String componentId,
512            @PathParam("commentId") String commentId)
513            throws IOException {
514        LOG.debug("Comments of component with id {} are requested.", commentId);
515        try {
516
517            return this.getBaseRegistry().getSpecifiedCommentInComponent(componentId, commentId);
518        } catch (ComponentRegistryException e) {
519            response.sendError(Status.INTERNAL_SERVER_ERROR.getStatusCode(), e.getMessage());
520            return new Comment();
521        } catch (ItemNotFoundException e) {
522            response.sendError(Status.NOT_FOUND.getStatusCode(), e.getMessage());
523            return new Comment();
524        } catch (UserUnauthorizedException e1) {
525            response.sendError(Status.FORBIDDEN.getStatusCode(), e1.getMessage());
526            return new Comment();
527        } catch (AuthenticationFailException e1) {
528            response.sendError(Status.UNAUTHORIZED.getStatusCode(), e1.getMessage());
529            return new Comment();
530        }
531    }
532
533    /**
534     *
535     * Purely helper method for my front-end (FLEX) which only does post/get
536     * requests. The query param is checked and the "proper" method is called.
537     *
538     * @param profileId
539     * @param method
540     * @return
541     */
542    // TODO: test via POSTMAN
543    @Override
544    @POST
545    @Path("/profiles/{profileId}")
546    public Response manipulateRegisteredProfile(
547            @PathParam("profileId") String profileId,
548            @FormParam("method") String method) {
549        if ("delete".equalsIgnoreCase(method)) {
550            return this.deleteRegisteredProfile(profileId);
551        } else {
552            return Response.ok().build();
553        }
554    }
555
556    @Override
557    @POST
558    @Path("/profiles/{profileId}/comments/{commentId}")
559    public Response manipulateCommentFromProfile(
560            @PathParam("profileId") String profileId,
561            @PathParam("commentId") String commentId,
562            @FormParam("method") String method) {
563        if ("delete".equalsIgnoreCase(method)) {
564            return this.deleteCommentFromProfile(profileId, commentId);
565        } else {
566            return Response.ok().build();
567        }
568    }
569
570    @Override
571    @POST
572    @Path("/components/{componentId}/comments/{commentId}")
573    public Response manipulateCommentFromComponent(
574            @PathParam("componentId") String componentId,
575            @PathParam("commentId") String commentId,
576            @FormParam("method") String method) {
577        if ("delete".equalsIgnoreCase(method)) {
578            return this.deleteCommentFromComponent(componentId, commentId);
579        } else {
580            return Response.ok().build();
581        }
582    }
583
584    // TODO: test via POSTMAN
585    @Override
586    @POST
587    @Path("/profiles/{profileId}/publish")
588    @Consumes("multipart/form-data")
589    public Response publishRegisteredProfile(
590            @PathParam("profileId") String profileId,
591            @FormDataParam(DATA_FORM_FIELD) InputStream input,
592            @FormDataParam(NAME_FORM_FIELD) String name,
593            @FormDataParam(DESCRIPTION_FORM_FIELD) String description,
594            @FormDataParam(GROUP_FORM_FIELD) String group,
595            @FormDataParam(DOMAIN_FORM_FIELD) String domainName) {
596
597        try {
598            Principal principal = checkAndGetUserPrincipal();
599            ComponentRegistry registry = this.getBaseRegistry();
600            ProfileDescription desc = registry.getProfileDescriptionAccessControlled(profileId);
601            if (desc != null) {
602                if (desc.isPublic()) {
603                    return Response.status(Status.CONFLICT).entity("Cannot publish already published profile.")
604                            .build();
605                }
606                desc.setPublic(true);
607                this.updateDescription(desc, name, description, domainName, group);
608                return this.register(input, desc, new PublishAction(principal), registry);
609            } else {
610                LOG.error("Update of nonexistent profile {} failed.", profileId);
611                return Response
612                        .serverError()
613                        .entity("Invalid id, cannot update nonexistent profile")
614                        .build();
615            }
616
617        } catch (AuthenticationFailException e) {
618            return Response.serverError().status(Status.UNAUTHORIZED)
619                    .build();
620        } catch (ItemNotFoundException e1) {
621            return Response.status(Status.NOT_FOUND).entity(e1.getMessage()).build();
622        } catch (ComponentRegistryException e) {
623            LOG.warn("Could not retrieve profile {}", profileId);
624            LOG.debug("Details", e);
625            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
626                    .build();
627        } catch (UserUnauthorizedException ex) {
628            return Response.status(Status.FORBIDDEN).entity(ex.getMessage())
629                    .build();
630        }
631    }
632
633    @Override
634    @POST
635    @Path("/profiles/{profileId}/update")
636    @Consumes("multipart/form-data")
637    public Response updateRegisteredProfile(
638            @PathParam("profileId") String profileId,
639            @FormDataParam(DATA_FORM_FIELD) InputStream input,
640            @FormDataParam(NAME_FORM_FIELD) String name,
641            @FormDataParam(DESCRIPTION_FORM_FIELD) String description,
642            @FormDataParam(GROUP_FORM_FIELD) String group,
643            @FormDataParam(DOMAIN_FORM_FIELD) String domainName) {
644        try {
645            ComponentRegistry br = this.getBaseRegistry();
646            ProfileDescription desc = br.getProfileDescriptionAccessControlled(profileId);
647            if (desc != null) {
648                if (desc.isPublic()) {
649                    return Response.status(Status.CONFLICT).entity("Cannot update already published profile.")
650                            .build();
651
652                }
653                Number groupId;
654                RegistrySpace space;
655                List<Number> groupIds = br.getItemGroups(profileId);
656                if (groupIds == null || groupIds.isEmpty()) {
657                    groupId = null;
658                    space = RegistrySpace.PRIVATE;
659                } else {
660                    groupId = groupIds.get(0);
661                    space = RegistrySpace.GROUP;
662                }
663
664                updateDescription(desc, name, description, domainName, group);
665                ComponentRegistry cr = this.getRegistry(space, groupId);
666                return register(input, desc, new UpdateAction(), cr);
667            } else {
668                LOG.error("Update of nonexistent id (" + profileId
669                        + ") failed.");
670                return Response
671                        .serverError()
672                        .entity("Invalid id, cannot update nonexistent profile")
673                        .build();
674            }
675        } catch (ComponentRegistryException e) {
676            LOG.warn("Could not retrieve profile {}", profileId);
677            LOG.debug("Details", e);
678            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
679                    .build();
680
681        } catch (UserUnauthorizedException ex) {
682            return Response.status(Status.FORBIDDEN).entity(ex.getMessage())
683                    .build();
684
685        } catch (ItemNotFoundException ex2) {
686            return Response.status(Status.NOT_FOUND).entity(ex2.getMessage())
687                    .build();
688        } catch (AuthenticationFailException e1) {
689            return Response.status(Status.UNAUTHORIZED).entity(e1.getMessage())
690                    .build();
691        }
692
693    }
694
695    /**
696     *
697     * Purely helper method for my front-end (FLEX) which van only do post/get
698     * requests. The query param is checked and the "proper" method is called.
699     *
700     * @param componentId
701     * @param method
702     * @return
703     */
704    // twan: why do we need it?
705    // TODO: test via POSTMAN
706    @Override
707    @POST
708    @Path("/components/{componentId}")
709    public Response manipulateRegisteredComponent(
710            @PathParam("componentId") String componentId,
711            @FormParam("method") String method) {
712        if ("delete".equalsIgnoreCase(method)) {
713            return this.deleteRegisteredComponent(componentId);
714        } else {
715            return Response.ok("Nothing to do, not 'delete' method").build();
716        }
717    }
718
719    // TODO: test via POSTMAN
720    @Override
721    @POST
722    @Path("/components/{componentId}/publish")
723    @Consumes("multipart/form-data")
724    public Response publishRegisteredComponent(
725            @PathParam("componentId") String componentId,
726            @FormDataParam(DATA_FORM_FIELD) InputStream input,
727            @FormDataParam(NAME_FORM_FIELD) String name,
728            @FormDataParam(DESCRIPTION_FORM_FIELD) String description,
729            @FormDataParam(GROUP_FORM_FIELD) String group,
730            @FormDataParam(DOMAIN_FORM_FIELD) String domainName) {
731
732        try {
733            Principal principal = checkAndGetUserPrincipal();
734            ComponentRegistry registry = this.getBaseRegistry();
735            ComponentDescription desc = registry.getComponentDescriptionAccessControlled(componentId);
736            if (desc != null) {
737                if (desc.isPublic()) {
738                    return Response.status(Status.CONFLICT).entity("Cannot publish already published omponent.")
739                            .build();
740                }
741                desc.setPublic(true);
742                this.updateDescription(desc, name, description, domainName, group);
743                return this.register(input, desc, new PublishAction(principal), registry);
744            } else {
745                LOG.error("Update of nonexistent id (" + componentId
746                        + ") failed.");
747                return Response
748                        .serverError()
749                        .entity("Invalid id, cannot update nonexistent profile")
750                        .build();
751            }
752        } catch (AuthenticationFailException e) {
753            LOG.warn("Could not retrieve component {}", componentId);
754            LOG.debug("Details", e);
755            return Response.serverError().status(Status.UNAUTHORIZED)
756                    .build();
757        } catch (ComponentRegistryException e) {
758            LOG.warn("Could not retrieve component {}", componentId);
759            LOG.debug("Details", e);
760            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
761                    .build();
762        } catch (ItemNotFoundException e) {
763            LOG.warn("Could not retrieve component {}", componentId);
764            LOG.debug("Details", e);
765            return Response.serverError().status(Status.NOT_FOUND)
766                    .build();
767        } catch (UserUnauthorizedException ex) {
768            return Response.status(Status.FORBIDDEN).entity(ex.getMessage())
769                    .build();
770        }
771    }
772
773    @Override
774    @POST
775    @Path("/components/{componentId}/update")
776    @Consumes("multipart/form-data")
777    public Response updateRegisteredComponent(
778            @PathParam("componentId") String componentId,
779            @FormDataParam(DATA_FORM_FIELD) InputStream input,
780            @FormDataParam(NAME_FORM_FIELD) String name,
781            @FormDataParam(DESCRIPTION_FORM_FIELD) String description,
782            @FormDataParam(GROUP_FORM_FIELD) String group,
783            @FormDataParam(DOMAIN_FORM_FIELD) String domainName) {
784        try {
785            ComponentRegistry br = this.getBaseRegistry();
786            ComponentDescription desc = br.getComponentDescriptionAccessControlled(componentId);
787            if (desc != null) {
788                if (desc.isPublic()) {
789                    return Response.status(Status.CONFLICT).entity("Cannot update already published component.")
790                            .build();
791                }
792                Number groupId;
793                RegistrySpace space;
794                List<Number> groupIds = br.getItemGroups(componentId);
795                if (groupIds == null || groupIds.isEmpty()) {
796                    groupId = null;
797                    space = RegistrySpace.PRIVATE;
798                } else {
799                    groupId = groupIds.get(0);
800                    space = RegistrySpace.GROUP;
801                }
802
803                this.updateDescription(desc, name, description, domainName, group);
804                ComponentRegistry cr = this.getRegistry(space, groupId);
805                return this.register(input, desc, new UpdateAction(), cr);
806            } else {
807                LOG.error("Update of nonexistent id (" + componentId
808                        + ") failed.");
809                return Response
810                        .serverError()
811                        .entity("Invalid id, cannot update nonexistent component")
812                        .build();
813            }
814        } catch (ComponentRegistryException e) {
815            LOG.warn("Could not retrieve component {}", componentId);
816            LOG.debug("Details", e);
817            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
818                    .build();
819        } catch (UserUnauthorizedException ex) {
820            return Response.status(Status.FORBIDDEN).entity(ex.getMessage())
821                    .build();
822        } catch (ItemNotFoundException ex2) {
823            return Response.status(Status.FORBIDDEN).entity(ex2.getMessage())
824                    .build();
825        } catch (AuthenticationFailException e1) {
826            return Response.status(Status.UNAUTHORIZED).entity(e1.getMessage())
827                    .build();
828        }
829
830    }
831
832    private void updateDescription(BaseDescription desc, String name,
833            String description, String domainName, String group) {
834        desc.setName(name);
835        desc.setDescription(description);
836        desc.setDomainName(domainName);
837        desc.setGroupName(group);
838        desc.setRegistrationDate(new Date());
839    }
840
841    @Override
842    @DELETE
843    @Path("/components/{componentId}")
844    public Response deleteRegisteredComponent(
845            @PathParam("componentId") String componentId) {
846        try {
847            ComponentRegistry registry = this.getBaseRegistry();
848            LOG.debug("Component with id {} set for deletion.", componentId);
849            registry.deleteMDComponent(componentId, false);
850        } catch (DeleteFailedException e) {
851            LOG.info("Component with id {} deletion failed. Reason: {}",
852                    componentId, e.getMessage());
853            LOG.debug("Deletion failure details:", e);
854            return Response.status(Status.FORBIDDEN)
855                    .entity("" + e.getMessage()).build();
856        } catch (ComponentRegistryException e) {
857            LOG.warn("Component with id " + componentId + " deletion failed.",
858                    e);
859            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
860                    .build();
861        } catch (ItemNotFoundException e) {
862            LOG.warn("Component with id " + componentId + " is not found.");
863            return Response.serverError().status(Status.NOT_FOUND)
864                    .build();
865        } catch (IOException e) {
866            LOG.error("Component with id " + componentId + " deletion failed.",
867                    e);
868            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
869                    .build();
870        } catch (UserUnauthorizedException e) {
871            LOG.info("Component with id {} deletion failed: {}", componentId,
872                    e.getMessage());
873            LOG.debug("Deletion failure details:", e);
874            return Response.serverError().status(Status.FORBIDDEN)
875                    .entity("" + e.getMessage()).build();
876        } catch (AuthenticationFailException e1) {
877            return Response.status(Status.UNAUTHORIZED).entity(e1.getMessage())
878                    .build();
879        }
880
881        LOG.info("Component with id: {} deleted.", componentId);
882        return Response.ok("Component with id" + componentId + " deleted.").build();
883    }
884
885    @Override
886    @DELETE
887    @Path("/profiles/{profileId}")
888    public Response deleteRegisteredProfile(
889            @PathParam("profileId") String profileId) {
890        try {
891            LOG.debug("Profile with id: {} set for deletion.", profileId);
892            this.getBaseRegistry().deleteMDProfile(profileId);
893        } catch (DeleteFailedException e) {
894            LOG.info("Profile with id: {} deletion failed: {}", profileId,
895                    e.getMessage());
896            LOG.debug("Deletion failure details:", e);
897            return Response.serverError().status(Status.FORBIDDEN)
898                    .entity("" + e.getMessage()).build();
899        } catch (ComponentRegistryException e) {
900            LOG.warn("Could not retrieve component", e);
901            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
902                    .build();
903        } catch (ItemNotFoundException e) {
904            LOG.warn("Profile with id " + profileId + " is not found.");
905            return Response.serverError().status(Status.NOT_FOUND)
906                    .build();
907        } catch (IOException e) {
908            LOG.error("Profile with id: " + profileId + " deletion failed.", e);
909            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
910                    .build();
911        } catch (UserUnauthorizedException e) {
912            LOG.info("Profile with id: {} deletion failed: {}", profileId,
913                    e.getMessage());
914            LOG.debug("Deletion failure details:", e);
915            return Response.serverError().status(Status.FORBIDDEN)
916                    .entity("" + e.getMessage()).build();
917        } catch (AuthenticationFailException e1) {
918            return Response.status(Status.UNAUTHORIZED).entity(e1.getMessage())
919                    .build();
920        }
921
922        LOG.info("Profile with id: {} deleted.", profileId);
923        return Response.ok().build();
924    }
925
926    @Override
927    @DELETE
928    @Path("/profiles/{profileId}/comments/{commentId}")
929    public Response deleteCommentFromProfile(
930            @PathParam("profileId") String profileId,
931            @PathParam("commentId") String commentId) {
932        try {
933            final ComponentRegistry registry = this.getBaseRegistry();
934            try {
935                final Comment comment = registry.getSpecifiedCommentInProfile(profileId, commentId);
936                if (comment != null
937                        && profileId.equals(comment.getComponentId())) {
938                    LOG.debug("Comment with id: {} set for deletion.", commentId);
939                    registry.deleteComment(commentId);
940                } else {
941                    throw new ComponentRegistryException(
942                            "Comment not found for specified profile");
943                }
944            } catch (ItemNotFoundException e1) {
945                LOG.info("Comment with id: {} deletion failed: {}", commentId,
946                        e1.getMessage());
947                LOG.debug("Deletion failure details:", e1);
948                return Response.serverError().status(Status.NOT_FOUND)
949                        .entity("" + e1.getMessage()).build();
950            }
951
952        } catch (DeleteFailedException e) {
953            LOG.info("Comment with id: {} deletion failed: {}", commentId,
954                    e.getMessage());
955            LOG.debug("Deletion failure details:", e);
956            return Response.serverError().status(Status.FORBIDDEN)
957                    .entity("" + e.getMessage()).build();
958        } catch (ComponentRegistryException e) {
959            LOG.info("Could not find comment " + commentId + " for " + profileId);
960            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
961                    .build();
962        } catch (IOException e) {
963            LOG.error("Comment with id: " + commentId + " deletion failed.", e);
964            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
965                    .build();
966        } catch (UserUnauthorizedException e) {
967            LOG.info("Comment with id: {} deletion failed: {}", commentId,
968                    e.getMessage());
969            LOG.debug("Deletion failure details:", e);
970            return Response.serverError().status(Status.FORBIDDEN)
971                    .entity("" + e.getMessage()).build();
972        } catch (AuthenticationFailException e1) {
973            return Response.status(Status.UNAUTHORIZED).entity(e1.getMessage())
974                    .build();
975        }
976
977        LOG.info("Comment with id: {} deleted.", commentId);
978        return Response.ok("Comment with id " + commentId + " deleted.").build();
979    }
980
981    @Override
982    @DELETE
983    @Path("/components/{componentId}/comments/{commentId}")
984    public Response deleteCommentFromComponent(
985            @PathParam("componentId") String componentId,
986            @PathParam("commentId") String commentId) {
987        try {
988            final ComponentRegistry registry = this.getBaseRegistry();
989            final Comment comment = registry.getSpecifiedCommentInComponent(componentId, commentId);
990            if (comment != null
991                    && componentId.equals(comment.getComponentId())) {
992                LOG.debug("Comment with id: {} set for deletion.", commentId);
993                registry.deleteComment(commentId);
994            } else {
995                throw new ComponentRegistryException(
996                        "Comment not found for specified component");
997            }
998        } catch (ItemNotFoundException e) {
999            LOG.info("Comment with id: {} deletion failed: {}", commentId,
1000                    e.getMessage());
1001            LOG.debug("Deletion failure details:", e);
1002            return Response.serverError().status(Status.NOT_FOUND)
1003                    .entity("" + e.getMessage()).build();
1004        } catch (DeleteFailedException e) {
1005            LOG.info("Comment with id: {} deletion failed: {}", commentId,
1006                    e.getMessage());
1007            LOG.debug("Deletion failure details:", e);
1008            return Response.serverError().status(Status.FORBIDDEN)
1009                    .entity("" + e.getMessage()).build();
1010        } catch (ComponentRegistryException e) {
1011            LOG.info("Could not retrieve component " + componentId + " for the component " + componentId);
1012            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
1013                    .build();
1014        } catch (IOException e) {
1015            LOG.error("Comment with id: " + commentId + " deletion failed.", e);
1016            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
1017                    .build();
1018        } catch (UserUnauthorizedException e) {
1019            LOG.info("Comment with id: {} deletion failed: {}", commentId,
1020                    e.getMessage());
1021            LOG.debug("Deletion failure details:", e);
1022            return Response.serverError().status(Status.FORBIDDEN)
1023                    .entity("" + e.getMessage()).build();
1024        } catch (AuthenticationFailException e1) {
1025            return Response.status(Status.UNAUTHORIZED).entity(e1.getMessage())
1026                    .build();
1027        }
1028
1029        LOG.info("Comment with id: {} deleted.", commentId);
1030        return Response.ok("Comment with id " + commentId + " deleted.").build();
1031    }
1032
1033    @Override
1034    @GET
1035    @Path("/profiles/{profileId}/{rawType}")
1036    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML})
1037    public Response getRegisteredProfileRawType(
1038            @PathParam("profileId") final String profileId,
1039            @PathParam("rawType") String rawType) throws ComponentRegistryException, IllegalArgumentException {
1040
1041
1042        LOG.debug("Profile with id {} and rawType {} is requested.", profileId,
1043                rawType);
1044        try {
1045            final ComponentRegistry registry = this.getBaseRegistry();
1046
1047            ProfileDescription desc = registry.getProfileDescriptionAccessControlled(profileId);
1048            if (desc == null) {
1049                return Response.status(Status.NOT_FOUND).build();
1050            }
1051
1052            StreamingOutput result = null;
1053            String fileName = desc.getName() + "." + rawType;
1054            if ("xml".equalsIgnoreCase(rawType)) {
1055                result = new StreamingOutput() {
1056                    @Override
1057                    public void write(OutputStream output) throws IOException,
1058                            WebApplicationException {
1059                        try {
1060                            registry.getMDProfileAsXml(profileId, output);
1061                        } catch (Exception e) {
1062                            LOG.warn("Could not retrieve component {}",
1063                                    profileId);
1064                            LOG.debug("Details", e);
1065                            throw new WebApplicationException(e, Response
1066                                    .serverError()
1067                                    .status(Status.INTERNAL_SERVER_ERROR)
1068                                    .build());
1069                        }
1070                    }
1071                };
1072            } else if ("xsd".equalsIgnoreCase(rawType)) {
1073                result = new StreamingOutput() {
1074                    @Override
1075                    public void write(OutputStream output) throws IOException,
1076                            WebApplicationException {
1077                        try {
1078                            registry.getMDProfileAsXsd(profileId, output);
1079                        } catch (Exception e) {
1080                            LOG.warn("Could not retrieve component {}",
1081                                    profileId);
1082                            LOG.debug("Details", e);
1083                            throw new WebApplicationException(e, Response
1084                                    .serverError()
1085                                    .status(Status.INTERNAL_SERVER_ERROR)
1086                                    .build());
1087                        }
1088                    }
1089                };
1090            } else {
1091                return Response.status(Status.NOT_FOUND).entity("Unsupported raw type " + rawType).build();
1092            }
1093            return createDownloadResponse(result, fileName);
1094        } catch (UserUnauthorizedException ex) {
1095            return Response.status(Status.FORBIDDEN).build();
1096        } catch (ItemNotFoundException e) {
1097            return Response.serverError().status(Status.NOT_FOUND)
1098                    .entity("" + e.getMessage()).build();
1099        } catch (AuthenticationFailException e1) {
1100            return Response.status(Status.UNAUTHORIZED).entity(e1.getMessage())
1101                    .build();
1102        }
1103
1104    }
1105
1106    private Response createDownloadResponse(StreamingOutput result,
1107            String fileName) {
1108        // Making response so it triggers browsers native save as dialog.
1109        Response response = Response
1110                .ok()
1111                .type("application/x-download")
1112                .header("Content-Disposition",
1113                "attachment; filename=\"" + fileName + "\"")
1114                .entity(result).build();
1115        return response;
1116
1117    }
1118
1119    @Override
1120    @POST
1121    @Path("/profiles")
1122    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
1123        MediaType.APPLICATION_JSON})
1124    @Consumes("multipart/form-data")
1125    public Response registerProfile(
1126            @FormDataParam(DATA_FORM_FIELD) InputStream input,
1127            @FormDataParam(NAME_FORM_FIELD) String name,
1128            @FormDataParam(DESCRIPTION_FORM_FIELD) String description,
1129            @FormDataParam(GROUP_FORM_FIELD) String group,
1130            @FormDataParam(DOMAIN_FORM_FIELD) String domainName) {
1131        try {
1132            Principal principal = checkAndGetUserPrincipal();
1133            UserCredentials userCredentials = getUserCredentials(principal);
1134            ProfileDescription desc = this.createNewProfileDescription();
1135            desc.setCreatorName(userCredentials.getDisplayName());
1136            desc.setUserId(userCredentials.getPrincipalName()); // Hash used to
1137            // be created
1138            // here, now Id
1139            // is
1140            // constructed
1141            // by impl
1142            desc.setName(name);
1143            desc.setDescription(description);
1144            desc.setGroupName(group);
1145            desc.setDomainName(domainName);
1146            desc.setPublic(false);
1147            LOG.debug("Trying to register Profile: {}", desc);
1148            ComponentRegistry cr = this.getRegistry(RegistrySpace.PRIVATE, null);
1149            return this.register(input, desc, new NewAction(), cr);
1150        } catch (AuthenticationFailException e) {
1151            LOG.debug("Details", e);
1152            return Response.serverError().status(Status.UNAUTHORIZED)
1153                    .build();
1154        } catch (UserUnauthorizedException ex) {
1155            return Response.status(Status.FORBIDDEN).entity(ex.getMessage())
1156                    .build();
1157        }
1158    }
1159
1160    @Override
1161    @POST
1162    @Path("/components")
1163    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
1164        MediaType.APPLICATION_JSON})
1165    @Consumes("multipart/form-data")
1166    public Response registerComponent(
1167            @FormDataParam(DATA_FORM_FIELD) InputStream input,
1168            @FormDataParam(NAME_FORM_FIELD) String name,
1169            @FormDataParam(DESCRIPTION_FORM_FIELD) String description,
1170            @FormDataParam(GROUP_FORM_FIELD) String group,
1171            @FormDataParam(DOMAIN_FORM_FIELD) String domainName) {
1172        try {
1173            Principal principal = checkAndGetUserPrincipal();
1174            UserCredentials userCredentials = getUserCredentials(principal);
1175            ComponentDescription desc = createNewComponentDescription();
1176            desc.setCreatorName(userCredentials.getDisplayName());
1177            desc.setUserId(userCredentials.getPrincipalName()); // Hash used to
1178            // be created
1179            // here, now Id
1180            // is
1181            // constructed
1182            // by impl
1183            desc.setName(name);
1184            desc.setDescription(description);
1185            desc.setGroupName(group);
1186            desc.setDomainName(domainName);
1187            desc.setPublic(false);
1188            LOG.debug("Trying to register Component: {}", desc);
1189            ComponentRegistry cr = this.getRegistry(RegistrySpace.PRIVATE, null);
1190            return this.register(input, desc, new NewAction(), cr);
1191        } catch (AuthenticationFailException e) {
1192            LOG.debug("Details", e);
1193            return Response.serverError().status(Status.UNAUTHORIZED)
1194                    .build();
1195        } catch (UserUnauthorizedException ex) {
1196            return Response.status(Status.FORBIDDEN).entity(ex.getMessage())
1197                    .build();
1198        }
1199    }
1200
1201    @Override
1202    @POST
1203    @Path("/components/{componentId}/comments")
1204    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
1205        MediaType.APPLICATION_JSON})
1206    @Consumes("multipart/form-data")
1207    public Response registerCommentInComponent(
1208            @FormDataParam(DATA_FORM_FIELD) InputStream input,
1209            @PathParam("componentId") String componentId) throws ComponentRegistryException {
1210        try {
1211            ComponentRegistry registry = this.getBaseRegistry();
1212            ComponentDescription description = registry.getComponentDescriptionAccessControlled(componentId);
1213
1214            LOG.debug("Trying to register comment to {}", componentId);
1215
1216            return this.registerComment(input, description, registry);
1217        } catch (AuthenticationFailException e) {
1218            LOG.debug("Details", e);
1219            return Response.serverError().status(Status.UNAUTHORIZED)
1220                    .build();
1221        } catch (UserUnauthorizedException ex) {
1222            return Response.status(Status.FORBIDDEN)
1223                    .build();
1224        } catch (ItemNotFoundException e) {
1225            return Response.serverError().status(Status.NOT_FOUND)
1226                    .entity("" + e.getMessage()).build();
1227        }
1228    }
1229
1230    // TODO test with the POSTMAN
1231    @Override
1232    @POST
1233    @Path("/profiles/{profileId}/comments")
1234    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
1235        MediaType.APPLICATION_JSON})
1236    @Consumes("multipart/form-data")
1237    public Response registerCommentInProfile(
1238            @FormDataParam(DATA_FORM_FIELD) InputStream input,
1239            @PathParam("profileId") String profileId)
1240            throws ComponentRegistryException {
1241        try {
1242            ComponentRegistry registry = this.getBaseRegistry();
1243            ProfileDescription description = registry
1244                    .getProfileDescriptionAccessControlled(profileId);
1245
1246            LOG.debug("Trying to register comment to {}", profileId);
1247
1248            return this.registerComment(input, description, registry);
1249        } catch (AuthenticationFailException e) {
1250            LOG.debug("Details", e);
1251            return Response.serverError().status(Status.UNAUTHORIZED)
1252                    .build();
1253        } catch (UserUnauthorizedException ex) {
1254            return Response.status(Status.FORBIDDEN)
1255                    .build();
1256        } catch (ItemNotFoundException e1) {
1257            return Response.serverError().status(Status.NOT_FOUND)
1258                    .entity("" + e1.getMessage()).build();
1259        }
1260    }
1261
1262    @Override
1263    @GET
1264    @Path("/pingSession")
1265    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
1266        MediaType.APPLICATION_JSON})
1267    public Response pingSession() {
1268        boolean stillActive = false;
1269        Principal userPrincipal = security.getUserPrincipal();
1270        if (LOG.isInfoEnabled()) {
1271            LOG.debug("ping by <{}>",
1272                    (userPrincipal == null ? "unauthorized user"
1273                    : userPrincipal.getName()));
1274        }
1275        if (request != null) {
1276            if (userPrincipal != null
1277                    && !ComponentRegistryFactory.ANONYMOUS_USER
1278                    .equals(userPrincipal.getName())) {
1279                stillActive = !((HttpServletRequest) request).getSession()
1280                        .isNew();
1281            }
1282        }
1283        return Response
1284                .ok()
1285                .entity(String.format("<session stillActive=\"%s\"/>",
1286                stillActive)).build();
1287    }
1288
1289    private Response register(InputStream input, BaseDescription desc, RegisterAction action, ComponentRegistry registry) throws UserUnauthorizedException {
1290        try {
1291
1292
1293            DescriptionValidator descriptionValidator = new DescriptionValidator(
1294                    desc);
1295            MDValidator validator = new MDValidator(input, desc, registry, marshaller);
1296            RegisterResponse response = new RegisterResponse();
1297            //obsolete. Make it setstatus
1298            response.setIsInUserSpace(!desc.isPublic());
1299            this.validate(response, descriptionValidator, validator);
1300            if (response.getErrors().isEmpty()) {
1301
1302                CMDComponentSpec spec = validator.getCMDComponentSpec();
1303
1304                // removing filename from spec before it gets extended.
1305                // recursion over all the components
1306                setFileNamesFromListToNull(Collections.singletonList(spec.getCMDComponent()));
1307
1308                try {
1309                    checkForRecursion(validator, registry, desc);
1310
1311                    // Add profile
1312                    int returnCode = action.execute(desc, spec, response,
1313                            registry);
1314                    if (returnCode == 0) {
1315                        response.setRegistered(true);
1316                        response.setDescription(desc);
1317                    } else {
1318                        response.setRegistered(false);
1319                        response.addError("Unable to register at this moment. Internal server error.");
1320                    }
1321                } catch (ComponentRegistryException ex) {
1322                    // Recursion detected
1323                    response.setRegistered(false);
1324                    response.addError("Error while expanding specification. "
1325                            + ex.getMessage());
1326                } catch (ItemNotFoundException ex) {
1327                    // Recursion detected
1328                    response.setRegistered(false);
1329                    response.addError("Error while expanding specification. "
1330                            + ex.getMessage());
1331                }
1332            } else {
1333                LOG.warn("Registration failed with validation errors: {}",
1334                        Arrays.toString(response.getErrors().toArray()));
1335                response.setRegistered(false);
1336            }
1337            LOG.info("Registered new {} {}", desc.isProfile() ? "profile"
1338                    : "component", desc);
1339            response.setIsProfile(desc.isProfile());
1340            return Response.ok(response).build();
1341        } finally {
1342            try {
1343                input.close();// either we read the input or there was an
1344                // exception, we need to close it.
1345            } catch (IOException e) {
1346                LOG.error("Error when closing inputstream: ", e);
1347            }
1348        }
1349    }
1350
1351    /**
1352     *
1353     * @param validator
1354     * @param registry
1355     * @param desc
1356     * @throws ComponentRegistryException if recursion is detected or something
1357     * goes wrong while trying to detect recursion
1358     */
1359    private void checkForRecursion(MDValidator validator,
1360            ComponentRegistry registry, BaseDescription desc)
1361            throws ComponentRegistryException {
1362        try {
1363            // Expand to check for recursion. Operate on copy so that original
1364            // does not get expanded.
1365            final CMDComponentSpec specCopy = validator
1366                    .getCopyOfCMDComponentSpec();
1367            // In case of recursion, the following will throw a
1368            // ComponentRegistryException
1369            registry.getExpander().expandNestedComponent(
1370                    Lists.newArrayList(specCopy.getCMDComponent()), desc.getId());
1371        } catch (JAXBException ex) {
1372            throw new ComponentRegistryException(
1373                    "Unmarshalling failed while preparing recursion detection",
1374                    ex);
1375        }
1376    }
1377
1378    private Response registerComment(InputStream input, BaseDescription description, ComponentRegistry registry) throws UserUnauthorizedException, AuthenticationFailException {
1379        try {
1380            CommentValidator validator = new CommentValidator(input, description, marshaller);
1381            CommentResponse responseLocal = new CommentResponse();
1382
1383            responseLocal.setIsInUserSpace(!description.isPublic());
1384            this.validateComment(responseLocal, validator);
1385            if (responseLocal.getErrors().isEmpty()) {
1386                Comment com = validator.getCommentSpec();
1387                // int returnCode = action.executeComment(com, response,
1388                // registry, principal.getName());
1389
1390                // If user name is left empty, fill it using the user's display
1391                // name
1392
1393                Principal principal = this.checkAndGetUserPrincipal();
1394                UserCredentials userCredentials = this.getUserCredentials(principal);
1395                if (null == com.getUserName() || "".equals(com.getUserName())) {
1396                    if (userCredentials != null) {
1397                        com.setUserName(userCredentials.getDisplayName());
1398                    } else {
1399                        com.setUserName(principal.getName());
1400                    }
1401                }
1402                try {
1403                    int returnCode = registry.registerComment(com,
1404                            principal.getName());
1405                    if (returnCode == 0) {
1406                        responseLocal.setRegistered(true);
1407                        responseLocal.setComment(com);
1408                    } else {
1409                        responseLocal.setRegistered(false);
1410                        responseLocal.addError("Unable to post at this moment. Internal server error.");
1411                    }
1412                    if (com.getComponentId() != null) {
1413                        LOG.info("Posted new comment on component {}",
1414                                com.getComponentId());
1415                    } else {
1416                        LOG.info("Posted new comment on profile {}",
1417                                com.getComponentId());
1418                    }
1419                } catch (ItemNotFoundException e) {
1420                    return Response.serverError().status(Status.NOT_FOUND)
1421                            .entity("" + e.getMessage()).build();
1422                }
1423            } else {
1424                LOG.warn(
1425                        "Posting of comment failed with validation errors: {}",
1426                        Arrays.toString(responseLocal.getErrors().toArray()));
1427                responseLocal.setRegistered(false);
1428            }
1429            return Response.ok(responseLocal).build();
1430        } catch (ComponentRegistryException ex) {
1431            LOG.error("Error while inserting comment: ", ex);
1432            return Response.serverError().entity(ex.getMessage()).build();
1433        } finally {
1434            try {
1435                input.close();// either we read the input or there was an
1436                // exception, we need to close it.
1437            } catch (IOException e) {
1438                LOG.error("Error when closing inputstream: ", e);
1439                return Response.serverError().build();
1440            }
1441        }
1442    }
1443
1444    private ComponentDescription createNewComponentDescription() {
1445        ComponentDescription desc = ComponentDescription.createNewDescription();
1446        desc.setHref(createXlink(desc.getId()));
1447        return desc;
1448    }
1449
1450    private ProfileDescription createNewProfileDescription() {
1451        ProfileDescription desc = ProfileDescription.createNewDescription();
1452        desc.setHref(createXlink(desc.getId()));
1453        return desc;
1454    }
1455
1456    private String createXlink(String id) {
1457        URI uri = uriInfo.getRequestUriBuilder().path(id).build();
1458        return uri.toString();
1459    }
1460
1461    /**
1462     *
1463     * @return The application's base URI as configured in the
1464     * {@link #APPLICATION_BASE_URL_PARAM} context parameter. If correctly
1465     * configured, it should look something like
1466     * "http://catalog.clarin.eu/ds/ComponentRegistry". <em>Be aware that this
1467     * can also be null if configured incorrectly!</em>
1468     *
1469     * @see #APPLICATION_BASE_URL_PARAM
1470     */
1471    private String getApplicationBaseURI() {
1472        return servletContext.getInitParameter(APPLICATION_BASE_URL_PARAM);
1473    }
1474
1475    private void validate(RegisterResponse response, Validator... validators) throws UserUnauthorizedException {
1476        for (Validator validator : validators) {
1477            if (!validator.validate()) {
1478                for (String error : validator.getErrorMessages()) {
1479                    response.addError(error);
1480                }
1481            }
1482        }
1483    }
1484
1485    private void validateComment(CommentResponse response,
1486            Validator... validators) throws UserUnauthorizedException {
1487        for (Validator validator : validators) {
1488            if (!validator.validate()) {
1489                for (String error : validator.getErrorMessages()) {
1490                    response.addError(error);
1491                }
1492            }
1493        }
1494    }
1495
1496    /**
1497     * @param componentRegistryFactory the componentRegistryFactory to set
1498     */
1499    @Override
1500    public void setComponentRegistryFactory(
1501            ComponentRegistryFactory componentRegistryFactory) {
1502        this.componentRegistryFactory = componentRegistryFactory;
1503    }
1504
1505    /**
1506     *
1507     * @param listofcomponents a list of components whose file-names and whose
1508     * childrens' filenames are to be set to null
1509     */
1510    @Override
1511    public void setFileNamesFromListToNull(
1512            List<CMDComponentType> listofcomponents) {
1513
1514        for (CMDComponentType currentcomponent : listofcomponents) {
1515            setFileNamesToNullCurrent(currentcomponent);
1516        }
1517
1518    }
1519
1520    /**
1521     *
1522     * @param currentcomponent a component whose file-name and whose children
1523     * filenames are to be set to null
1524     */
1525    protected void setFileNamesToNullCurrent(CMDComponentType currentcomponent) {
1526        currentcomponent.setFilename(null);
1527        setFileNamesFromListToNull(currentcomponent.getCMDComponent());
1528    }
1529
1530    /**
1531     *
1532     * @param isPublished if "true" then profiles and components from the user's
1533     * workspace, otherwise -- public
1534     * @param limit the number of items to be displayed
1535     * @return rss for the components in the database to which we are currently
1536     * connected
1537     * @throws ComponentRegistryException
1538     * @throws ParseException
1539     */
1540    @Override
1541    @GET
1542    @Path("/components/rss")
1543    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
1544        MediaType.APPLICATION_JSON})
1545    public Rss getRssComponent(@QueryParam(GROUPID_PARAM) String groupId,
1546            @QueryParam(REGISTRY_SPACE_PARAM) @DefaultValue("published") String registrySpace,
1547            @QueryParam(NUMBER_OF_RSSITEMS) @DefaultValue("20") String limit)
1548            throws ComponentRegistryException, ParseException, IOException {
1549        List<ComponentDescription> components = null;
1550        try {
1551            ComponentRegistry cr = this.initialiseRegistry(registrySpace, groupId);
1552            components = cr.getComponentDescriptions();
1553        } catch (AuthenticationFailException e) {
1554            response.sendError(Status.UNAUTHORIZED.getStatusCode(), e.toString());
1555            return new Rss();
1556        } catch (UserUnauthorizedException e) {
1557            response.sendError(Status.FORBIDDEN.getStatusCode(), e.toString());
1558            return new Rss();
1559        }
1560        // obsolete, add group Id
1561        final RssCreatorDescriptions instance = new RssCreatorDescriptions(!registrySpace.equalsIgnoreCase("published"), getApplicationBaseURI(), "components",
1562                Integer.parseInt(limit), components,
1563                ComponentUtils.COMPARE_ON_DATE);
1564        final Rss rss = instance.getRss();
1565        LOG.debug("Releasing RSS of {} most recently registered components",
1566                limit);
1567        return rss;
1568    }
1569
1570    /**
1571     *
1572     * @param isPublished if "true" then profiles and components from the user's
1573     * workspace, otherwise -- public
1574     * @param limit the number of items to be displayed
1575     * @return rss for the profiles in the database to which we are currently
1576     * connected
1577     * @throws ComponentRegistryException
1578     * @throws ParseException
1579     */
1580    @Override
1581    @GET
1582    @Path("/profiles/rss")
1583    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
1584        MediaType.APPLICATION_JSON})
1585    public Rss getRssProfile(@QueryParam(GROUPID_PARAM) String groupId,
1586            @QueryParam(REGISTRY_SPACE_PARAM) @DefaultValue("published") String registrySpace,
1587            @QueryParam(NUMBER_OF_RSSITEMS) @DefaultValue("20") String limit)
1588            throws ComponentRegistryException, ParseException, IOException {
1589        List<ProfileDescription> profiles = null;
1590        try {
1591            ComponentRegistry cr = this.initialiseRegistry(registrySpace, groupId);
1592            profiles = cr.getProfileDescriptions();
1593        } catch (AuthenticationFailException e) {
1594            response.sendError(Status.UNAUTHORIZED.getStatusCode(), e.toString());
1595            return new Rss();
1596        } catch (UserUnauthorizedException e) {
1597            response.sendError(Status.FORBIDDEN.getStatusCode(), e.toString());
1598            return new Rss();
1599        }
1600        final RssCreatorDescriptions instance = new RssCreatorDescriptions(
1601                !registrySpace.equalsIgnoreCase("published"), getApplicationBaseURI(), "profiles",
1602                Integer.parseInt(limit), profiles,
1603                ComponentUtils.COMPARE_ON_DATE);
1604        final Rss rss = instance.getRss();
1605        LOG.debug("Releasing RSS of {} most recently registered profiles",
1606                limit);
1607        return rss;
1608    }
1609
1610    /**
1611     *
1612     * @param profileId the Id of a profile whose comments are to be rss-ed
1613     * @param isPublished if "true" then profiles and components from the user's
1614     * workspace, otherwise -- public
1615     * @param limit the number of items to be displayed
1616     * @return rss of the comments for a chosen profile
1617     * @throws ComponentRegistryException
1618     * @throws IOException
1619     * @throws JAXBException
1620     * @throws ParseException
1621     */
1622    @Override
1623    @GET
1624    @Path("/profiles/{profileId}/comments/rss")
1625    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
1626        MediaType.APPLICATION_JSON})
1627    public Rss getRssOfCommentsFromProfile(
1628            @PathParam("profileId") String profileId,
1629            @QueryParam(NUMBER_OF_RSSITEMS) @DefaultValue("20") String limit)
1630            throws ComponentRegistryException, IOException, JAXBException,
1631            ParseException {
1632        try {
1633
1634            ComponentRegistry cr = this.getBaseRegistry();
1635
1636            final List<Comment> comments = cr.getCommentsInProfile(profileId);
1637            final ProfileDescription pd = cr.getProfileDescriptionAccessControlled(profileId);
1638            final String profileName = pd.getName();
1639            boolean profileIsPrivate = !pd.isPublic();
1640            // obsolete, status must be involved, not boolean profileIsPrivate
1641            final RssCreatorComments instance = new RssCreatorComments(profileIsPrivate,
1642                    getApplicationBaseURI(), Integer.parseInt(limit), profileId,
1643                    profileName, "profile", comments, Comment.COMPARE_ON_DATE);
1644            final Rss rss = instance.getRss();
1645            LOG.debug("Releasing RSS of {} most recent post on profile {}", limit,
1646                    profileId);
1647            return rss;
1648        } catch (UserUnauthorizedException ex) {
1649            response.sendError(Status.FORBIDDEN.getStatusCode());
1650            return new Rss();
1651        } catch (ItemNotFoundException e) {
1652            response.sendError(Status.NOT_FOUND.getStatusCode());
1653            return new Rss();
1654        } catch (AuthenticationFailException e) {
1655            response.sendError(Status.UNAUTHORIZED.getStatusCode(), e.toString());
1656            return new Rss();
1657        }
1658    }
1659
1660    /**
1661     *
1662     * @param componentId the Id of a component whose comments are to be rss-ed
1663     * @param isPublished if "true" then profiles and components from the user's
1664     * workspace, otherwise -- public
1665     * @param limit the number of items to be displayed
1666     * @return rss of the comments for a chosen component
1667     * @throws ComponentRegistryException
1668     * @throws IOException
1669     * @throws JAXBException
1670     * @throws ParseException
1671     */
1672    @Override
1673    @GET
1674    @Path("/components/{componentId}/comments/rss")
1675    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
1676        MediaType.APPLICATION_JSON})
1677    public Rss getRssOfCommentsFromComponent(
1678            @PathParam("componentId") String componentId,
1679            @QueryParam(NUMBER_OF_RSSITEMS)
1680            @DefaultValue("20") String limit)
1681            throws ComponentRegistryException, IOException, JAXBException,
1682            ParseException {
1683        try {
1684            ComponentRegistry cr = this.getBaseRegistry();
1685            final List<Comment> comments = cr.getCommentsInComponent(componentId);
1686            final ComponentDescription cd = cr.getComponentDescriptionAccessControlled(componentId);
1687            final String componentName = cd.getName();
1688            final boolean isPrivate = !cd.isPublic();
1689            //oboslete. status must be involved, not boolean isPrivate
1690            final RssCreatorComments instance = new RssCreatorComments(isPrivate,
1691                    getApplicationBaseURI(), Integer.parseInt(limit), componentId,
1692                    componentName, "component", comments, Comment.COMPARE_ON_DATE);
1693            final Rss rss = instance.getRss();
1694            LOG.debug("Releasing RSS of {} most recent post on component {}",
1695                    limit, componentId);
1696            return rss;
1697        } catch (UserUnauthorizedException e) {
1698            response.sendError(Status.FORBIDDEN.getStatusCode());
1699            return new Rss();
1700        } catch (ItemNotFoundException e) {
1701            response.sendError(Status.NOT_FOUND.getStatusCode());
1702            return new Rss();
1703        } catch (AuthenticationFailException e1) {
1704            response.sendError(Status.UNAUTHORIZED.getStatusCode());
1705            return new Rss();
1706        }
1707
1708    }
1709
1710    @Override
1711    @GET
1712    @Path("/AllowedTypes")
1713    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
1714        MediaType.APPLICATION_JSON})
1715    public AllowedAttributetypesXML getAllowedAttributeTypes()
1716            throws ComponentRegistryException, IOException, JAXBException,
1717            ParseException {
1718        return (new AllowedAttributetypesXML());
1719    }
1720
1721    @Override
1722    @GET
1723    @Path("/groups/usermembership")
1724    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
1725        MediaType.APPLICATION_JSON})
1726    public List<Group> getGroupsTheCurrentUserIsAMemberOf() {
1727        Principal principal = security.getUserPrincipal();
1728        if (principal == null) {
1729            return new ArrayList<Group>();
1730        }
1731        List<Group> groups = groupService.getGroupsOfWhichUserIsAMember(principal.getName());
1732        return groups;
1733    }
1734
1735    @Override
1736    @GET
1737    @Path("/items/{itemId}/groups")
1738    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
1739        MediaType.APPLICATION_JSON})
1740    public List<Group> getGroupsTheItemIsAMemberOf(@PathParam("itemId") String itemId) {
1741        return groupService.getGroupsTheItemIsAMemberOf(itemId);
1742    }
1743
1744    @Override
1745    @POST
1746    @Path("/items/{itemId}/transferownership")
1747    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
1748        MediaType.APPLICATION_JSON})
1749    public Response transferItemOwnershipToGroup(@PathParam("itemId") String itemId,
1750            @QueryParam("groupId") long groupId) throws IOException {
1751        Principal principal = security.getUserPrincipal();
1752        try {
1753            groupService.transferItemOwnershipFromUserToGroupId(principal.getName(), groupId, itemId);
1754            return Response.ok("Ownership transferred").build();
1755        } catch (UserUnauthorizedException e) {
1756            return Response.status(Status.FORBIDDEN).build();
1757        }
1758    }
1759
1760    @Override
1761    @GET
1762    @Path("/items/{itemId}")
1763    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
1764        MediaType.APPLICATION_JSON})
1765    public BaseDescription getBaseDescription(@PathParam("itemId") String itemId) throws ComponentRegistryException, IOException {
1766        LOG.debug("Item with id: {} is requested.", itemId);
1767        try {
1768            ComponentRegistry cr = this.getBaseRegistry();
1769            BaseDescription description;
1770            if (itemId.startsWith(ComponentDescription.COMPONENT_PREFIX)) {
1771                description = cr.getComponentDescriptionAccessControlled(itemId);
1772                return description;
1773            };
1774            if (itemId.startsWith(ProfileDescription.PROFILE_PREFIX)) {
1775                description = cr.getProfileDescriptionAccessControlled(itemId);
1776                return description;
1777            };
1778            response.sendError(Status.BAD_REQUEST.getStatusCode());
1779            return new BaseDescription();
1780
1781
1782        } catch (UserUnauthorizedException ex2) {
1783            response.sendError(Status.FORBIDDEN.getStatusCode(), ex2.getMessage());
1784            return new BaseDescription();
1785        } catch (ItemNotFoundException e) {
1786            response.sendError(Status.NOT_FOUND.getStatusCode(), e.getMessage());
1787            return new BaseDescription();
1788        } catch (AuthenticationFailException e) {
1789            response.sendError(Status.UNAUTHORIZED.getStatusCode(), e.toString());
1790            return new BaseDescription();
1791        }
1792    }
1793
1794    // Group Service (added by Olha)
1795    @Override
1796    @POST
1797    @Path("/groups/create")
1798    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
1799        MediaType.APPLICATION_JSON})
1800    public Response createNewGroup(@QueryParam("groupName") String groupName) throws IOException {
1801
1802        try {
1803            Principal principal = this.checkAndGetUserPrincipal();
1804            Number id = groupService.createNewGroup(groupName, principal.getName());
1805            return Response.ok("Group with the name " + groupName + " is created and given an id " + id).build();
1806        } catch (AuthenticationFailException e) {
1807            return Response.status(Status.UNAUTHORIZED).build();
1808        }
1809    }
1810
1811    @Override
1812    @GET
1813    @Path("/groups/principal")
1814    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
1815        MediaType.APPLICATION_JSON})
1816    public List<Group> getGroupsOwnedByUser(@QueryParam("principalName") String pricipalName) throws IOException {
1817
1818        try {
1819            Principal principal = this.checkAndGetUserPrincipal();
1820            return groupService.getGroupsOwnedByUser(principal.getName());
1821        } catch (AuthenticationFailException e) {
1822            response.sendError(Status.UNAUTHORIZED.getStatusCode());
1823            return new ArrayList<Group>();
1824        }
1825    }
1826
1827    @Override
1828    @GET
1829    @Path("/groups/names")
1830    public Response listGroupNames() throws IOException {
1831
1832        try {
1833            Principal principal = this.checkAndGetUserPrincipal();
1834            List<String> result = groupService.listGroupNames();
1835            //final GenericEntity<List<String>> entity  = new GenericEntity<List<String>>(result){};
1836            //return Response.status(Status.OK).entity(entity).build();
1837            StringsWrapper ids = new StringsWrapper();
1838            ids.setStrings(result);
1839            return Response.status(Status.OK).entity(ids).build();
1840        } catch (AuthenticationFailException e) {
1841            return Response.status(Status.UNAUTHORIZED).build();
1842        }
1843    }
1844
1845    @Override
1846    @GET
1847    @Path("/groups/ownership")
1848    public Response isOwner(@QueryParam("groupName") String groupName) throws IOException {
1849
1850        try {
1851            Principal principal = this.checkAndGetUserPrincipal();
1852            Boolean isOwner = groupService.isUserOwnerOfGroup(groupName, principal.getName());
1853            return Response.ok(isOwner.toString()).build();
1854        } catch (AuthenticationFailException e) {
1855            return Response.serverError().status(Status.UNAUTHORIZED).build();
1856        }
1857    }
1858
1859    @Override
1860    @POST
1861    @Path("/groups/makemember")
1862    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
1863        MediaType.APPLICATION_JSON})
1864    public Response makeGroupMember(@QueryParam("groupName") String groupName, @QueryParam("principalName") String principalName) throws IOException {
1865        try {
1866            ComponentRegistry registry = this.getBaseRegistry();
1867            Number id = registry.makeGroupMember(principalName, groupName);
1868            return Response.ok(id.toString()).build();
1869        } catch (UserUnauthorizedException e) {
1870            return Response.status(Status.FORBIDDEN).entity(e.getMessage()).build();
1871        } catch (ItemNotFoundException e) {
1872            return Response.status(Status.NOT_FOUND).entity(e.getMessage()).build();
1873       
1874        } catch (AuthenticationFailException e) {
1875            return Response.status(Status.UNAUTHORIZED).build();
1876        }
1877    }
1878   
1879//    @Override
1880//    @DELETE
1881//    @Path("/groups/removemember")
1882//    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML,
1883//        MediaType.APPLICATION_JSON})
1884//    public Response removeGroupMember(@QueryParam("groupName") String groupName, @QueryParam("principalName") String principalName) throws IOException {
1885//        try {
1886//            ComponentRegistry registry = this.getBaseRegistry();
1887//            Number id = registry.removeGroupMember(principalName, groupName);
1888//            return Response.ok(id.toString()).build();
1889//        } catch (UserUnauthorizedException e) {
1890//            return Response.status(Status.FORBIDDEN).entity(e.getMessage()).build();
1891//        } catch (ItemNotFoundException e) {
1892//            return Response.status(Status.NOT_FOUND).entity(e.getMessage()).build();
1893//       
1894//        } catch (AuthenticationFailException e) {
1895//            return Response.status(Status.UNAUTHORIZED).build();
1896//        }
1897//    }
1898
1899    @Override
1900    @GET
1901    @Path("/groups/profiles")
1902    public Response listProfiles(@QueryParam("groupId") String groupId) throws IOException {
1903
1904        try {
1905            Principal principal = this.checkAndGetUserPrincipal();
1906            List<String> result = groupService.getProfileIdsInGroup(Long.parseLong(groupId));
1907            StringsWrapper ids = new StringsWrapper();
1908            ids.setStrings(result);
1909            return Response.status(Status.OK).entity(ids).build();
1910        } catch (AuthenticationFailException e) {
1911            return Response.status(Status.UNAUTHORIZED).build();
1912        }
1913    }
1914
1915    @Override
1916    @GET
1917    @Path("/groups/components")
1918    public Response listComponents(@QueryParam("groupId") String groupId) throws IOException {
1919
1920        try {
1921            Principal principal = this.checkAndGetUserPrincipal();
1922            List<String> result = groupService.getComponentIdsInGroup(Long.parseLong(groupId));
1923            StringsWrapper ids = new StringsWrapper();
1924            ids.setStrings(result);
1925            return Response.status(Status.OK).entity(ids).build();
1926        } catch (AuthenticationFailException e) {
1927            response.sendError(Status.UNAUTHORIZED.getStatusCode());
1928            return Response.status(Status.UNAUTHORIZED).build();
1929        }
1930    }
1931
1932    @Override
1933    @GET
1934    @Path("/groups/nameById")
1935    public Response getGroupNameById(@QueryParam("groupId") String groupId) throws IOException {
1936
1937        try {
1938            Principal principal = this.checkAndGetUserPrincipal();
1939            String name = groupService.getGroupNameById(Long.parseLong(groupId));
1940            return Response.ok(name).build();
1941        } catch (AuthenticationFailException e) {
1942            return Response.status(Status.UNAUTHORIZED).build();
1943        } catch (ItemNotFoundException e) {
1944            return Response.status(Status.NOT_FOUND).build();
1945        }
1946    }
1947
1948    @Override
1949    @GET
1950    @Path("/groups/idByName")
1951    public Response getGroupIdByName(@QueryParam("groupName") String groupName) throws IOException {
1952
1953        try {
1954            Principal principal = this.checkAndGetUserPrincipal();
1955            Number id = groupService.getGroupIdByName(groupName);
1956            return Response.ok(id.toString()).build();
1957        } catch (AuthenticationFailException e) {
1958            return Response.status(Status.UNAUTHORIZED).build();
1959        } catch (ItemNotFoundException e) {
1960            return Response.status(Status.NOT_FOUND).build();
1961        }
1962    }
1963
1964    @XmlRootElement(name = "Identifiers")
1965    public static class StringsWrapper {
1966
1967        @XmlElement(name = "item")
1968        List<String> strings = new ArrayList<String>();
1969
1970        StringsWrapper() {
1971        }
1972
1973        public void setStrings(List<String> strings) {
1974            this.strings = strings;
1975        }
1976       
1977       
1978    }
1979}
Note: See TracBrowser for help on using the repository browser.