Ignore:
Timestamp:
08/20/13 15:32:37 (11 years ago)
Author:
George.Georgovassilis@mpi.nl
Message:

#360 Refactoring of transaction handling, tests and application context

File:
1 edited

Legend:

Unmodified
Added
Removed
  • ComponentRegistry/trunk/ComponentRegistry/src/main/java/clarin/cmdi/componentregistry/rest/ComponentRegistryRestService.java

    r3088 r3449  
    2222import clarin.cmdi.componentregistry.rss.RssCreatorComments;
    2323import clarin.cmdi.componentregistry.rss.RssCreatorDescriptions;
     24
    2425import com.sun.jersey.api.core.InjectParam;
    2526import com.sun.jersey.multipart.FormDataParam;
    26 import com.sun.jersey.spi.inject.Inject;
     27
    2728import java.io.IOException;
    2829import java.io.InputStream;
     
    3435import java.util.Arrays;
    3536import java.util.List;
     37
    3638import javax.servlet.ServletContext;
    3739import javax.servlet.http.HttpServletRequest;
     
    5557import javax.ws.rs.core.UriInfo;
    5658import javax.xml.bind.JAXBException;
     59
    5760import org.slf4j.Logger;
    5861import org.slf4j.LoggerFactory;
    59 
     62import org.springframework.stereotype.Component;
     63import org.springframework.stereotype.Service;
     64import org.springframework.transaction.annotation.Transactional;
     65
     66/**
     67 * Handles CRUD operations on {@link ComponentDescription}, {@link ProfileDescription} and {@link Comment}s
     68 * @author george.georgovassilis@mpi.nl
     69 *
     70 */
    6071@Path("/registry")
    61 public 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 {
     72@Service
     73public class ComponentRegistryRestService implements
     74                IComponentRegistryRestService {
     75
     76        private final static Logger LOG = LoggerFactory
     77                        .getLogger(IComponentRegistryRestService.class);
     78        @Context
     79        private UriInfo uriInfo;
     80        @Context
     81        private SecurityContext security;
     82        @Context
     83        private HttpServletRequest request;
     84        @Context
     85        private ServletContext servletContext;
     86        @InjectParam(value = "componentRegistryFactory")
     87        private ComponentRegistryFactory componentRegistryFactory;
     88        @InjectParam(value = "mdMarshaller")
     89        private MDMarshaller marshaller;
     90
     91        /**
     92         * Converts userspace boolean to component status. Temporary solution!!!
     93         *
     94         * TODO: Replace all calls to getRegistry that use this by calls using
     95         * ComponentStatus
     96         *
     97         *
     98         *
     99         * @param userSpace
     100         * @return
     101         * @deprecated All calls should go directly to
     102         *             {@link #getRegistry(clarin.cmdi.componentregistry.ComponentStatus)}
     103         */
     104        @Deprecated
     105        private static ComponentStatus getStatus(boolean userSpace) {
     106                if (userSpace) {
     107                        return ComponentStatus.PRIVATE;
     108                } else {
     109                        return ComponentStatus.PUBLISHED;
     110                }
     111        }
     112
     113        private ComponentRegistry getRegistry(ComponentStatus status) {
     114                Principal userPrincipal = security.getUserPrincipal();
     115                UserCredentials userCredentials = getUserCredentials(userPrincipal);
     116                return getRegistry(status, null, userCredentials);
     117        }
     118
     119        private ComponentRegistry getRegistry(ComponentStatus status, Owner owner,
     120                        UserCredentials userCredentials) {
     121                try {
     122                        return componentRegistryFactory.getComponentRegistry(status, owner,
     123                                        userCredentials);
     124                } catch (UserUnauthorizedException uuEx) {
     125                        LOG.warn("Unauthorized access to {} registry by user {}", status,
     126                                        userCredentials);
     127                        LOG.debug("Details for unauthorized access", uuEx);
     128                        throw new WebApplicationException(uuEx, Status.UNAUTHORIZED);
     129                }
     130        }
     131
     132        /**
     133         *
     134         * @return Principal of current request
     135         * @throws IllegalArgumentException
     136         *             If no user principal found
     137         */
     138        private Principal checkAndGetUserPrincipal()
     139                        throws UserUnauthorizedException {
     140                Principal principal = security.getUserPrincipal();
     141                if (principal == null) {
     142                        throw new UserUnauthorizedException("no user principal found.");
     143                }
     144                return principal;
     145        }
     146
     147        private UserCredentials getUserCredentials(Principal userPrincipal) {
     148                UserCredentials userCredentials = null;
     149                if (userPrincipal != null) {
     150                        userCredentials = new UserCredentials(userPrincipal);
     151                }
     152                return userCredentials;
     153        }
     154       
     155        @Override
     156        @GET
     157        @Path("/components")
     158        @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_XML,
     159                        MediaType.APPLICATION_JSON })
     160        public List<ComponentDescription> getRegisteredComponents(
     161                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace)
     162                        throws ComponentRegistryException {
     163                long start = System.currentTimeMillis();
     164                List<ComponentDescription> components = getRegistry(
     165                                getStatus(userspace)).getComponentDescriptions();
     166                LOG.debug(
     167                                "Releasing {} registered components into the world ({} millisecs)",
     168                                components.size(), (System.currentTimeMillis() - start));
     169                return components;
     170        }
     171
     172        @Override
     173        @GET
     174        @Path("/profiles")
     175        @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_XML,
     176                        MediaType.APPLICATION_JSON })
     177        public List<ProfileDescription> getRegisteredProfiles(
     178                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace,
     179                        @QueryParam(METADATA_EDITOR_PARAM) @DefaultValue("false") boolean metadataEditor)
     180                        throws ComponentRegistryException {
     181                long start = System.currentTimeMillis();
     182
     183                List<ProfileDescription> profiles;
     184                if (metadataEditor) {
     185                        profiles = getRegistry(getStatus(userspace))
     186                                        .getProfileDescriptionsForMetadaEditor();
     187                } else {
     188                        profiles = getRegistry(getStatus(userspace))
     189                                        .getProfileDescriptions();
     190                }
     191
     192                LOG.debug(
     193                                "Releasing {} registered profiles into the world ({} millisecs)",
     194                                profiles.size(), (System.currentTimeMillis() - start));
     195                return profiles;
     196        }
     197
     198        @Override
     199        @GET
     200        @Path("/components/{componentId}")
     201        @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_XML,
     202                        MediaType.APPLICATION_JSON })
     203        public Response getRegisteredComponent(
     204                        @PathParam("componentId") String componentId,
     205                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace)
     206                        throws ComponentRegistryException {
     207                LOG.debug("Component with id: {} is requested.", componentId);
     208                CMDComponentSpec mdComponent = getRegistry(getStatus(userspace))
     209                                .getMDComponent(componentId);
     210                if (mdComponent == null) {
     211                        return Response.status(Status.NOT_FOUND).build();
     212                } else {
     213                        return Response.ok(mdComponent).build();
     214                }
     215        }
     216
     217        @Override
     218        @GET
     219        @Path("/components/{componentId}/{rawType}")
     220        @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_XML })
     221        public Response getRegisteredComponentRawType(
     222                        @PathParam("componentId") final String componentId,
     223                        @PathParam("rawType") String rawType) {
     224                LOG.debug("Component with id: {} and rawType: {} is requested.",
     225                                componentId, rawType);
     226                StreamingOutput result = null;
     227                try {
     228                        final ComponentRegistry registry = findRegistry(componentId,
     229                                        new ComponentClosure());
     230                        if (registry == null) {
     231                                return Response
     232                                                .status(Status.NOT_FOUND)
     233                                                .entity("Id: " + componentId
     234                                                                + " is not registered, cannot create data.")
     235                                                .build();
     236                        }
     237                        ComponentDescription desc = registry
     238                                        .getComponentDescription(componentId);
     239                        checkAndThrowDescription(desc, componentId);
     240                        String fileName = desc.getName() + "." + rawType;
     241                        if ("xml".equalsIgnoreCase(rawType)) {
     242                                result = new StreamingOutput() {
     243                                        @Override
     244                                        public void write(OutputStream output) throws IOException,
     245                                                        WebApplicationException {
     246                                                try {
     247                                                        registry.getMDComponentAsXml(componentId, output);
     248                                                } catch (ComponentRegistryException e) {
     249                                                        LOG.warn("Could not retrieve component {}",
     250                                                                        componentId);
     251                                                        LOG.debug("Details", e);
     252                                                        throw new WebApplicationException(e, Response
     253                                                                        .serverError()
     254                                                                        .status(Status.INTERNAL_SERVER_ERROR)
     255                                                                        .build());
     256                                                }
     257                                        }
     258                                };
     259                        } else if ("xsd".equalsIgnoreCase(rawType)) {
     260                                result = new StreamingOutput() {
     261                                        @Override
     262                                        public void write(OutputStream output) throws IOException,
     263                                                        WebApplicationException {
     264                                                try {
     265                                                        registry.getMDComponentAsXsd(componentId, output);
     266                                                } catch (ComponentRegistryException e) {
     267                                                        LOG.warn("Could not retrieve component {}",
     268                                                                        componentId);
     269                                                        LOG.debug("Details", e);
     270                                                        throw new WebApplicationException(e, Response
     271                                                                        .serverError()
     272                                                                        .status(Status.INTERNAL_SERVER_ERROR)
     273                                                                        .build());
     274                                                }
     275
     276                                        }
     277                                };
     278                        } else {
     279                                throw new WebApplicationException(Response
     280                                                .serverError()
     281                                                .entity("unsupported rawType: " + rawType
     282                                                                + " (only xml or xsd are supported)").build());
     283                        }
     284                        return createDownloadResponse(result, fileName);
     285                } catch (ComponentRegistryException e) {
     286                        LOG.warn("Could not retrieve component {}", componentId);
     287                        LOG.debug("Details", e);
     288                        return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
     289                                        .build();
     290                }
     291        }
     292
     293        @Override
     294        public ComponentRegistry findRegistry(String id,
     295                        RegistryClosure<? extends AbstractDescription> clos)
     296                        throws ComponentRegistryException {
     297                AbstractDescription desc = null;
     298                ComponentRegistry result = getRegistry(getStatus(false));
     299                desc = clos.getDescription(result, id);
     300                if (desc == null) {
     301                        List<ComponentRegistry> userRegs = componentRegistryFactory
     302                                        .getAllUserRegistries();
     303                        for (ComponentRegistry reg : userRegs) {
     304                                desc = clos.getDescription(reg, id);
     305                                if (desc != null) {
     306                                        result = reg;
     307                                        break;
     308                                }
     309                        }
     310                }
     311                return result;
     312        }
     313
     314        @Override
     315        @GET
     316        @Path("/profiles/{profileId}")
     317        @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_XML,
     318                        MediaType.APPLICATION_JSON })
     319        public Response getRegisteredProfile(
     320                        @PathParam("profileId") String profileId,
     321                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace)
     322                        throws ComponentRegistryException {
     323                LOG.debug("Profile with id {} is requested.", profileId);
     324                CMDComponentSpec mdProfile = getRegistry(getStatus(userspace))
     325                                .getMDProfile(profileId);
     326                if (mdProfile == null) {
     327                        return Response.status(Status.NOT_FOUND).build();
     328                } else {
     329                        return Response.ok(mdProfile).build();
     330                }
     331        }
     332
     333        @Override
     334        @GET
     335        @Path("/components/usage/{componentId}")
     336        @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_XML,
     337                        MediaType.APPLICATION_JSON })
     338        public List<AbstractDescription> getComponentUsage(
     339                        @PathParam("componentId") String componentId,
     340                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace)
     341                        throws ComponentRegistryException {
     342                try {
     343                        final long start = System.currentTimeMillis();
     344                        ComponentRegistry registry = getRegistry(getStatus(userspace));
     345                        List<ComponentDescription> components = registry
     346                                        .getUsageInComponents(componentId);
     347                        List<ProfileDescription> profiles = registry
     348                                        .getUsageInProfiles(componentId);
     349
     350                        LOG.debug(
     351                                        "Found {} components and {} profiles that use component {} ({} millisecs)",
     352                                        components.size(), profiles.size(), componentId,
     353                                        (System.currentTimeMillis() - start));
     354
     355                        List<AbstractDescription> usages = new ArrayList<AbstractDescription>(
     356                                        components.size() + profiles.size());
     357                        usages.addAll(components);
     358                        usages.addAll(profiles);
     359
     360                        return usages;
     361                } catch (ComponentRegistryException e) {
     362                        LOG.warn("Could not retrieve profile usage {}", componentId);
     363                        LOG.debug("Details", e);
     364                        throw e;
     365                }
     366        }
     367
     368        @Override
     369        @GET
     370        @Path("/profiles/{profileId}/comments")
     371        @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_XML,
     372                        MediaType.APPLICATION_JSON })
     373        public List<Comment> getCommentsFromProfile(
     374                        @PathParam("profileId") String profileId,
     375                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace)
     376                        throws ComponentRegistryException {
     377                long start = System.currentTimeMillis();
     378                final Principal principal = security.getUserPrincipal();
     379                List<Comment> comments = getRegistry(getStatus(userspace))
     380                                .getCommentsInProfile(profileId, principal);
     381                LOG.debug(
     382                                "Releasing {} registered comments in profile into the world ({} millisecs)",
     383                                comments.size(), (System.currentTimeMillis() - start));
     384                return comments;
     385        }
     386
     387        @Override
     388        @GET
     389        @Path("/components/{componentId}/comments")
     390        @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_XML,
     391                        MediaType.APPLICATION_JSON })
     392        public List<Comment> getCommentsFromComponent(
     393                        @PathParam("componentId") String componentId,
     394                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace)
     395                        throws ComponentRegistryException {
     396                long start = System.currentTimeMillis();
     397                final Principal principal = security.getUserPrincipal();
     398                List<Comment> comments = getRegistry(getStatus(userspace))
     399                                .getCommentsInComponent(componentId, principal);
     400                LOG.debug(
     401                                "Releasing {} registered comments in Component into the world ({} millisecs)",
     402                                comments.size(), (System.currentTimeMillis() - start));
     403                return comments;
     404        }
     405
     406        @Override
     407        @GET
     408        @Path("/profiles/{profileId}/comments/{commentId}")
     409        @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_XML,
     410                        MediaType.APPLICATION_JSON })
     411        public Comment getSpecifiedCommentFromProfile(
     412                        @PathParam("profileId") String profileId,
     413                        @PathParam("commentId") String commentId,
     414                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace)
     415                        throws ComponentRegistryException {
     416                LOG.debug("Comments of profile with id {} are requested.", commentId);
     417                final Principal principal = security.getUserPrincipal();
     418                return getRegistry(getStatus(userspace)).getSpecifiedCommentInProfile(
     419                                profileId, commentId, principal);
     420        }
     421
     422        @Override
     423        @GET
     424        @Path("/components/{componentId}/comments/{commentId}")
     425        @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_XML,
     426                        MediaType.APPLICATION_JSON })
     427        public Comment getSpecifiedCommentFromComponent(
     428                        @PathParam("componentId") String componentId,
     429                        @PathParam("commentId") String commentId,
     430                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace)
     431                        throws ComponentRegistryException {
     432                LOG.debug("Comments of component with id {} are requested.", commentId);
     433                final Principal principal = security.getUserPrincipal();
     434                return getRegistry(getStatus(userspace))
     435                                .getSpecifiedCommentInComponent(componentId, commentId,
     436                                                principal);
     437        }
     438
     439        /**
     440         *
     441         * Purely helper method for my front-end (FLEX) which only does post/get
     442         * requests. The query param is checked and the "proper" method is called.
     443         *
     444         * @param profileId
     445         * @param method
     446         * @return
     447         */
     448        @Override
     449        @POST
     450        @Path("/profiles/{profileId}")
     451        public Response manipulateRegisteredProfile(
     452                        @PathParam("profileId") String profileId,
     453                        @FormParam("method") String method,
     454                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) {
     455                if ("delete".equalsIgnoreCase(method)) {
     456                        return deleteRegisteredProfile(profileId, userspace);
     457                } else {
     458                        return Response.ok().build();
     459                }
     460        }
     461
     462        @Override
     463        @POST
     464        @Path("/profiles/{profileId}/comments/{commentId}")
     465        public Response manipulateCommentFromProfile(
     466                        @PathParam("profileId") String profileId,
     467                        @PathParam("commentId") String commentId,
     468                        @FormParam("method") String method,
     469                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) {
     470                if ("delete".equalsIgnoreCase(method)) {
     471                        return deleteCommentFromProfile(profileId, commentId, userspace);
     472                } else {
     473                        return Response.ok().build();
     474                }
     475        }
     476
     477        @Override
     478        @POST
     479        @Path("/components/{componentId}/comments/{commentId}")
     480        public Response manipulateCommentFromComponent(
     481                        @PathParam("componentId") String componentId,
     482                        @PathParam("commentId") String commentId,
     483                        @FormParam("method") String method,
     484                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) {
     485                if ("delete".equalsIgnoreCase(method)) {
     486                        return deleteCommentFromComponent(componentId, commentId, userspace);
     487                } else {
     488                        return Response.ok().build();
     489                }
     490        }
     491
     492        @Override
     493        @POST
     494        @Path("/profiles/{profileId}/publish")
     495        @Consumes("multipart/form-data")
     496        public Response publishRegisteredProfile(
     497                        @PathParam("profileId") String profileId,
     498                        @FormDataParam(DATA_FORM_FIELD) InputStream input,
     499                        @FormDataParam(NAME_FORM_FIELD) String name,
     500                        @FormDataParam(DESCRIPTION_FORM_FIELD) String description,
     501                        @FormDataParam(GROUP_FORM_FIELD) String group,
     502                        @FormDataParam(DOMAIN_FORM_FIELD) String domainName) {
     503                try {
     504                        Principal principal = checkAndGetUserPrincipal();
     505                        ProfileDescription desc = getRegistry(getStatus(true))
     506                                        .getProfileDescription(profileId);
     507                        if (desc != null) {
     508                                updateDescription(desc, name, description, domainName, group);
     509                                return register(input, desc, getUserCredentials(principal),
     510                                                true, new PublishAction(principal));
     511                        } else {
     512                                LOG.error("Update of nonexistent profile {} failed.", profileId);
     513                                return Response
     514                                                .serverError()
     515                                                .entity("Invalid id, cannot update nonexistent profile")
     516                                                .build();
     517                        }
     518                } catch (ComponentRegistryException e) {
     519                        LOG.warn("Could not retrieve profile {}", profileId);
     520                        LOG.debug("Details", e);
     521                        return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
     522                                        .build();
     523                } catch (UserUnauthorizedException ex) {
     524                        return Response.status(Status.UNAUTHORIZED).entity(ex.getMessage())
     525                                        .build();
     526                }
     527        }
     528
     529        @Override
     530        @POST
     531        @Path("/profiles/{profileId}/update")
     532        @Consumes("multipart/form-data")
     533        public Response updateRegisteredProfile(
     534                        @PathParam("profileId") String profileId,
     535                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace,
     536                        @FormDataParam(DATA_FORM_FIELD) InputStream input,
     537                        @FormDataParam(NAME_FORM_FIELD) String name,
     538                        @FormDataParam(DESCRIPTION_FORM_FIELD) String description,
     539                        @FormDataParam(GROUP_FORM_FIELD) String group,
     540                        @FormDataParam(DOMAIN_FORM_FIELD) String domainName) {
     541                try {
     542                        Principal principal = checkAndGetUserPrincipal();
     543                        UserCredentials userCredentials = getUserCredentials(principal);
     544                        ProfileDescription desc = getRegistry(getStatus(userspace))
     545                                        .getProfileDescription(profileId);
     546                        if (desc != null) {
     547                                updateDescription(desc, name, description, domainName, group);
     548                                return register(input, desc, userCredentials, userspace,
     549                                                new UpdateAction(principal));
     550                        } else {
     551                                LOG.error("Update of nonexistent id (" + profileId
     552                                                + ") failed.");
     553                                return Response
     554                                                .serverError()
     555                                                .entity("Invalid id, cannot update nonexistent profile")
     556                                                .build();
     557                        }
     558                } catch (ComponentRegistryException e) {
     559                        LOG.warn("Could not retrieve profile {}", profileId);
     560                        LOG.debug("Details", e);
     561                        return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
     562                                        .build();
     563                } catch (UserUnauthorizedException ex) {
     564                        return Response.status(Status.UNAUTHORIZED).entity(ex.getMessage())
     565                                        .build();
     566                }
     567
     568        }
     569
     570        /**
     571         *
     572         * Purely helper method for my front-end (FLEX) which van only do post/get
     573         * requests. The query param is checked and the "proper" method is called.
     574         *
     575         * @param componentId
     576         * @param method
     577         * @return
     578         */
     579        @Override
     580        @POST
     581        @Path("/components/{componentId}")
     582        public Response manipulateRegisteredComponent(
     583                        @PathParam("componentId") String componentId,
     584                        @FormParam("method") String method,
     585                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) {
     586                if ("delete".equalsIgnoreCase(method)) {
     587                        return deleteRegisteredComponent(componentId, userspace);
     588                } else {
     589                        return Response.ok().build();
     590                }
     591        }
     592
     593        @Override
     594        @POST
     595        @Path("/components/{componentId}/publish")
     596        @Consumes("multipart/form-data")
     597        public Response publishRegisteredComponent(
     598                        @PathParam("componentId") String componentId,
     599                        @FormDataParam(DATA_FORM_FIELD) InputStream input,
     600                        @FormDataParam(NAME_FORM_FIELD) String name,
     601                        @FormDataParam(DESCRIPTION_FORM_FIELD) String description,
     602                        @FormDataParam(GROUP_FORM_FIELD) String group,
     603                        @FormDataParam(DOMAIN_FORM_FIELD) String domainName) {
     604                try {
     605                        Principal principal = checkAndGetUserPrincipal();
     606                        // TODO: Get status from parameter
     607                        ComponentDescription desc = getRegistry(getStatus(true))
     608                                        .getComponentDescription(componentId);
     609                        if (desc != null) {
     610                                updateDescription(desc, name, description, domainName, group);
     611                                return register(input, desc, getUserCredentials(principal),
     612                                                true, new PublishAction(principal));
     613                        } else {
     614                                LOG.error("Update of nonexistent id (" + componentId
     615                                                + ") failed.");
     616                                return Response
     617                                                .serverError()
     618                                                .entity("Invalid id, cannot update nonexistent profile")
     619                                                .build();
     620                        }
     621                } catch (ComponentRegistryException e) {
     622                        LOG.warn("Could not retrieve component {}", componentId);
     623                        LOG.debug("Details", e);
     624                        return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
     625                                        .build();
     626                } catch (UserUnauthorizedException ex) {
     627                        return Response.status(Status.UNAUTHORIZED).entity(ex.getMessage())
     628                                        .build();
     629                }
     630        }
     631
     632        @Override
     633        @POST
     634        @Path("/components/{componentId}/update")
     635        @Consumes("multipart/form-data")
     636        public Response updateRegisteredComponent(
     637                        @PathParam("componentId") String componentId,
     638                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace,
     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                        Principal principal = checkAndGetUserPrincipal();
     646                        ComponentDescription desc = getRegistry(getStatus(userspace))
     647                                        .getComponentDescription(componentId);
     648                        if (desc != null) {
     649                                updateDescription(desc, name, description, domainName, group);
     650                                return register(input, desc, getUserCredentials(principal),
     651                                                userspace, new UpdateAction(principal));
     652                        } else {
     653                                LOG.error("Update of nonexistent id (" + componentId
     654                                                + ") failed.");
     655                                return Response
     656                                                .serverError()
     657                                                .entity("Invalid id, cannot update nonexistent component")
     658                                                .build();
     659                        }
     660                } catch (ComponentRegistryException e) {
     661                        LOG.warn("Could not retrieve component {}", componentId);
     662                        LOG.debug("Details", e);
     663                        return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
     664                                        .build();
     665                } catch (UserUnauthorizedException ex) {
     666                        return Response.status(Status.UNAUTHORIZED).entity(ex.getMessage())
     667                                        .build();
     668                }
     669        }
     670
     671        private void updateDescription(AbstractDescription desc, String name,
     672                        String description, String domainName, String group) {
     673                desc.setName(name);
     674                desc.setDescription(description);
     675                desc.setDomainName(domainName);
     676                desc.setGroupName(group);
     677                desc.setRegistrationDate(AbstractDescription.createNewDate());
     678        }
     679
     680        @Override
     681        @DELETE
     682        @Path("/components/{componentId}")
     683        public Response deleteRegisteredComponent(
     684                        @PathParam("componentId") String componentId,
     685                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) {
     686                try {
     687                        Principal principal = checkAndGetUserPrincipal();
     688                        ComponentRegistry registry = getRegistry(getStatus(userspace));
     689                        LOG.debug("Component with id {} set for deletion.", componentId);
     690                        registry.deleteMDComponent(componentId, principal, false);
     691                } catch (DeleteFailedException e) {
     692                        LOG.info("Component with id {} deletion failed. Reason: {}",
     693                                        componentId, e.getMessage());
     694                        LOG.debug("Deletion failure details:", e);
     695                        return Response.status(Status.FORBIDDEN)
     696                                        .entity("" + e.getMessage()).build();
     697                } catch (ComponentRegistryException e) {
     698                        LOG.warn("Component with id " + componentId + " deletion failed.",
     699                                        e);
     700                        return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
     701                                        .build();
     702                } catch (IOException e) {
     703                        LOG.error("Component with id " + componentId + " deletion failed.",
     704                                        e);
     705                        return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
     706                                        .build();
     707                } catch (UserUnauthorizedException e) {
     708                        LOG.info("Component with id {} deletion failed: {}", componentId,
     709                                        e.getMessage());
     710                        LOG.debug("Deletion failure details:", e);
     711                        return Response.serverError().status(Status.UNAUTHORIZED)
     712                                        .entity("" + e.getMessage()).build();
     713                }
     714                LOG.info("Component with id: {} deleted.", componentId);
     715                return Response.ok().build();
     716        }
     717
     718        @Override
     719        @DELETE
     720        @Path("/profiles/{profileId}")
     721        public Response deleteRegisteredProfile(
     722                        @PathParam("profileId") String profileId,
     723                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) {
     724                try {
     725                        Principal principal = checkAndGetUserPrincipal();
     726                        LOG.debug("Profile with id: {} set for deletion.", profileId);
     727                        getRegistry(getStatus(userspace)).deleteMDProfile(profileId,
     728                                        principal);
     729                } catch (DeleteFailedException e) {
     730                        LOG.info("Profile with id: {} deletion failed: {}", profileId,
     731                                        e.getMessage());
     732                        LOG.debug("Deletion failure details:", e);
     733                        return Response.serverError().status(Status.FORBIDDEN)
     734                                        .entity("" + e.getMessage()).build();
     735                } catch (ComponentRegistryException e) {
     736                        LOG.warn("Could not retrieve component", e);
     737                        return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
     738                                        .build();
     739                } catch (IOException e) {
     740                        LOG.error("Profile with id: " + profileId + " deletion failed.", e);
     741                        return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
     742                                        .build();
     743                } catch (UserUnauthorizedException e) {
     744                        LOG.info("Profile with id: {} deletion failed: {}", profileId,
     745                                        e.getMessage());
     746                        LOG.debug("Deletion failure details:", e);
     747                        return Response.serverError().status(Status.UNAUTHORIZED)
     748                                        .entity("" + e.getMessage()).build();
     749                }
     750                LOG.info("Profile with id: {} deleted.", profileId);
     751                return Response.ok().build();
     752        }
     753
     754        @Override
     755        @DELETE
     756        @Path("/profiles/{profileId}/comments/{commentId}")
     757        public Response deleteCommentFromProfile(
     758                        @PathParam("profileId") String profileId,
     759                        @PathParam("commentId") String commentId,
     760                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) {
     761                try {
     762                        final Principal principal = checkAndGetUserPrincipal();
     763                        final ComponentRegistry registry = getRegistry(getStatus(userspace));
     764                        final Comment comment = registry.getSpecifiedCommentInProfile(
     765                                        profileId, commentId, principal);
     766                        if (comment != null
     767                                        && profileId.equals(comment.getProfileDescriptionId())) {
     768                                LOG.debug("Comment with id: {} set for deletion.", commentId);
     769                                registry.deleteComment(commentId, principal);
     770                        } else {
     771                                throw new ComponentRegistryException(
     772                                                "Comment not found for specified profile");
     773                        }
     774                } catch (DeleteFailedException e) {
     775                        LOG.info("Comment with id: {} deletion failed: {}", commentId,
     776                                        e.getMessage());
     777                        LOG.debug("Deletion failure details:", e);
     778                        return Response.serverError().status(Status.FORBIDDEN)
     779                                        .entity("" + e.getMessage()).build();
     780                } catch (ComponentRegistryException e) {
     781                        LOG.info("Could not retrieve component", e);
     782                        return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
     783                                        .build();
     784                } catch (IOException e) {
     785                        LOG.error("Comment with id: " + commentId + " deletion failed.", e);
     786                        return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
     787                                        .build();
     788                } catch (UserUnauthorizedException e) {
     789                        LOG.info("Comment with id: {} deletion failed: {}", commentId,
     790                                        e.getMessage());
     791                        LOG.debug("Deletion failure details:", e);
     792                        return Response.serverError().status(Status.UNAUTHORIZED)
     793                                        .entity("" + e.getMessage()).build();
     794                }
     795                LOG.info("Comment with id: {} deleted.", commentId);
     796                return Response.ok().build();
     797        }
     798
     799        @Override
     800        @DELETE
     801        @Path("/components/{componentId}/comments/{commentId}")
     802        public Response deleteCommentFromComponent(
     803                        @PathParam("componentId") String componentId,
     804                        @PathParam("commentId") String commentId,
     805                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) {
     806                try {
     807                        final Principal principal = checkAndGetUserPrincipal();
     808                        final ComponentRegistry registry = getRegistry(getStatus(userspace));
     809                        final Comment comment = registry.getSpecifiedCommentInComponent(
     810                                        componentId, commentId, principal);
     811                        if (comment != null
     812                                        && componentId.equals(comment.getComponentDescriptionId())) {
     813                                LOG.debug("Comment with id: {} set for deletion.", commentId);
     814                                registry.deleteComment(commentId, principal);
     815                        } else {
     816                                throw new ComponentRegistryException(
     817                                                "Comment not found for specified component");
     818                        }
     819                } catch (DeleteFailedException e) {
     820                        LOG.info("Comment with id: {} deletion failed: {}", commentId,
     821                                        e.getMessage());
     822                        LOG.debug("Deletion failure details:", e);
     823                        return Response.serverError().status(Status.FORBIDDEN)
     824                                        .entity("" + e.getMessage()).build();
     825                } catch (ComponentRegistryException e) {
     826                        LOG.info("Could not retrieve component", e);
     827                        return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
     828                                        .build();
     829                } catch (IOException e) {
     830                        LOG.error("Comment with id: " + commentId + " deletion failed.", e);
     831                        return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
     832                                        .build();
     833                } catch (UserUnauthorizedException e) {
     834                        LOG.info("Comment with id: {} deletion failed: {}", commentId,
     835                                        e.getMessage());
     836                        LOG.debug("Deletion failure details:", e);
     837                        return Response.serverError().status(Status.UNAUTHORIZED)
     838                                        .entity("" + e.getMessage()).build();
     839                }
     840                LOG.info("Comment with id: {} deleted.", commentId);
     841                return Response.ok().build();
     842        }
     843
     844        @Override
     845        @GET
     846        @Path("/profiles/{profileId}/{rawType}")
     847        @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_XML })
     848        public Response getRegisteredProfileRawType(
     849                        @PathParam("profileId") final String profileId,
     850                        @PathParam("rawType") String rawType) {
     851                LOG.debug("Profile with id {} and rawType {} is requested.", profileId,
     852                                rawType);
     853                StreamingOutput result = null;
     854                try {
     855                        final ComponentRegistry registry = findRegistry(profileId,
     856                                        new ProfileClosure());
     857                        if (registry == null) {
     858                                return Response
     859                                                .status(Status.NOT_FOUND)
     860                                                .entity("Id: " + profileId
     861                                                                + " is not registered, cannot create data.")
     862                                                .build();
     863                        }
     864                        ProfileDescription desc = registry.getProfileDescription(profileId);
     865                        checkAndThrowDescription(desc, profileId);
     866                        String fileName = desc.getName() + "." + rawType;
     867
     868                        if ("xml".equalsIgnoreCase(rawType)) {
     869                                result = new StreamingOutput() {
     870                                        @Override
     871                                        public void write(OutputStream output) throws IOException,
     872                                                        WebApplicationException {
     873                                                try {
     874                                                        registry.getMDProfileAsXml(profileId, output);
     875                                                } catch (ComponentRegistryException e) {
     876                                                        LOG.warn("Could not retrieve component {}",
     877                                                                        profileId);
     878                                                        LOG.debug("Details", e);
     879                                                        throw new WebApplicationException(e, Response
     880                                                                        .serverError()
     881                                                                        .status(Status.INTERNAL_SERVER_ERROR)
     882                                                                        .build());
     883                                                }
     884                                        }
     885                                };
     886                        } else if ("xsd".equalsIgnoreCase(rawType)) {
     887                                result = new StreamingOutput() {
     888                                        @Override
     889                                        public void write(OutputStream output) throws IOException,
     890                                                        WebApplicationException {
     891                                                try {
     892                                                        registry.getMDProfileAsXsd(profileId, output);
     893                                                } catch (ComponentRegistryException e) {
     894                                                        LOG.warn("Could not retrieve component {}",
     895                                                                        profileId);
     896                                                        LOG.debug("Details", e);
     897                                                        throw new WebApplicationException(e, Response
     898                                                                        .serverError()
     899                                                                        .status(Status.INTERNAL_SERVER_ERROR)
     900                                                                        .build());
     901                                                }
     902                                        }
     903                                };
     904                        } else {
     905                                throw new WebApplicationException(Response
     906                                                .serverError()
     907                                                .entity("unsupported rawType: " + rawType
     908                                                                + " (only xml or xsd are supported)").build());
     909                        }
     910                        return createDownloadResponse(result, fileName);
     911                } catch (ComponentRegistryException e) {
     912                        LOG.warn("Could not retrieve component {}", profileId);
     913                        LOG.debug("Details", e);
     914                        return Response.serverError().status(Status.INTERNAL_SERVER_ERROR)
     915                                        .build();
     916                }
     917        }
     918
     919        private void checkAndThrowDescription(AbstractDescription desc, String id) {
     920                if (desc == null) {
     921                        throw new WebApplicationException(Response.serverError()
     922                                        .entity("Incorrect id:" + id + "cannot handle request")
     923                                        .build());
     924                }
     925        }
     926
     927        private Response createDownloadResponse(StreamingOutput result,
     928                        String fileName) {
     929                // Making response so it triggers browsers native save as dialog.
     930                Response response = Response
     931                                .ok()
     932                                .type("application/x-download")
     933                                .header("Content-Disposition",
     934                                                "attachment; filename=\"" + fileName + "\"")
     935                                .entity(result).build();
     936                return response;
     937
     938        }
     939
     940        @Override
     941        @POST
     942        @Path("/profiles")
     943        @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_XML,
     944                        MediaType.APPLICATION_JSON })
     945        @Consumes("multipart/form-data")
     946        public Response registerProfile(
     947                        @FormDataParam(DATA_FORM_FIELD) InputStream input,
     948                        @FormDataParam(NAME_FORM_FIELD) String name,
     949                        @FormDataParam(DESCRIPTION_FORM_FIELD) String description,
     950                        @FormDataParam(GROUP_FORM_FIELD) String group,
     951                        @FormDataParam(DOMAIN_FORM_FIELD) String domainName,
     952                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) {
     953                try {
     954                        Principal principal = checkAndGetUserPrincipal();
     955                        UserCredentials userCredentials = getUserCredentials(principal);
     956                        ProfileDescription desc = createNewProfileDescription();
     957                        desc.setCreatorName(userCredentials.getDisplayName());
     958                        desc.setUserId(userCredentials.getPrincipalName()); // Hash used to
     959                                                                                                                                // be created
     960                                                                                                                                // here, now Id
     961                                                                                                                                // is
     962                                                                                                                                // constructed
     963                                                                                                                                // by impl
     964                        desc.setName(name);
     965                        desc.setDescription(description);
     966                        desc.setGroupName(group);
     967                        desc.setDomainName(domainName);
     968                        LOG.debug("Trying to register Profile: {}", desc);
     969                        return register(input, desc, userCredentials, userspace,
     970                                        new NewAction());
     971                } catch (UserUnauthorizedException ex) {
     972                        return Response.status(Status.UNAUTHORIZED).entity(ex.getMessage())
     973                                        .build();
     974                }
     975        }
     976
     977        @Override
     978        @POST
     979        @Path("/components")
     980        @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_XML,
     981                        MediaType.APPLICATION_JSON })
     982        @Consumes("multipart/form-data")
     983        public Response registerComponent(
     984                        @FormDataParam(DATA_FORM_FIELD) InputStream input,
     985                        @FormDataParam(NAME_FORM_FIELD) String name,
     986                        @FormDataParam(DESCRIPTION_FORM_FIELD) String description,
     987                        @FormDataParam(GROUP_FORM_FIELD) String group,
     988                        @FormDataParam(DOMAIN_FORM_FIELD) String domainName,
     989                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace) {
     990                try {
     991                        Principal principal = checkAndGetUserPrincipal();
     992                        UserCredentials userCredentials = getUserCredentials(principal);
     993                        ComponentDescription desc = createNewComponentDescription();
     994                        desc.setCreatorName(userCredentials.getDisplayName());
     995                        desc.setUserId(userCredentials.getPrincipalName()); // Hash used to
     996                                                                                                                                // be created
     997                                                                                                                                // here, now Id
     998                                                                                                                                // is
     999                                                                                                                                // constructed
     1000                                                                                                                                // by impl
     1001                        desc.setName(name);
     1002                        desc.setDescription(description);
     1003                        desc.setGroupName(group);
     1004                        desc.setDomainName(domainName);
     1005                        LOG.debug("Trying to register Component: {}", desc);
     1006                        return register(input, desc, userCredentials, userspace,
     1007                                        new NewAction());
     1008                } catch (UserUnauthorizedException ex) {
     1009                        return Response.status(Status.UNAUTHORIZED).entity(ex.getMessage())
     1010                                        .build();
     1011                }
     1012        }
     1013
     1014        @Override
     1015        @POST
     1016        @Path("/components/{componentId}/comments")
     1017        @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_XML,
     1018                        MediaType.APPLICATION_JSON })
     1019        @Consumes("multipart/form-data")
     1020        public Response registerCommentInComponent(
     1021                        @FormDataParam(DATA_FORM_FIELD) InputStream input,
     1022                        @PathParam("componentId") String componentId,
     1023                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace)
     1024                        throws ComponentRegistryException {
     1025                try {
     1026                        Principal principal = checkAndGetUserPrincipal();
     1027                        UserCredentials userCredentials = getUserCredentials(principal);
     1028                        if (null == componentRegistryFactory
     1029                                        .getOrCreateUser(userCredentials)) {
     1030                                throw new UserUnauthorizedException(
     1031                                                "Cannot materialize authenticated user");
     1032                        }
     1033                        // TODO: Add user/group param
     1034                        ComponentRegistry registry = getRegistry(getStatus(userspace),
     1035                                        null, userCredentials);
     1036                        ComponentDescription description = registry
     1037                                        .getComponentDescription(componentId);
     1038                        if (description != null) {
     1039                                LOG.debug("Trying to register comment to {}", componentId);
     1040                                return registerComment(input, registry, userspace, description,
     1041                                                principal, userCredentials);
     1042                        } else {
     1043                                LOG.warn(
     1044                                                "Attempt to post comment on nonexistent component id {} failed.",
     1045                                                componentId);
     1046                                return Response
     1047                                                .serverError()
     1048                                                .entity("Invalid id, cannot comment on nonexistent component")
     1049                                                .build();
     1050                        }
     1051                } catch (UserUnauthorizedException ex) {
     1052                        return Response.status(Status.UNAUTHORIZED).entity(ex.getMessage())
     1053                                        .build();
     1054                }
     1055        }
     1056
     1057        @Override
     1058        @POST
     1059        @Path("/profiles/{profileId}/comments")
     1060        @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_XML,
     1061                        MediaType.APPLICATION_JSON })
     1062        @Consumes("multipart/form-data")
     1063        public Response registerCommentInProfile(
     1064                        @FormDataParam(DATA_FORM_FIELD) InputStream input,
     1065                        @PathParam("profileId") String profileId,
     1066                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace)
     1067                        throws ComponentRegistryException {
     1068                try {
     1069                        Principal principal = checkAndGetUserPrincipal();
     1070                        UserCredentials userCredentials = getUserCredentials(principal);
     1071                        if (null == componentRegistryFactory
     1072                                        .getOrCreateUser(userCredentials)) {
     1073                                throw new UserUnauthorizedException(
     1074                                                "Cannot materialize authenticated user");
     1075                        }
     1076                        // TODO: Add user/group param
     1077                        ComponentRegistry registry = getRegistry(getStatus(userspace),
     1078                                        null, userCredentials);
     1079                        ProfileDescription description = registry
     1080                                        .getProfileDescription(profileId);
     1081                        if (description != null) {
     1082                                LOG.debug("Trying to register comment to {}", profileId);
     1083                                return registerComment(input, registry, userspace, description,
     1084                                                principal, userCredentials);
     1085                        } else {
     1086                                LOG.warn(
     1087                                                "Attempt to post comment on nonexistent profile id {} failed.",
     1088                                                profileId);
     1089                                return Response
     1090                                                .serverError()
     1091                                                .entity("Invalid id, cannot comment on nonexistent profile")
     1092                                                .build();
     1093                        }
     1094                } catch (UserUnauthorizedException ex) {
     1095                        return Response.status(Status.UNAUTHORIZED).entity(ex.getMessage())
     1096                                        .build();
     1097                }
     1098        }
     1099
     1100        @Override
     1101        @GET
     1102        @Path("/pingSession")
     1103        @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_XML,
     1104                        MediaType.APPLICATION_JSON })
     1105        public Response pingSession() {
     1106                boolean stillActive = false;
     1107                Principal userPrincipal = security.getUserPrincipal();
     1108                if (LOG.isInfoEnabled()) {
     1109                        LOG.debug("ping by <{}>",
     1110                                        (userPrincipal == null ? "unauthorized user"
     1111                                                        : userPrincipal.getName()));
     1112                }
     1113                if (request != null) {
     1114                        if (userPrincipal != null
     1115                                        && !ComponentRegistryFactory.ANONYMOUS_USER
     1116                                                        .equals(userPrincipal.getName())) {
     1117                                stillActive = !((HttpServletRequest) request).getSession()
     1118                                                .isNew();
     1119                        }
     1120                }
     1121                return Response
     1122                                .ok()
     1123                                .entity(String.format("<session stillActive=\"%s\"/>",
     1124                                                stillActive)).build();
     1125        }
     1126
     1127        private Response register(InputStream input, AbstractDescription desc,
     1128                        UserCredentials userCredentials, boolean userspace,
     1129                        RegisterAction action) {
     1130                try {
     1131                        // TODO: Add user/group param
     1132                        ComponentRegistry registry = getRegistry(getStatus(userspace),
     1133                                        null, userCredentials);
     1134                        DescriptionValidator descriptionValidator = new DescriptionValidator(
     1135                                        desc);
     1136                        MDValidator validator = new MDValidator(input, desc, registry,
     1137                                        getRegistry(getStatus(true)),
     1138                                        componentRegistryFactory.getPublicRegistry(), marshaller);
     1139                        RegisterResponse response = new RegisterResponse();
     1140                        response.setIsInUserSpace(userspace);
     1141                        validate(response, descriptionValidator, validator);
     1142                        if (response.getErrors().isEmpty()) {
     1143
     1144                                CMDComponentSpec spec = validator.getCMDComponentSpec();
     1145
     1146                                // removing filename from spec before it gets extended.
     1147                                // recursion over all the components
     1148                                setFileNamesFromListToNull(spec.getCMDComponent());
     1149
     1150                                try {
     1151                                        checkForRecursion(validator, registry, desc);
     1152
     1153                                        // Add profile
     1154                                        int returnCode = action.execute(desc, spec, response,
     1155                                                        registry);
     1156                                        if (returnCode == 0) {
     1157                                                response.setRegistered(true);
     1158                                                response.setDescription(desc);
     1159                                        } else {
     1160                                                response.setRegistered(false);
     1161                                                response.addError("Unable to register at this moment. Internal server error.");
     1162                                        }
     1163                                } catch (ComponentRegistryException ex) {
     1164                                        // Recursion detected
     1165                                        response.setRegistered(false);
     1166                                        response.addError("Error while expanding specification. "
     1167                                                        + ex.getMessage());
     1168                                }
     1169                        } else {
     1170                                LOG.warn("Registration failed with validation errors: {}",
     1171                                                Arrays.toString(response.getErrors().toArray()));
     1172                                response.setRegistered(false);
     1173                        }
     1174                        LOG.info("Registered new {} {}", desc.isProfile() ? "profile"
     1175                                        : "component", desc);
     1176                        response.setIsProfile(desc.isProfile());
     1177                        return Response.ok(response).build();
     1178                } finally {
    2051179                        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 {
     1180                                input.close();// either we read the input or there was an
     1181                                                                // exception, we need to close it.
     1182                        } catch (IOException e) {
     1183                                LOG.error("Error when closing inputstream: ", e);
     1184                        }
     1185                }
     1186        }
     1187
     1188        /**
     1189         *
     1190         * @param validator
     1191         * @param registry
     1192         * @param desc
     1193         * @throws ComponentRegistryException
     1194         *             if recursion is detected or something goes wrong while trying
     1195         *             to detect recursion
     1196         */
     1197        private void checkForRecursion(MDValidator validator,
     1198                        ComponentRegistry registry, AbstractDescription desc)
     1199                        throws ComponentRegistryException {
     1200                try {
     1201                        // Expand to check for recursion. Operate on copy so that original
     1202                        // does not get expanded.
     1203                        final CMDComponentSpec specCopy = validator
     1204                                        .getCopyOfCMDComponentSpec();
     1205                        // In case of recursion, the following will throw a
     1206                        // ComponentRegistryException
     1207                        registry.getExpander().expandNestedComponent(
     1208                                        specCopy.getCMDComponent(), desc.getId());
     1209                } catch (JAXBException ex) {
     1210                        throw new ComponentRegistryException(
     1211                                        "Unmarshalling failed while preparing recursion detection",
     1212                                        ex);
     1213                }
     1214        }
     1215
     1216        private Response registerComment(InputStream input,
     1217                        ComponentRegistry registry, boolean userspace,
     1218                        AbstractDescription description, Principal principal,
     1219                        UserCredentials userCredentials) {
     1220                try {
     1221                        CommentValidator validator = new CommentValidator(input,
     1222                                        description, marshaller);
     1223                        CommentResponse response = new CommentResponse();
     1224                        response.setIsInUserSpace(userspace);
     1225                        validateComment(response, validator);
     1226                        if (response.getErrors().isEmpty()) {
     1227                                Comment com = validator.getCommentSpec();
     1228                                // int returnCode = action.executeComment(com, response,
     1229                                // registry, principal.getName());
     1230
     1231                                // If user name is left empty, fill it using the user's display
     1232                                // name
     1233                                if (null == com.getUserName() || "".equals(com.getUserName())) {
     1234                                        if (userCredentials != null) {
     1235                                                com.setUserName(userCredentials.getDisplayName());
     1236                                        } else {
     1237                                                com.setUserName(principal.getName());
     1238                                        }
     1239                                }
     1240
     1241                                int returnCode = registry.registerComment(com,
     1242                                                principal.getName());
     1243                                if (returnCode == 0) {
     1244                                        response.setRegistered(true);
     1245                                        response.setComment(com);
     1246                                } else {
     1247                                        response.setRegistered(false);
     1248                                        response.addError("Unable to post at this moment. Internal server error.");
     1249                                }
     1250                                if (com.getComponentDescriptionId() != null) {
     1251                                        LOG.info("Posted new comment on component {}",
     1252                                                        com.getComponentDescriptionId());
     1253                                } else {
     1254                                        LOG.info("Posted new comment on profile {}",
     1255                                                        com.getProfileDescriptionId());
     1256                                }
     1257                        } else {
     1258                                LOG.warn(
     1259                                                "Posting of comment failed with validation errors: {}",
     1260                                                Arrays.toString(response.getErrors().toArray()));
     1261                                response.setRegistered(false);
     1262                        }
     1263                        return Response.ok(response).build();
     1264                } catch (ComponentRegistryException ex) {
     1265                        LOG.error("Error while inserting comment: ", ex);
     1266                        return Response.serverError().entity(ex.getMessage()).build();
     1267                } finally {
    2181268                        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     }
     1269                                input.close();// either we read the input or there was an
     1270                                                                // exception, we need to close it.
     1271                        } catch (IOException e) {
     1272                                LOG.error("Error when closing inputstream: ", e);
     1273                                return Response.serverError().build();
     1274                        }
     1275                }
     1276        }
     1277
     1278        private ComponentDescription createNewComponentDescription() {
     1279                ComponentDescription desc = ComponentDescription.createNewDescription();
     1280                desc.setHref(createXlink(desc.getId()));
     1281                return desc;
     1282        }
     1283
     1284        private ProfileDescription createNewProfileDescription() {
     1285                ProfileDescription desc = ProfileDescription.createNewDescription();
     1286                desc.setHref(createXlink(desc.getId()));
     1287                return desc;
     1288        }
     1289
     1290        private String createXlink(String id) {
     1291                URI uri = uriInfo.getRequestUriBuilder().path(id).build();
     1292                return uri.toString();
     1293        }
     1294
     1295        /**
     1296         *
     1297         * @return The application's base URI as configured in the
     1298         *         {@link #APPLICATION_BASE_URL_PARAM} context parameter. If
     1299         *         correctly configured, it should look something like
     1300         *         "http://catalog.clarin.eu/ds/ComponentRegistry".
     1301         *         <em>Be aware that this
     1302         * can also be null if configured incorrectly!</em>
     1303         *
     1304         * @see #APPLICATION_BASE_URL_PARAM
     1305         */
     1306        private String getApplicationBaseURI() {
     1307                return servletContext.getInitParameter(APPLICATION_BASE_URL_PARAM);
     1308        }
     1309
     1310        private void validate(RegisterResponse response, Validator... validators) {
     1311                for (Validator validator : validators) {
     1312                        if (!validator.validate()) {
     1313                                for (String error : validator.getErrorMessages()) {
     1314                                        response.addError(error);
     1315                                }
     1316                        }
     1317                }
     1318        }
     1319
     1320        private void validateComment(CommentResponse response,
     1321                        Validator... validators) {
     1322                for (Validator validator : validators) {
     1323                        if (!validator.validate()) {
     1324                                for (String error : validator.getErrorMessages()) {
     1325                                        response.addError(error);
     1326                                }
     1327                        }
     1328                }
     1329        }
     1330
     1331        /**
     1332         * @param componentRegistryFactory
     1333         *            the componentRegistryFactory to set
     1334         */
     1335        @Override
     1336        public void setComponentRegistryFactory(
     1337                        ComponentRegistryFactory componentRegistryFactory) {
     1338                this.componentRegistryFactory = componentRegistryFactory;
     1339        }
     1340
     1341        /**
     1342         *
     1343         * @param listofcomponents
     1344         *            a list of components whose file-names and whose childrens'
     1345         *            filenames are to be set to null
     1346         */
     1347        @Override
     1348        public void setFileNamesFromListToNull(
     1349                        List<CMDComponentType> listofcomponents) {
     1350
     1351                for (CMDComponentType currentcomponent : listofcomponents) {
     1352                        setFileNamesToNullCurrent(currentcomponent);
     1353                }
     1354
     1355        }
     1356
     1357        /**
     1358         *
     1359         * @param currentcomponent
     1360         *            a component whose file-name and whose children filenames are
     1361         *            to be set to null
     1362         */
     1363        protected void setFileNamesToNullCurrent(CMDComponentType currentcomponent) {
     1364                currentcomponent.setFilename(null);
     1365                setFileNamesFromListToNull(currentcomponent.getCMDComponent());
     1366        }
     1367
     1368        /**
     1369         *
     1370         * @param userspace
     1371         *            if "true" then profiles and components from the user's
     1372         *            workspace, otherwise -- public
     1373         * @param limit
     1374         *            the number of items to be displayed
     1375         * @return rss for the components in the database to which we are currently
     1376         *         connected
     1377         * @throws ComponentRegistryException
     1378         * @throws ParseException
     1379         */
     1380        @Override
     1381        @GET
     1382        @Path("/components/rss")
     1383        @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_XML,
     1384                        MediaType.APPLICATION_JSON })
     1385        public Rss getRssComponent(
     1386                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace,
     1387                        @QueryParam(NUMBER_OF_RSSITEMS) @DefaultValue("20") String limit)
     1388                        throws ComponentRegistryException, ParseException {
     1389                final List<ComponentDescription> components = getRegistry(
     1390                                getStatus(userspace)).getComponentDescriptions();
     1391                final RssCreatorDescriptions instance = new RssCreatorDescriptions(
     1392                                userspace, getApplicationBaseURI(), "components",
     1393                                Integer.parseInt(limit), components,
     1394                                AbstractDescription.COMPARE_ON_DATE);
     1395                final Rss rss = instance.getRss();
     1396                LOG.debug("Releasing RSS of {} most recently registered components",
     1397                                limit);
     1398                return rss;
     1399        }
     1400
     1401        /**
     1402         *
     1403         * @param userspace
     1404         *            if "true" then profiles and components from the user's
     1405         *            workspace, otherwise -- public
     1406         * @param limit
     1407         *            the number of items to be displayed
     1408         * @return rss for the profiles in the database to which we are currently
     1409         *         connected
     1410         * @throws ComponentRegistryException
     1411         * @throws ParseException
     1412         */
     1413        @Override
     1414        @GET
     1415        @Path("/profiles/rss")
     1416        @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_XML,
     1417                        MediaType.APPLICATION_JSON })
     1418        public Rss getRssProfile(
     1419                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace,
     1420                        @QueryParam(NUMBER_OF_RSSITEMS) @DefaultValue("20") String limit)
     1421                        throws ComponentRegistryException, ParseException {
     1422                final List<ProfileDescription> profiles = getRegistry(
     1423                                getStatus(userspace)).getProfileDescriptions();
     1424                final RssCreatorDescriptions instance = new RssCreatorDescriptions(
     1425                                userspace, getApplicationBaseURI(), "profiles",
     1426                                Integer.parseInt(limit), profiles,
     1427                                AbstractDescription.COMPARE_ON_DATE);
     1428                final Rss rss = instance.getRss();
     1429                LOG.debug("Releasing RSS of {} most recently registered profiles",
     1430                                limit);
     1431                return rss;
     1432        }
     1433
     1434        /**
     1435         *
     1436         * @param profileId
     1437         *            the Id of a profile whose comments are to be rss-ed
     1438         * @param userspace
     1439         *            if "true" then profiles and components from the user's
     1440         *            workspace, otherwise -- public
     1441         * @param limit
     1442         *            the number of items to be displayed
     1443         * @return rss of the comments for a chosen profile
     1444         * @throws ComponentRegistryException
     1445         * @throws IOException
     1446         * @throws JAXBException
     1447         * @throws ParseException
     1448         */
     1449        @Override
     1450        @GET
     1451        @Path("/profiles/{profileId}/comments/rss")
     1452        @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_XML,
     1453                        MediaType.APPLICATION_JSON })
     1454        public Rss getRssOfCommentsFromProfile(
     1455                        @PathParam("profileId") String profileId,
     1456                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace,
     1457                        @QueryParam(NUMBER_OF_RSSITEMS) @DefaultValue("20") String limit)
     1458                        throws ComponentRegistryException, IOException, JAXBException,
     1459                        ParseException {
     1460                final Principal principal = security.getUserPrincipal();
     1461                final List<Comment> comments = getRegistry(getStatus(userspace))
     1462                                .getCommentsInProfile(profileId, principal);
     1463                final String profileName = getRegistry(getStatus(userspace))
     1464                                .getProfileDescription(profileId).getName();
     1465                final RssCreatorComments instance = new RssCreatorComments(userspace,
     1466                                getApplicationBaseURI(), Integer.parseInt(limit), profileId,
     1467                                profileName, "profile", comments, Comment.COMPARE_ON_DATE);
     1468                final Rss rss = instance.getRss();
     1469                LOG.debug("Releasing RSS of {} most recent post on profile {}", limit,
     1470                                profileId);
     1471                return rss;
     1472        }
     1473
     1474        /**
     1475         *
     1476         * @param componentId
     1477         *            the Id of a component whose comments are to be rss-ed
     1478         * @param userspace
     1479         *            if "true" then profiles and components from the user's
     1480         *            workspace, otherwise -- public
     1481         * @param limit
     1482         *            the number of items to be displayed
     1483         * @return rss of the comments for a chosen component
     1484         * @throws ComponentRegistryException
     1485         * @throws IOException
     1486         * @throws JAXBException
     1487         * @throws ParseException
     1488         */
     1489        @Override
     1490        @GET
     1491        @Path("/components/{componentId}/comments/rss")
     1492        @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_XML,
     1493                        MediaType.APPLICATION_JSON })
     1494        public Rss getRssOfCommentsFromComponent(
     1495                        @PathParam("componentId") String componentId,
     1496                        @QueryParam(USERSPACE_PARAM) @DefaultValue("false") boolean userspace,
     1497                        @QueryParam(NUMBER_OF_RSSITEMS) @DefaultValue("20") String limit)
     1498                        throws ComponentRegistryException, IOException, JAXBException,
     1499                        ParseException {
     1500                final Principal principal = security.getUserPrincipal();
     1501                final List<Comment> comments = getRegistry(getStatus(userspace))
     1502                                .getCommentsInComponent(componentId, principal);
     1503                final String componentName = getRegistry(getStatus(userspace))
     1504                                .getComponentDescription(componentId).getName();
     1505                final RssCreatorComments instance = new RssCreatorComments(userspace,
     1506                                getApplicationBaseURI(), Integer.parseInt(limit), componentId,
     1507                                componentName, "component", comments, Comment.COMPARE_ON_DATE);
     1508                final Rss rss = instance.getRss();
     1509                LOG.debug("Releasing RSS of {} most recent post on component {}",
     1510                                limit, componentId);
     1511                return rss;
     1512        }
     1513
     1514        @Override
     1515        @GET
     1516        @Path("/AllowedTypes")
     1517        @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_XML,
     1518                        MediaType.APPLICATION_JSON })
     1519        public AllowedAttributetypesXML getAllowedAttributeTypes()
     1520                        throws ComponentRegistryException, IOException, JAXBException,
     1521                        ParseException {
     1522                return (new AllowedAttributetypesXML());
     1523        }
    11091524}
Note: See TracChangeset for help on using the changeset viewer.