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