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

Last change on this file since 3088 was 3088, checked in by twagoo, 11 years ago

Changes in MdMarshaller? and its usage:

  • now used as an instantiated object (singleton bean via Spring).
  • XSLT transformation uses ComponentRegistryResourceResolver? (which now also implements javax.xml.transform.URIResolver)
  • Created xml catalog for tests, using svn-external copies of the comp2schema xslt
File size: 51.0 KB
Line 
1package clarin.cmdi.componentregistry.rest;
2
3import clarin.cmdi.componentregistry.AllowedAttributetypesXML;
4import clarin.cmdi.componentregistry.ComponentRegistry;
5import clarin.cmdi.componentregistry.ComponentRegistryException;
6import clarin.cmdi.componentregistry.ComponentRegistryFactory;
7import clarin.cmdi.componentregistry.ComponentStatus;
8import clarin.cmdi.componentregistry.DeleteFailedException;
9import clarin.cmdi.componentregistry.MDMarshaller;
10import clarin.cmdi.componentregistry.Owner;
11import clarin.cmdi.componentregistry.UserCredentials;
12import clarin.cmdi.componentregistry.UserUnauthorizedException;
13import clarin.cmdi.componentregistry.components.CMDComponentSpec;
14import clarin.cmdi.componentregistry.components.CMDComponentType;
15import clarin.cmdi.componentregistry.model.AbstractDescription;
16import clarin.cmdi.componentregistry.model.Comment;
17import clarin.cmdi.componentregistry.model.CommentResponse;
18import clarin.cmdi.componentregistry.model.ComponentDescription;
19import clarin.cmdi.componentregistry.model.ProfileDescription;
20import clarin.cmdi.componentregistry.model.RegisterResponse;
21import clarin.cmdi.componentregistry.rss.Rss;
22import clarin.cmdi.componentregistry.rss.RssCreatorComments;
23import clarin.cmdi.componentregistry.rss.RssCreatorDescriptions;
24import com.sun.jersey.api.core.InjectParam;
25import com.sun.jersey.multipart.FormDataParam;
26import com.sun.jersey.spi.inject.Inject;
27import java.io.IOException;
28import java.io.InputStream;
29import java.io.OutputStream;
30import java.net.URI;
31import java.security.Principal;
32import java.text.ParseException;
33import java.util.ArrayList;
34import java.util.Arrays;
35import java.util.List;
36import javax.servlet.ServletContext;
37import javax.servlet.http.HttpServletRequest;
38import javax.ws.rs.Consumes;
39import javax.ws.rs.DELETE;
40import javax.ws.rs.DefaultValue;
41import javax.ws.rs.FormParam;
42import javax.ws.rs.GET;
43import javax.ws.rs.POST;
44import javax.ws.rs.Path;
45import javax.ws.rs.PathParam;
46import javax.ws.rs.Produces;
47import javax.ws.rs.QueryParam;
48import javax.ws.rs.WebApplicationException;
49import javax.ws.rs.core.Context;
50import javax.ws.rs.core.MediaType;
51import javax.ws.rs.core.Response;
52import javax.ws.rs.core.Response.Status;
53import javax.ws.rs.core.SecurityContext;
54import javax.ws.rs.core.StreamingOutput;
55import javax.ws.rs.core.UriInfo;
56import javax.xml.bind.JAXBException;
57import org.slf4j.Logger;
58import org.slf4j.LoggerFactory;
59
60@Path("/registry")
61public class ComponentRegistryRestService {
62
63    private final static Logger LOG = LoggerFactory.getLogger(ComponentRegistryRestService.class);
64    public static final String APPLICATION_BASE_URL_PARAM = "eu.clarin.cmdi.componentregistry.serviceRootUrl";
65    @Context
66    private UriInfo uriInfo;
67    @Context
68    private SecurityContext security;
69    @Context
70    private HttpServletRequest request;
71    @Context
72    private ServletContext servletContext;
73    public static final String DATA_FORM_FIELD = "data";
74    public static final String NAME_FORM_FIELD = "name";
75    public static final String DESCRIPTION_FORM_FIELD = "description";
76    public static final String GROUP_FORM_FIELD = "group";
77    public static final String DOMAIN_FORM_FIELD = "domainName";
78    public static final String USERSPACE_PARAM = "userspace";
79    public static final String METADATA_EDITOR_PARAM = "mdEditor";
80    public static final String NUMBER_OF_RSSITEMS = "limit";
81    @InjectParam(value = "componentRegistryFactory")
82    private ComponentRegistryFactory componentRegistryFactory;
83    @InjectParam(value = "mdMarshaller")
84    private MDMarshaller marshaller;
85
86    /**
87     * Converts userspace boolean to component status. Temporary solution!!!
88     *
89     * TODO: Replace all calls to getRegistry that use this by calls using
90     * ComponentStatus
91     *
92     *
93     *
94     * @param userSpace
95     * @return
96     * @deprecated All calls should go directly to
97     * {@link #getRegistry(clarin.cmdi.componentregistry.ComponentStatus)}
98     */
99    @Deprecated
100    private static ComponentStatus getStatus(boolean userSpace) {
101        if (userSpace) {
102            return ComponentStatus.PRIVATE;
103        } else {
104            return ComponentStatus.PUBLISHED;
105        }
106    }
107
108    private ComponentRegistry getRegistry(ComponentStatus status) {
109        Principal userPrincipal = security.getUserPrincipal();
110        UserCredentials userCredentials = getUserCredentials(userPrincipal);
111        return getRegistry(status, null, userCredentials);
112    }
113
114    private ComponentRegistry getRegistry(ComponentStatus status, Owner owner, UserCredentials userCredentials) {
115        try {
116            return componentRegistryFactory.getComponentRegistry(status, owner, userCredentials);
117        } catch (UserUnauthorizedException uuEx) {
118            LOG.warn("Unauthorized access to {} registry by user {}", status, userCredentials);
119            LOG.debug("Details for unauthorized access", uuEx);
120            throw new WebApplicationException(uuEx, Status.UNAUTHORIZED);
121        }
122    }
123
124    /**
125     *
126     * @return Principal of current request
127     * @throws IllegalArgumentException If no user principal found
128     */
129    private Principal checkAndGetUserPrincipal() throws UserUnauthorizedException {
130        Principal principal = security.getUserPrincipal();
131        if (principal == null) {
132            throw new UserUnauthorizedException("no user principal found.");
133        }
134        return principal;
135    }
136
137    private UserCredentials getUserCredentials(Principal userPrincipal) {
138        UserCredentials userCredentials = null;
139        if (userPrincipal != null) {
140            userCredentials = new UserCredentials(userPrincipal);
141        }
142        return userCredentials;
143    }
144
145    @GET
146    @Path("/components")
147    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
148    public List<ComponentDescription> getRegisteredComponents(@QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) throws ComponentRegistryException {
149        long start = System.currentTimeMillis();
150        List<ComponentDescription> components = getRegistry(getStatus(userspace)).getComponentDescriptions();
151        LOG.debug("Releasing {} registered components into the world ({} millisecs)", components.size(), (System.currentTimeMillis() - start));
152        return components;
153    }
154
155    @GET
156    @Path("/profiles")
157    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
158    public List<ProfileDescription> getRegisteredProfiles(@QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace,
159            @QueryParam(METADATA_EDITOR_PARAM) @DefaultValue("false") boolean metadataEditor) throws ComponentRegistryException {
160        long start = System.currentTimeMillis();
161
162        List<ProfileDescription> profiles;
163        if (metadataEditor) {
164            profiles = getRegistry(getStatus(userspace)).getProfileDescriptionsForMetadaEditor();
165        } else {
166            profiles = getRegistry(getStatus(userspace)).getProfileDescriptions();
167        }
168
169        LOG.debug("Releasing {} registered profiles into the world ({} millisecs)", profiles.size(), (System.currentTimeMillis() - start));
170        return profiles;
171    }
172
173    @GET
174    @Path("/components/{componentId}")
175    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
176    public Response getRegisteredComponent(@PathParam("componentId") String componentId,
177            @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) throws ComponentRegistryException {
178        LOG.debug("Component with id: {} is requested.", componentId);
179        CMDComponentSpec mdComponent = getRegistry(getStatus(userspace)).getMDComponent(componentId);
180        if (mdComponent == null) {
181            return Response.status(Status.NOT_FOUND).build();
182        } else {
183            return Response.ok(mdComponent).build();
184        }
185    }
186
187    @GET
188    @Path("/components/{componentId}/{rawType}")
189    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML})
190    public Response getRegisteredComponentRawType(@PathParam("componentId") final String componentId, @PathParam("rawType") String rawType) {
191        LOG.debug("Component with id: {} and rawType: {} is requested.", componentId, rawType);
192        StreamingOutput result = null;
193        try {
194            final ComponentRegistry registry = findRegistry(componentId, new ComponentClosure());
195            if (registry == null) {
196                return Response.status(Status.NOT_FOUND).entity("Id: " + componentId + " is not registered, cannot create data.").build();
197            }
198            ComponentDescription desc = registry.getComponentDescription(componentId);
199            checkAndThrowDescription(desc, componentId);
200            String fileName = desc.getName() + "." + rawType;
201            if ("xml".equalsIgnoreCase(rawType)) {
202                result = new StreamingOutput() {
203                    @Override
204                    public void write(OutputStream output) throws IOException, WebApplicationException {
205                        try {
206                            registry.getMDComponentAsXml(componentId, output);
207                        } catch (ComponentRegistryException e) {
208                            LOG.warn("Could not retrieve component {}", componentId);
209                            LOG.debug("Details", e);
210                            throw new WebApplicationException(e, Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build());
211                        }
212                    }
213                };
214            } else if ("xsd".equalsIgnoreCase(rawType)) {
215                result = new StreamingOutput() {
216                    @Override
217                    public void write(OutputStream output) throws IOException, WebApplicationException {
218                        try {
219                            registry.getMDComponentAsXsd(componentId, output);
220                        } catch (ComponentRegistryException e) {
221                            LOG.warn("Could not retrieve component {}", componentId);
222                            LOG.debug("Details", e);
223                            throw new WebApplicationException(e, Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build());
224                        }
225
226                    }
227                };
228            } else {
229                throw new WebApplicationException(Response.serverError().entity(
230                        "unsupported rawType: " + rawType + " (only xml or xsd are supported)").build());
231            }
232            return createDownloadResponse(result, fileName);
233        } catch (ComponentRegistryException e) {
234            LOG.warn("Could not retrieve component {}", componentId);
235            LOG.debug("Details", e);
236            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build();
237        }
238    }
239
240    public ComponentRegistry findRegistry(String id, RegistryClosure<? extends AbstractDescription> clos) throws ComponentRegistryException {
241        AbstractDescription desc = null;
242        ComponentRegistry result = getRegistry(getStatus(false));
243        desc = clos.getDescription(result, id);
244        if (desc == null) {
245            List<ComponentRegistry> userRegs = componentRegistryFactory.getAllUserRegistries();
246            for (ComponentRegistry reg : userRegs) {
247                desc = clos.getDescription(reg, id);
248                if (desc != null) {
249                    result = reg;
250                    break;
251                }
252            }
253        }
254        return result;
255    }
256
257    @GET
258    @Path("/profiles/{profileId}")
259    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
260    public Response getRegisteredProfile(@PathParam("profileId") String profileId,
261            @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) throws ComponentRegistryException {
262        LOG.debug("Profile with id {} is requested.", profileId);
263        CMDComponentSpec mdProfile = getRegistry(getStatus(userspace)).getMDProfile(profileId);
264        if (mdProfile == null) {
265            return Response.status(Status.NOT_FOUND).build();
266        } else {
267            return Response.ok(mdProfile).build();
268        }
269    }
270
271    @GET
272    @Path("/components/usage/{componentId}")
273    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
274    public List<AbstractDescription> getComponentUsage(@PathParam("componentId") String componentId, @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) throws ComponentRegistryException {
275        try {
276            final long start = System.currentTimeMillis();
277            ComponentRegistry registry = getRegistry(getStatus(userspace));
278            List<ComponentDescription> components = registry.getUsageInComponents(componentId);
279            List<ProfileDescription> profiles = registry.getUsageInProfiles(componentId);
280
281            LOG.debug("Found {} components and {} profiles that use component {} ({} millisecs)",
282                    components.size(), profiles.size(), componentId, (System.currentTimeMillis() - start));
283
284            List<AbstractDescription> usages = new ArrayList<AbstractDescription>(components.size() + profiles.size());
285            usages.addAll(components);
286            usages.addAll(profiles);
287
288            return usages;
289        } catch (ComponentRegistryException e) {
290            LOG.warn("Could not retrieve profile usage {}", componentId);
291            LOG.debug("Details", e);
292            throw e;
293        }
294    }
295
296    @GET
297    @Path("/profiles/{profileId}/comments")
298    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
299    public List<Comment> getCommentsFromProfile(@PathParam("profileId") String profileId, @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) throws ComponentRegistryException {
300        long start = System.currentTimeMillis();
301        final Principal principal = security.getUserPrincipal();
302        List<Comment> comments = getRegistry(getStatus(userspace)).getCommentsInProfile(profileId, principal);
303        LOG.debug("Releasing {} registered comments in profile into the world ({} millisecs)", comments.size(), (System.currentTimeMillis() - start));
304        return comments;
305    }
306
307    @GET
308    @Path("/components/{componentId}/comments")
309    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
310    public List<Comment> getCommentsFromComponent(@PathParam("componentId") String componentId, @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) throws ComponentRegistryException {
311        long start = System.currentTimeMillis();
312        final Principal principal = security.getUserPrincipal();
313        List<Comment> comments = getRegistry(getStatus(userspace)).getCommentsInComponent(componentId, principal);
314        LOG.debug("Releasing {} registered comments in Component into the world ({} millisecs)", comments.size(), (System.currentTimeMillis() - start));
315        return comments;
316    }
317
318    @GET
319    @Path("/profiles/{profileId}/comments/{commentId}")
320    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
321    public Comment getSpecifiedCommentFromProfile(@PathParam("profileId") String profileId, @PathParam("commentId") String commentId, @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) throws ComponentRegistryException {
322        LOG.debug("Comments of profile with id {} are requested.", commentId);
323        final Principal principal = security.getUserPrincipal();
324        return getRegistry(getStatus(userspace)).getSpecifiedCommentInProfile(profileId, commentId, principal);
325    }
326
327    @GET
328    @Path("/components/{componentId}/comments/{commentId}")
329    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
330    public Comment getSpecifiedCommentFromComponent(@PathParam("componentId") String componentId, @PathParam("commentId") String commentId, @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) throws ComponentRegistryException {
331        LOG.debug("Comments of component with id {} are requested.", commentId);
332        final Principal principal = security.getUserPrincipal();
333        return getRegistry(getStatus(userspace)).getSpecifiedCommentInComponent(componentId, commentId, principal);
334    }
335
336    /**
337     *
338     * Purely helper method for my front-end (FLEX) which only does post/get
339     * requests. The query param is checked and the "proper" method is called.
340     *
341     * @param profileId
342     * @param method
343     * @return
344     */
345    @POST
346    @Path("/profiles/{profileId}")
347    public Response manipulateRegisteredProfile(@PathParam("profileId") String profileId, @FormParam("method") String method,
348            @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) {
349        if ("delete".equalsIgnoreCase(method)) {
350            return deleteRegisteredProfile(profileId, userspace);
351        } else {
352            return Response.ok().build();
353        }
354    }
355
356    @POST
357    @Path("/profiles/{profileId}/comments/{commentId}")
358    public Response manipulateCommentFromProfile(@PathParam("profileId") String profileId, @PathParam("commentId") String commentId, @FormParam("method") String method,
359            @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) {
360        if ("delete".equalsIgnoreCase(method)) {
361            return deleteCommentFromProfile(profileId, commentId, userspace);
362        } else {
363            return Response.ok().build();
364        }
365    }
366
367    @POST
368    @Path("/components/{componentId}/comments/{commentId}")
369    public Response manipulateCommentFromComponent(@PathParam("componentId") String componentId, @PathParam("commentId") String commentId, @FormParam("method") String method,
370            @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) {
371        if ("delete".equalsIgnoreCase(method)) {
372            return deleteCommentFromComponent(componentId, commentId, userspace);
373        } else {
374            return Response.ok().build();
375        }
376    }
377
378    @POST
379    @Path("/profiles/{profileId}/publish")
380    @Consumes("multipart/form-data")
381    public Response publishRegisteredProfile(@PathParam("profileId") String profileId, @FormDataParam(DATA_FORM_FIELD) InputStream input,
382            @FormDataParam(NAME_FORM_FIELD) String name, @FormDataParam(DESCRIPTION_FORM_FIELD) String description,
383            @FormDataParam(GROUP_FORM_FIELD) String group, @FormDataParam(DOMAIN_FORM_FIELD) String domainName) {
384        try {
385            Principal principal = checkAndGetUserPrincipal();
386            ProfileDescription desc = getRegistry(getStatus(true)).getProfileDescription(profileId);
387            if (desc != null) {
388                updateDescription(desc, name, description, domainName, group);
389                return register(input, desc, getUserCredentials(principal), true, new PublishAction(principal));
390            } else {
391                LOG.error("Update of nonexistent profile {} failed.", profileId);
392                return Response.serverError().entity("Invalid id, cannot update nonexistent profile").build();
393            }
394        } catch (ComponentRegistryException e) {
395            LOG.warn("Could not retrieve profile {}", profileId);
396            LOG.debug("Details", e);
397            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build();
398        } catch (UserUnauthorizedException ex) {
399            return Response.status(Status.UNAUTHORIZED).entity(ex.getMessage()).build();
400        }
401    }
402
403    @POST
404    @Path("/profiles/{profileId}/update")
405    @Consumes("multipart/form-data")
406    public Response updateRegisteredProfile(@PathParam("profileId") String profileId,
407            @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace, @FormDataParam(DATA_FORM_FIELD) InputStream input,
408            @FormDataParam(NAME_FORM_FIELD) String name, @FormDataParam(DESCRIPTION_FORM_FIELD) String description,
409            @FormDataParam(GROUP_FORM_FIELD) String group, @FormDataParam(DOMAIN_FORM_FIELD) String domainName) {
410        try {
411            Principal principal = checkAndGetUserPrincipal();
412            UserCredentials userCredentials = getUserCredentials(principal);
413            ProfileDescription desc = getRegistry(getStatus(userspace)).getProfileDescription(profileId);
414            if (desc != null) {
415                updateDescription(desc, name, description, domainName, group);
416                return register(input, desc, userCredentials, userspace, new UpdateAction(principal));
417            } else {
418                LOG.error("Update of nonexistent id (" + profileId + ") failed.");
419                return Response.serverError().entity("Invalid id, cannot update nonexistent profile").build();
420            }
421        } catch (ComponentRegistryException e) {
422            LOG.warn("Could not retrieve profile {}", profileId);
423            LOG.debug("Details", e);
424            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build();
425        } catch (UserUnauthorizedException ex) {
426            return Response.status(Status.UNAUTHORIZED).entity(ex.getMessage()).build();
427        }
428
429    }
430
431    /**
432     *
433     * Purely helper method for my front-end (FLEX) which van only do post/get
434     * requests. The query param is checked and the "proper" method is called.
435     *
436     * @param componentId
437     * @param method
438     * @return
439     */
440    @POST
441    @Path("/components/{componentId}")
442    public Response manipulateRegisteredComponent(@PathParam("componentId") String componentId, @FormParam("method") String method,
443            @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) {
444        if ("delete".equalsIgnoreCase(method)) {
445            return deleteRegisteredComponent(componentId, userspace);
446        } else {
447            return Response.ok().build();
448        }
449    }
450
451    @POST
452    @Path("/components/{componentId}/publish")
453    @Consumes("multipart/form-data")
454    public Response publishRegisteredComponent(@PathParam("componentId") String componentId,
455            @FormDataParam(DATA_FORM_FIELD) InputStream input, @FormDataParam(NAME_FORM_FIELD) String name,
456            @FormDataParam(DESCRIPTION_FORM_FIELD) String description, @FormDataParam(GROUP_FORM_FIELD) String group,
457            @FormDataParam(DOMAIN_FORM_FIELD) String domainName) {
458        try {
459            Principal principal = checkAndGetUserPrincipal();
460            // TODO: Get status from parameter
461            ComponentDescription desc = getRegistry(getStatus(true)).getComponentDescription(componentId);
462            if (desc != null) {
463                updateDescription(desc, name, description, domainName, group);
464                return register(input, desc, getUserCredentials(principal), true, new PublishAction(principal));
465            } else {
466                LOG.error("Update of nonexistent id (" + componentId + ") failed.");
467                return Response.serverError().entity("Invalid id, cannot update nonexistent profile").build();
468            }
469        } catch (ComponentRegistryException e) {
470            LOG.warn("Could not retrieve component {}", componentId);
471            LOG.debug("Details", e);
472            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build();
473        } catch (UserUnauthorizedException ex) {
474            return Response.status(Status.UNAUTHORIZED).entity(ex.getMessage()).build();
475        }
476    }
477
478    @POST
479    @Path("/components/{componentId}/update")
480    @Consumes("multipart/form-data")
481    public Response updateRegisteredComponent(@PathParam("componentId") String componentId,
482            @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace, @FormDataParam(DATA_FORM_FIELD) InputStream input,
483            @FormDataParam(NAME_FORM_FIELD) String name, @FormDataParam(DESCRIPTION_FORM_FIELD) String description,
484            @FormDataParam(GROUP_FORM_FIELD) String group, @FormDataParam(DOMAIN_FORM_FIELD) String domainName) {
485        try {
486            Principal principal = checkAndGetUserPrincipal();
487            ComponentDescription desc = getRegistry(getStatus(userspace)).getComponentDescription(componentId);
488            if (desc != null) {
489                updateDescription(desc, name, description, domainName, group);
490                return register(input, desc, getUserCredentials(principal), userspace, new UpdateAction(principal));
491            } else {
492                LOG.error("Update of nonexistent id (" + componentId + ") failed.");
493                return Response.serverError().entity("Invalid id, cannot update nonexistent component").build();
494            }
495        } catch (ComponentRegistryException e) {
496            LOG.warn("Could not retrieve component {}", componentId);
497            LOG.debug("Details", e);
498            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build();
499        } catch (UserUnauthorizedException ex) {
500            return Response.status(Status.UNAUTHORIZED).entity(ex.getMessage()).build();
501        }
502    }
503
504    private void updateDescription(AbstractDescription desc, String name, String description, String domainName, String group) {
505        desc.setName(name);
506        desc.setDescription(description);
507        desc.setDomainName(domainName);
508        desc.setGroupName(group);
509        desc.setRegistrationDate(AbstractDescription.createNewDate());
510    }
511
512    @DELETE
513    @Path("/components/{componentId}")
514    public Response deleteRegisteredComponent(@PathParam("componentId") String componentId,
515            @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) {
516        try {
517            Principal principal = checkAndGetUserPrincipal();
518            ComponentRegistry registry = getRegistry(getStatus(userspace));
519            LOG.debug("Component with id {} set for deletion.", componentId);
520            registry.deleteMDComponent(componentId, principal, false);
521        } catch (DeleteFailedException e) {
522            LOG.info("Component with id {} deletion failed. Reason: {}", componentId, e.getMessage());
523            LOG.debug("Deletion failure details:", e);
524            return Response.status(Status.FORBIDDEN).entity("" + e.getMessage()).build();
525        } catch (ComponentRegistryException e) {
526            LOG.warn("Component with id " + componentId + " deletion failed.", e);
527            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build();
528        } catch (IOException e) {
529            LOG.error("Component with id " + componentId + " deletion failed.", e);
530            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build();
531        } catch (UserUnauthorizedException e) {
532            LOG.info("Component with id {} deletion failed: {}", componentId, e.getMessage());
533            LOG.debug("Deletion failure details:", e);
534            return Response.serverError().status(Status.UNAUTHORIZED).entity("" + e.getMessage()).build();
535        }
536        LOG.info("Component with id: {} deleted.", componentId);
537        return Response.ok().build();
538    }
539
540    @DELETE
541    @Path("/profiles/{profileId}")
542    public Response deleteRegisteredProfile(@PathParam("profileId") String profileId,
543            @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) {
544        try {
545            Principal principal = checkAndGetUserPrincipal();
546            LOG.debug("Profile with id: {} set for deletion.", profileId);
547            getRegistry(getStatus(userspace)).deleteMDProfile(profileId, principal);
548        } catch (DeleteFailedException e) {
549            LOG.info("Profile with id: {} deletion failed: {}", profileId, e.getMessage());
550            LOG.debug("Deletion failure details:", e);
551            return Response.serverError().status(Status.FORBIDDEN).entity("" + e.getMessage()).build();
552        } catch (ComponentRegistryException e) {
553            LOG.warn("Could not retrieve component", e);
554            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build();
555        } catch (IOException e) {
556            LOG.error("Profile with id: " + profileId + " deletion failed.", e);
557            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build();
558        } catch (UserUnauthorizedException e) {
559            LOG.info("Profile with id: {} deletion failed: {}", profileId, e.getMessage());
560            LOG.debug("Deletion failure details:", e);
561            return Response.serverError().status(Status.UNAUTHORIZED).entity("" + e.getMessage()).build();
562        }
563        LOG.info("Profile with id: {} deleted.", profileId);
564        return Response.ok().build();
565    }
566
567    @DELETE
568    @Path("/profiles/{profileId}/comments/{commentId}")
569    public Response deleteCommentFromProfile(@PathParam("profileId") String profileId, @PathParam("commentId") String commentId,
570            @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) {
571        try {
572            final Principal principal = checkAndGetUserPrincipal();
573            final ComponentRegistry registry = getRegistry(getStatus(userspace));
574            final Comment comment = registry.getSpecifiedCommentInProfile(profileId, commentId, principal);
575            if (comment != null && profileId.equals(comment.getProfileDescriptionId())) {
576                LOG.debug("Comment with id: {} set for deletion.", commentId);
577                registry.deleteComment(commentId, principal);
578            } else {
579                throw new ComponentRegistryException("Comment not found for specified profile");
580            }
581        } catch (DeleteFailedException e) {
582            LOG.info("Comment with id: {} deletion failed: {}", commentId, e.getMessage());
583            LOG.debug("Deletion failure details:", e);
584            return Response.serverError().status(Status.FORBIDDEN).entity("" + e.getMessage()).build();
585        } catch (ComponentRegistryException e) {
586            LOG.info("Could not retrieve component", e);
587            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build();
588        } catch (IOException e) {
589            LOG.error("Comment with id: " + commentId + " deletion failed.", e);
590            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build();
591        } catch (UserUnauthorizedException e) {
592            LOG.info("Comment with id: {} deletion failed: {}", commentId, e.getMessage());
593            LOG.debug("Deletion failure details:", e);
594            return Response.serverError().status(Status.UNAUTHORIZED).entity("" + e.getMessage()).build();
595        }
596        LOG.info("Comment with id: {} deleted.", commentId);
597        return Response.ok().build();
598    }
599
600    @DELETE
601    @Path("/components/{componentId}/comments/{commentId}")
602    public Response deleteCommentFromComponent(@PathParam("componentId") String componentId, @PathParam("commentId") String commentId,
603            @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) {
604        try {
605            final Principal principal = checkAndGetUserPrincipal();
606            final ComponentRegistry registry = getRegistry(getStatus(userspace));
607            final Comment comment = registry.getSpecifiedCommentInComponent(componentId, commentId, principal);
608            if (comment != null && componentId.equals(comment.getComponentDescriptionId())) {
609                LOG.debug("Comment with id: {} set for deletion.", commentId);
610                registry.deleteComment(commentId, principal);
611            } else {
612                throw new ComponentRegistryException("Comment not found for specified component");
613            }
614        } catch (DeleteFailedException e) {
615            LOG.info("Comment with id: {} deletion failed: {}", commentId, e.getMessage());
616            LOG.debug("Deletion failure details:", e);
617            return Response.serverError().status(Status.FORBIDDEN).entity("" + e.getMessage()).build();
618        } catch (ComponentRegistryException e) {
619            LOG.info("Could not retrieve component", e);
620            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build();
621        } catch (IOException e) {
622            LOG.error("Comment with id: " + commentId + " deletion failed.", e);
623            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build();
624        } catch (UserUnauthorizedException e) {
625            LOG.info("Comment with id: {} deletion failed: {}", commentId, e.getMessage());
626            LOG.debug("Deletion failure details:", e);
627            return Response.serverError().status(Status.UNAUTHORIZED).entity("" + e.getMessage()).build();
628        }
629        LOG.info("Comment with id: {} deleted.", commentId);
630        return Response.ok().build();
631    }
632
633    @GET
634    @Path("/profiles/{profileId}/{rawType}")
635    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML})
636    public Response getRegisteredProfileRawType(@PathParam("profileId") final String profileId, @PathParam("rawType") String rawType) {
637        LOG.debug("Profile with id {} and rawType {} is requested.", profileId, rawType);
638        StreamingOutput result = null;
639        try {
640            final ComponentRegistry registry = findRegistry(profileId, new ProfileClosure());
641            if (registry == null) {
642                return Response.status(Status.NOT_FOUND).entity("Id: " + profileId + " is not registered, cannot create data.").build();
643            }
644            ProfileDescription desc = registry.getProfileDescription(profileId);
645            checkAndThrowDescription(desc, profileId);
646            String fileName = desc.getName() + "." + rawType;
647
648            if ("xml".equalsIgnoreCase(rawType)) {
649                result = new StreamingOutput() {
650                    @Override
651                    public void write(OutputStream output) throws IOException, WebApplicationException {
652                        try {
653                            registry.getMDProfileAsXml(profileId, output);
654                        } catch (ComponentRegistryException e) {
655                            LOG.warn("Could not retrieve component {}", profileId);
656                            LOG.debug("Details", e);
657                            throw new WebApplicationException(e, Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build());
658                        }
659                    }
660                };
661            } else if ("xsd".equalsIgnoreCase(rawType)) {
662                result = new StreamingOutput() {
663                    @Override
664                    public void write(OutputStream output) throws IOException, WebApplicationException {
665                        try {
666                            registry.getMDProfileAsXsd(profileId, output);
667                        } catch (ComponentRegistryException e) {
668                            LOG.warn("Could not retrieve component {}", profileId);
669                            LOG.debug("Details", e);
670                            throw new WebApplicationException(e, Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build());
671                        }
672                    }
673                };
674            } else {
675                throw new WebApplicationException(Response.serverError().entity(
676                        "unsupported rawType: " + rawType + " (only xml or xsd are supported)").build());
677            }
678            return createDownloadResponse(result, fileName);
679        } catch (ComponentRegistryException e) {
680            LOG.warn("Could not retrieve component {}", profileId);
681            LOG.debug("Details", e);
682            return Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build();
683        }
684    }
685
686    private void checkAndThrowDescription(AbstractDescription desc, String id) {
687        if (desc == null) {
688            throw new WebApplicationException(Response.serverError().entity("Incorrect id:" + id + "cannot handle request").build());
689        }
690    }
691
692    private Response createDownloadResponse(StreamingOutput result, String fileName) {
693        //Making response so it triggers browsers native save as dialog.
694        Response response = Response.ok().type("application/x-download").header("Content-Disposition",
695                "attachment; filename=\"" + fileName + "\"").entity(result).build();
696        return response;
697
698    }
699
700    @POST
701    @Path("/profiles")
702    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
703    @Consumes("multipart/form-data")
704    public Response registerProfile(@FormDataParam(DATA_FORM_FIELD) InputStream input, @FormDataParam(NAME_FORM_FIELD) String name,
705            @FormDataParam(DESCRIPTION_FORM_FIELD) String description, @FormDataParam(GROUP_FORM_FIELD) String group, @FormDataParam(DOMAIN_FORM_FIELD) String domainName,
706            @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) {
707        try {
708            Principal principal = checkAndGetUserPrincipal();
709            UserCredentials userCredentials = getUserCredentials(principal);
710            ProfileDescription desc = createNewProfileDescription();
711            desc.setCreatorName(userCredentials.getDisplayName());
712            desc.setUserId(userCredentials.getPrincipalName()); // Hash used to be created here, now Id is constructed by impl
713            desc.setName(name);
714            desc.setDescription(description);
715            desc.setGroupName(group);
716            desc.setDomainName(domainName);
717            LOG.debug("Trying to register Profile: {}", desc);
718            return register(input, desc, userCredentials, userspace, new NewAction());
719        } catch (UserUnauthorizedException ex) {
720            return Response.status(Status.UNAUTHORIZED).entity(ex.getMessage()).build();
721        }
722    }
723
724    @POST
725    @Path("/components")
726    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
727    @Consumes("multipart/form-data")
728    public Response registerComponent(@FormDataParam(DATA_FORM_FIELD) InputStream input, @FormDataParam(NAME_FORM_FIELD) String name,
729            @FormDataParam(DESCRIPTION_FORM_FIELD) String description, @FormDataParam(GROUP_FORM_FIELD) String group,
730            @FormDataParam(DOMAIN_FORM_FIELD) String domainName, @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) {
731        try {
732            Principal principal = checkAndGetUserPrincipal();
733            UserCredentials userCredentials = getUserCredentials(principal);
734            ComponentDescription desc = createNewComponentDescription();
735            desc.setCreatorName(userCredentials.getDisplayName());
736            desc.setUserId(userCredentials.getPrincipalName()); // Hash used to be created here, now Id is constructed by impl
737            desc.setName(name);
738            desc.setDescription(description);
739            desc.setGroupName(group);
740            desc.setDomainName(domainName);
741            LOG.debug("Trying to register Component: {}", desc);
742            return register(input, desc, userCredentials, userspace, new NewAction());
743        } catch (UserUnauthorizedException ex) {
744            return Response.status(Status.UNAUTHORIZED).entity(ex.getMessage()).build();
745        }
746    }
747
748    @POST
749    @Path("/components/{componentId}/comments")
750    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
751    @Consumes("multipart/form-data")
752    public Response registerCommentInComponent(@FormDataParam(DATA_FORM_FIELD) InputStream input,
753            @PathParam("componentId") String componentId, @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) throws ComponentRegistryException {
754        try {
755            Principal principal = checkAndGetUserPrincipal();
756            UserCredentials userCredentials = getUserCredentials(principal);
757            if (null == componentRegistryFactory.getOrCreateUser(userCredentials)) {
758                throw new UserUnauthorizedException("Cannot materialize authenticated user");
759            }
760            // TODO: Add user/group param
761            ComponentRegistry registry = getRegistry(getStatus(userspace), null, userCredentials);
762            ComponentDescription description = registry.getComponentDescription(componentId);
763            if (description != null) {
764                LOG.debug("Trying to register comment to {}", componentId);
765                return registerComment(input, registry, userspace, description, principal, userCredentials);
766            } else {
767                LOG.warn("Attempt to post comment on nonexistent component id {} failed.", componentId);
768                return Response.serverError().entity("Invalid id, cannot comment on nonexistent component").build();
769            }
770        } catch (UserUnauthorizedException ex) {
771            return Response.status(Status.UNAUTHORIZED).entity(ex.getMessage()).build();
772        }
773    }
774
775    @POST
776    @Path("/profiles/{profileId}/comments")
777    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
778    @Consumes("multipart/form-data")
779    public Response registerCommentInProfile(@FormDataParam(DATA_FORM_FIELD) InputStream input,
780            @PathParam("profileId") String profileId, @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) throws ComponentRegistryException {
781        try {
782            Principal principal = checkAndGetUserPrincipal();
783            UserCredentials userCredentials = getUserCredentials(principal);
784            if (null == componentRegistryFactory.getOrCreateUser(userCredentials)) {
785                throw new UserUnauthorizedException("Cannot materialize authenticated user");
786            }
787            // TODO: Add user/group param
788            ComponentRegistry registry = getRegistry(getStatus(userspace), null, userCredentials);
789            ProfileDescription description = registry.getProfileDescription(profileId);
790            if (description != null) {
791                LOG.debug("Trying to register comment to {}", profileId);
792                return registerComment(input, registry, userspace, description, principal, userCredentials);
793            } else {
794                LOG.warn("Attempt to post comment on nonexistent profile id {} failed.", profileId);
795                return Response.serverError().entity("Invalid id, cannot comment on nonexistent profile").build();
796            }
797        } catch (UserUnauthorizedException ex) {
798            return Response.status(Status.UNAUTHORIZED).entity(ex.getMessage()).build();
799        }
800    }
801
802    @GET
803    @Path("/pingSession")
804    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
805    public Response pingSession() {
806        boolean stillActive = false;
807        Principal userPrincipal = security.getUserPrincipal();
808        if (LOG.isInfoEnabled()) {
809            LOG.debug("ping by <{}>", (userPrincipal == null ? "unauthorized user" : userPrincipal.getName()));
810        }
811        if (request != null) {
812            if (userPrincipal != null && !ComponentRegistryFactory.ANONYMOUS_USER.equals(userPrincipal.getName())) {
813                stillActive = !((HttpServletRequest) request).getSession().isNew();
814            }
815        }
816        return Response.ok().entity(String.format("<session stillActive=\"%s\"/>", stillActive)).build();
817    }
818
819    private Response register(InputStream input, AbstractDescription desc, UserCredentials userCredentials, boolean userspace,
820            RegisterAction action) {
821        try {
822            // TODO: Add user/group param
823            ComponentRegistry registry = getRegistry(getStatus(userspace), null, userCredentials);
824            DescriptionValidator descriptionValidator = new DescriptionValidator(desc);
825            MDValidator validator = new MDValidator(input, desc, registry, getRegistry(getStatus(true)), componentRegistryFactory.getPublicRegistry(), marshaller);
826            RegisterResponse response = new RegisterResponse();
827            response.setIsInUserSpace(userspace);
828            validate(response, descriptionValidator, validator);
829            if (response.getErrors().isEmpty()) {
830
831                CMDComponentSpec spec = validator.getCMDComponentSpec();
832
833                // removing filename from spec before it gets extended. recursion over all the components
834                setFileNamesFromListToNull(spec.getCMDComponent());
835
836                try {
837                    checkForRecursion(validator, registry, desc);
838
839                    // Add profile
840                    int returnCode = action.execute(desc, spec, response, registry);
841                    if (returnCode == 0) {
842                        response.setRegistered(true);
843                        response.setDescription(desc);
844                    } else {
845                        response.setRegistered(false);
846                        response.addError("Unable to register at this moment. Internal server error.");
847                    }
848                } catch (ComponentRegistryException ex) {
849                    // Recursion detected
850                    response.setRegistered(false);
851                    response.addError("Error while expanding specification. " + ex.getMessage());
852                }
853            } else {
854                LOG.warn("Registration failed with validation errors: {}", Arrays.toString(response.getErrors().toArray()));
855                response.setRegistered(false);
856            }
857            LOG.info("Registered new {} {}", desc.isProfile() ? "profile" : "component", desc);
858            response.setIsProfile(desc.isProfile());
859            return Response.ok(response).build();
860        } finally {
861            try {
862                input.close();//either we read the input or there was an exception, we need to close it.
863            } catch (IOException e) {
864                LOG.error("Error when closing inputstream: ", e);
865            }
866        }
867    }
868
869    /**
870     *
871     * @param validator
872     * @param registry
873     * @param desc
874     * @throws ComponentRegistryException if recursion is detected or something goes wrong while trying to detect recursion
875     */
876    private void checkForRecursion(MDValidator validator, ComponentRegistry registry, AbstractDescription desc) throws ComponentRegistryException {
877        try {
878            // Expand to check for recursion. Operate on copy so that original does not get expanded.
879            final CMDComponentSpec specCopy = validator.getCopyOfCMDComponentSpec();
880            // In case of recursion, the following will throw a ComponentRegistryException
881            registry.getExpander().expandNestedComponent(specCopy.getCMDComponent(), desc.getId());
882        } catch (JAXBException ex) {
883            throw new ComponentRegistryException("Unmarshalling failed while preparing recursion detection", ex);
884        }
885    }
886
887    private Response registerComment(InputStream input, ComponentRegistry registry, boolean userspace,
888            AbstractDescription description, Principal principal, UserCredentials userCredentials) {
889        try {
890            CommentValidator validator = new CommentValidator(input, description, marshaller);
891            CommentResponse response = new CommentResponse();
892            response.setIsInUserSpace(userspace);
893            validateComment(response, validator);
894            if (response.getErrors().isEmpty()) {
895                Comment com = validator.getCommentSpec();
896                //int returnCode = action.executeComment(com, response, registry, principal.getName());
897
898                // If user name is left empty, fill it using the user's display name
899                if (null == com.getUserName() || "".equals(com.getUserName())) {
900                    if (userCredentials != null) {
901                        com.setUserName(userCredentials.getDisplayName());
902                    } else {
903                        com.setUserName(principal.getName());
904                    }
905                }
906
907                int returnCode = registry.registerComment(com, principal.getName());
908                if (returnCode == 0) {
909                    response.setRegistered(true);
910                    response.setComment(com);
911                } else {
912                    response.setRegistered(false);
913                    response.addError("Unable to post at this moment. Internal server error.");
914                }
915                if (com.getComponentDescriptionId() != null) {
916                    LOG.info("Posted new comment on component {}", com.getComponentDescriptionId());
917                } else {
918                    LOG.info("Posted new comment on profile {}", com.getProfileDescriptionId());
919                }
920            } else {
921                LOG.warn("Posting of comment failed with validation errors: {}", Arrays.toString(response.getErrors().toArray()));
922                response.setRegistered(false);
923            }
924            return Response.ok(response).build();
925        } catch (ComponentRegistryException ex) {
926            LOG.error("Error while inserting comment: ", ex);
927            return Response.serverError().entity(ex.getMessage()).build();
928        } finally {
929            try {
930                input.close();//either we read the input or there was an exception, we need to close it.
931            } catch (IOException e) {
932                LOG.error("Error when closing inputstream: ", e);
933                return Response.serverError().build();
934            }
935        }
936    }
937
938    private ComponentDescription createNewComponentDescription() {
939        ComponentDescription desc = ComponentDescription.createNewDescription();
940        desc.setHref(createXlink(desc.getId()));
941        return desc;
942    }
943
944    private ProfileDescription createNewProfileDescription() {
945        ProfileDescription desc = ProfileDescription.createNewDescription();
946        desc.setHref(createXlink(desc.getId()));
947        return desc;
948    }
949
950    private String createXlink(String id) {
951        URI uri = uriInfo.getRequestUriBuilder().path(id).build();
952        return uri.toString();
953    }
954
955    /**
956     *
957     * @return The application's base URI as configured in the
958     * {@link #APPLICATION_BASE_URL_PARAM} context parameter. If correctly
959     * configured, it should look something like
960     * "http://catalog.clarin.eu/ds/ComponentRegistry". <em>Be aware that this
961     * can also be null if configured incorrectly!</em>
962     *
963     * @see #APPLICATION_BASE_URL_PARAM
964     */
965    private String getApplicationBaseURI() {
966        return servletContext.getInitParameter(APPLICATION_BASE_URL_PARAM);
967    }
968
969    private void validate(RegisterResponse response, Validator... validators) {
970        for (Validator validator : validators) {
971            if (!validator.validate()) {
972                for (String error : validator.getErrorMessages()) {
973                    response.addError(error);
974                }
975            }
976        }
977    }
978
979    private void validateComment(CommentResponse response, Validator... validators) {
980        for (Validator validator : validators) {
981            if (!validator.validate()) {
982                for (String error : validator.getErrorMessages()) {
983                    response.addError(error);
984                }
985            }
986        }
987    }
988
989    /**
990     * @param componentRegistryFactory the componentRegistryFactory to set
991     */
992    public void setComponentRegistryFactory(ComponentRegistryFactory componentRegistryFactory) {
993        this.componentRegistryFactory = componentRegistryFactory;
994    }
995
996    /**
997     *
998     * @param listofcomponents a list of components whose file-names and whose childrens' filenames are to be set to null
999     */
1000    protected void setFileNamesFromListToNull(List<CMDComponentType> listofcomponents) {
1001
1002        for (CMDComponentType currentcomponent : listofcomponents) {
1003            setFileNamesToNullCurrent(currentcomponent);
1004        }
1005
1006    }
1007
1008    /**
1009     *
1010     * @param currentcomponent a component whose file-name and whose children filenames are to be set to null
1011     */
1012    protected void setFileNamesToNullCurrent(CMDComponentType currentcomponent) {
1013        currentcomponent.setFilename(null);
1014        setFileNamesFromListToNull(currentcomponent.getCMDComponent());
1015    }
1016
1017    /**
1018     *
1019     * @param userspace if "true" then profiles and components from the user's workspace, otherwise -- public
1020     * @param limit the number of items to be displayed
1021     * @return rss for the components in the database to which we are currently connected
1022     * @throws ComponentRegistryException
1023     * @throws ParseException
1024     */
1025    @GET
1026    @Path("/components/rss")
1027    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
1028    public Rss getRssComponent(@QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace, @QueryParam(NUMBER_OF_RSSITEMS) @DefaultValue("20") String limit) throws ComponentRegistryException, ParseException {
1029        final List<ComponentDescription> components = getRegistry(getStatus(userspace)).getComponentDescriptions();
1030        final RssCreatorDescriptions instance = new RssCreatorDescriptions(userspace, getApplicationBaseURI(), "components", Integer.parseInt(limit), components, AbstractDescription.COMPARE_ON_DATE);
1031        final Rss rss = instance.getRss();
1032        LOG.debug("Releasing RSS of {} most recently registered components", limit);
1033        return rss;
1034    }
1035
1036    /**
1037     *
1038     * @param userspace if "true" then profiles and components from the user's workspace, otherwise -- public
1039     * @param limit the number of items to be displayed
1040     * @return rss for the profiles in the database to which we are currently connected
1041     * @throws ComponentRegistryException
1042     * @throws ParseException
1043     */
1044    @GET
1045    @Path("/profiles/rss")
1046    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
1047    public Rss getRssProfile(@QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace, @QueryParam(NUMBER_OF_RSSITEMS) @DefaultValue("20") String limit) throws ComponentRegistryException, ParseException {
1048        final List<ProfileDescription> profiles = getRegistry(getStatus(userspace)).getProfileDescriptions();
1049        final RssCreatorDescriptions instance = new RssCreatorDescriptions(userspace, getApplicationBaseURI(), "profiles", Integer.parseInt(limit), profiles, AbstractDescription.COMPARE_ON_DATE);
1050        final Rss rss = instance.getRss();
1051        LOG.debug("Releasing RSS of {} most recently registered profiles", limit);
1052        return rss;
1053    }
1054
1055    /**
1056     *
1057     * @param profileId the Id of a profile whose comments are to be rss-ed
1058     * @param userspace if "true" then profiles and components from the user's workspace, otherwise -- public
1059     * @param limit the number of items to be displayed
1060     * @return rss of the comments for a chosen profile
1061     * @throws ComponentRegistryException
1062     * @throws IOException
1063     * @throws JAXBException
1064     * @throws ParseException
1065     */
1066    @GET
1067    @Path("/profiles/{profileId}/comments/rss")
1068    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
1069    public Rss getRssOfCommentsFromProfile(@PathParam("profileId") String profileId, @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace, @QueryParam(NUMBER_OF_RSSITEMS) @DefaultValue("20") String limit) throws ComponentRegistryException, IOException, JAXBException, ParseException {
1070        final Principal principal = security.getUserPrincipal();
1071        final List<Comment> comments = getRegistry(getStatus(userspace)).getCommentsInProfile(profileId, principal);
1072        final String profileName = getRegistry(getStatus(userspace)).getProfileDescription(profileId).getName();
1073        final RssCreatorComments instance = new RssCreatorComments(userspace, getApplicationBaseURI(), Integer.parseInt(limit), profileId, profileName, "profile", comments, Comment.COMPARE_ON_DATE);
1074        final Rss rss = instance.getRss();
1075        LOG.debug("Releasing RSS of {} most recent post on profile {}", limit, profileId);
1076        return rss;
1077    }
1078
1079    /**
1080     *
1081     * @param componentId the Id of a component whose comments are to be rss-ed
1082     * @param userspace if "true" then profiles and components from the user's workspace, otherwise -- public
1083     * @param limit the number of items to be displayed
1084     * @return rss of the comments for a chosen component
1085     * @throws ComponentRegistryException
1086     * @throws IOException
1087     * @throws JAXBException
1088     * @throws ParseException
1089     */
1090    @GET
1091    @Path("/components/{componentId}/comments/rss")
1092    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
1093    public Rss getRssOfCommentsFromComponent(@PathParam("componentId") String componentId, @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace, @QueryParam(NUMBER_OF_RSSITEMS) @DefaultValue("20") String limit) throws ComponentRegistryException, IOException, JAXBException, ParseException {
1094        final Principal principal = security.getUserPrincipal();
1095        final List<Comment> comments = getRegistry(getStatus(userspace)).getCommentsInComponent(componentId, principal);
1096        final String componentName = getRegistry(getStatus(userspace)).getComponentDescription(componentId).getName();
1097        final RssCreatorComments instance = new RssCreatorComments(userspace, getApplicationBaseURI(), Integer.parseInt(limit), componentId, componentName, "component", comments, Comment.COMPARE_ON_DATE);
1098        final Rss rss = instance.getRss();
1099        LOG.debug("Releasing RSS of {} most recent post on component {}", limit, componentId);
1100        return rss;
1101    }
1102
1103    @GET
1104    @Path("/AllowedTypes")
1105    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
1106    public AllowedAttributetypesXML getAllowedAttributeTypes() throws ComponentRegistryException, IOException, JAXBException, ParseException {
1107        return (new AllowedAttributetypesXML());
1108    }
1109}
Note: See TracBrowser for help on using the repository browser.