Ignore:
Timestamp:
08/11/14 16:07:55 (10 years ago)
Author:
olhsha@mpi.nl
Message:

Added group service. Tested via the tomcat on loclahots (test URI and postman), old unit tests are adjusted and work well. Todo: retest on localhost tomcat, look at run-time exceptions, add new unit tests, adjust front-end

File:
1 edited

Legend:

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

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