Changeset 4168
- Timestamp:
- 12/09/13 10:23:33 (10 years ago)
- Location:
- ComponentRegistry/branches/ComponentRegistry-1.14.0/ComponentRegistry/src/main/java/clarin/cmdi/componentregistry/impl/database
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
ComponentRegistry/branches/ComponentRegistry-1.14.0/ComponentRegistry/src/main/java/clarin/cmdi/componentregistry/impl/database/ComponentRegistryDbImpl.java
r3660 r4168 55 55 * @author George.Georgovassilis@mpi.nl 56 56 */ 57 public class ComponentRegistryDbImpl extends ComponentRegistryImplBase 58 implements ComponentRegistry { 59 60 private final static Logger LOG = LoggerFactory 61 .getLogger(ComponentRegistryDbImpl.class); 62 private Owner registryOwner; 63 private ComponentStatus registryStatus; 64 @Autowired 65 private Configuration configuration; 66 @Autowired 67 @Qualifier("componentsCache") 68 private CMDComponentSpecCache componentsCache; 69 @Autowired 70 @Qualifier("profilesCache") 71 private CMDComponentSpecCache profilesCache; 72 // DAO's 73 @Autowired 74 private ProfileDescriptionDao profileDescriptionDao; 75 @Autowired 76 private ComponentDescriptionDao componentDescriptionDao; 77 @Autowired 78 private UserDao userDao; 79 @Autowired 80 private CommentsDao commentsDao; 81 @Autowired 82 private MDMarshaller marshaller; 83 @Autowired 84 private GroupService groupService; 85 86 /** 87 * Default constructor, to use this as a (spring) bean. The public registry 88 * by default. Use setStatus() and setOwner() to make it another kind of 89 * registry. 90 * 91 * @see setUser 92 */ 93 public ComponentRegistryDbImpl() throws TransformerException { 94 this.registryStatus = ComponentStatus.PUBLISHED; 95 } 96 97 /** 98 * Creates a new ComponentRegistry (either public or not) for the provided 99 * user. Only use for test and/or make sure to inject all dao's and other 100 * services 101 * 102 * @param userId 103 * User id of the user to create registry for. Pass null for 104 * public 105 */ 106 public ComponentRegistryDbImpl(ComponentStatus status, Owner owner) { 107 this.registryStatus = status; 108 this.registryOwner = owner; 109 } 110 111 @Override 112 public List<ProfileDescription> getProfileDescriptions() 113 throws ComponentRegistryException { 114 try { 115 switch (registryStatus) { 116 // TODO: support other status types 117 case PRIVATE: 118 if (registryOwner == null) { 119 throw new ComponentRegistryException( 120 "Private workspace without owner!"); 121 } 122 // TODO: Support group space 123 return profileDescriptionDao 124 .getUserspaceDescriptions(registryOwner.getId()); 125 case PUBLISHED: 126 return profileDescriptionDao.getPublicProfileDescriptions(); 127 default: 128 throw new ComponentRegistryException("Unsupported status type" 129 + registryStatus); 130 } 131 } catch (DataAccessException ex) { 132 throw new ComponentRegistryException( 133 "Database access error while trying to get profile descriptions", 134 ex); 135 } 136 } 137 138 @Override 139 public ProfileDescription getProfileDescription(String id) 140 throws ComponentRegistryException { 141 try { 142 return profileDescriptionDao.getByCmdId(id, getUserId()); 143 } catch (DataAccessException ex) { 144 throw new ComponentRegistryException( 145 "Database access error while trying to get profile description", 146 ex); 147 } 148 } 149 150 @Override 151 public List<ComponentDescription> getComponentDescriptions() 152 throws ComponentRegistryException { 153 try { 154 if (isPublic()) { 155 return componentDescriptionDao.getPublicComponentDescriptions(); 156 } else { 157 return componentDescriptionDao 158 .getUserspaceDescriptions(getUserId()); 159 } 160 } catch (DataAccessException ex) { 161 throw new ComponentRegistryException( 162 "Database access error while trying to get component descriptions", 163 ex); 164 } 165 } 166 167 @Override 168 public ComponentDescription getComponentDescription(String id) 169 throws ComponentRegistryException { 170 try { 171 return componentDescriptionDao.getByCmdId(id, getUserId()); 172 } catch (DataAccessException ex) { 173 throw new ComponentRegistryException( 174 "Database access error while trying to get component description", 175 ex); 176 } 177 } 178 179 @Override 180 public List<Comment> getCommentsInProfile(String profileId, 181 Principal principal) throws ComponentRegistryException { 182 try { 183 if (profileDescriptionDao.isInRegistry(profileId, getUserId())) { 184 final List<Comment> commentsFromProfile = commentsDao 185 .getCommentsFromProfile(profileId); 186 setCanDeleteInComments(commentsFromProfile, principal); 187 return commentsFromProfile; 188 } else { 189 // Profile does not exist (at least not in this registry) 190 throw new ComponentRegistryException("Profile " + profileId 191 + " does not exist in specified registry"); 192 } 193 } catch (DataAccessException ex) { 194 throw new ComponentRegistryException( 195 "Database access error while trying to get list of comments from profile", 196 ex); 197 } 198 } 199 200 @Override 201 public Comment getSpecifiedCommentInProfile(String profileId, 202 String commentId, Principal principal) 203 throws ComponentRegistryException { 204 try { 205 Comment comment = commentsDao 206 .getSpecifiedCommentFromProfile(commentId); 207 if (comment != null 208 && profileId.equals(comment.getProfileDescriptionId()) 209 && profileDescriptionDao.isInRegistry( 210 comment.getProfileDescriptionId(), getUserId())) { 211 setCanDeleteInComments(Collections.singleton(comment), 212 principal); 213 return comment; 214 } else { 215 // Comment exists in DB, but profile is not in this registry 216 throw new ComponentRegistryException("Comment " + commentId 217 + " cannot be found in specified registry"); 218 } 219 } catch (DataAccessException ex) { 220 throw new ComponentRegistryException( 221 "Database access error while trying to get comment from profile", 222 ex); 223 } 224 } 225 226 @Override 227 public List<Comment> getCommentsInComponent(String componentId, 228 Principal principal) throws ComponentRegistryException { 229 try { 230 if (componentDescriptionDao.isInRegistry(componentId, getUserId())) { 231 final List<Comment> commentsFromComponent = commentsDao 232 .getCommentsFromComponent(componentId); 233 setCanDeleteInComments(commentsFromComponent, principal); 234 return commentsFromComponent; 235 } else { 236 // Component does not exist (at least not in this registry) 237 throw new ComponentRegistryException("Component " + componentId 238 + " does not exist in specified registry"); 239 } 240 } catch (DataAccessException ex) { 241 throw new ComponentRegistryException( 242 "Database access error while trying to get list of comments from component", 243 ex); 244 } 245 } 246 247 @Override 248 public Comment getSpecifiedCommentInComponent(String componentId, 249 String commentId, Principal principal) 250 throws ComponentRegistryException { 251 try { 252 Comment comment = commentsDao 253 .getSpecifiedCommentFromComponent(commentId); 254 if (comment != null 255 && componentId.equals(comment.getComponentDescriptionId()) 256 && componentDescriptionDao.isInRegistry( 257 comment.getComponentDescriptionId(), getUserId())) { 258 setCanDeleteInComments(Collections.singleton(comment), 259 principal); 260 return comment; 261 } else { 262 // Comment does not exists in DB or component is not in this 263 // registry 264 throw new ComponentRegistryException( 265 "Comment " 266 + commentId 267 + " cannot be found in specified registry for specified component"); 268 } 269 } catch (DataAccessException ex) { 270 throw new ComponentRegistryException( 271 "Database access error while trying to get comment from component", 272 ex); 273 } 274 } 275 276 /** 277 * Sets the {@link Comment#setCanDelete(boolean) canDelete} property on all 278 * comments in the provided collection for the perspective of the specified 279 * principal. Comment owners (determined by {@link Comment#getUserId() }) and 280 * admins can delete, others cannot. 281 * 282 * @param comments 283 * comments to configure 284 * @param principal 285 * user to configure for 286 * @see Comment#isCanDelete() 287 */ 288 private void setCanDeleteInComments(Collection<Comment> comments, 289 Principal principal) { 290 if (principal != null && principal.getName() != null) { 291 final RegistryUser registryUser = userDao 292 .getByPrincipalName(principal.getName()); 293 final String registryUserId = registryUser == null ? null 294 : registryUser.getId().toString(); 295 final boolean isAdmin = registryUser != null 296 && configuration.isAdminUser(principal); 297 for (Comment comment : comments) { 298 comment.setCanDelete(isAdmin 299 || comment.getUserId().equals(registryUserId)); 300 } 301 } 302 } 303 304 @Override 305 public CMDComponentSpec getMDProfile(String id) 306 throws ComponentRegistryException { 307 if (inWorkspace(profileDescriptionDao, id)) { 308 CMDComponentSpec result = profilesCache.get(id); 309 if (result == null && !profilesCache.containsKey(id)) { 310 result = getUncachedMDProfile(id); 311 profilesCache.put(id, result); 312 } 313 return result; 314 } else { 315 // May exist, but not in this workspace 316 LOG.debug("Could not find profile '{}' in registry '{}'", 317 new Object[] { id, this.toString() }); 318 return null; 319 } 320 } 321 322 public CMDComponentSpec getUncachedMDProfile(String id) 323 throws ComponentRegistryException { 324 try { 325 return getUncachedMDComponent(id, profileDescriptionDao); 326 } catch (DataAccessException ex) { 327 throw new ComponentRegistryException( 328 "Database access error while trying to get profile", ex); 329 } 330 } 331 332 @Override 333 public CMDComponentSpec getMDComponent(String id) 334 throws ComponentRegistryException { 335 if (inWorkspace(componentDescriptionDao, id)) { 336 CMDComponentSpec result = componentsCache.get(id); 337 if (result == null && !componentsCache.containsKey(id)) { 338 result = getUncachedMDComponent(id); 339 componentsCache.put(id, result); 340 } 341 return result; 342 } else { 343 // May exist, but not in this workspace 344 LOG.info("Could not find component '{}' was in registry '{}'", 345 new Object[] { id, this.toString() }); 346 return null; 347 } 348 } 349 350 public CMDComponentSpec getUncachedMDComponent(String id) 351 throws ComponentRegistryException { 352 try { 353 return getUncachedMDComponent(id, componentDescriptionDao); 354 } catch (DataAccessException ex) { 355 throw new ComponentRegistryException( 356 "Database access error while trying to get component", ex); 357 } 358 } 359 360 @Override 361 public int register(AbstractDescription description, CMDComponentSpec spec) { 362 enrichSpecHeader(spec, description); 363 try { 364 String xml = componentSpecToString(spec); 365 // Convert principal name to user record id 366 Number uid = convertUserInDescription(description); 367 getDaoForDescription(description).insertDescription(description, 368 xml, isPublic(), uid); 369 invalidateCache(description); 370 return 0; 371 } catch (DataAccessException ex) { 372 LOG.error("Database error while registering component", ex); 373 return -1; 374 } catch (JAXBException ex) { 375 LOG.error("Error while registering component", ex); 376 return -2; 377 } catch (UnsupportedEncodingException ex) { 378 LOG.error("Error while registering component", ex); 379 return -3; 380 } 381 } 382 383 @Override 384 public int registerComment(Comment comment, String principalName) 385 throws ComponentRegistryException { 386 try { 387 if (comment.getComponentDescriptionId() != null 388 && componentDescriptionDao.isInRegistry( 389 comment.getComponentDescriptionId(), getUserId()) 390 || comment.getProfileDescriptionId() != null 391 && profileDescriptionDao.isInRegistry( 392 comment.getProfileDescriptionId(), getUserId())) { 393 // Convert principal name to user record id 394 Number uid = convertUserIdInComment(comment, principalName); 395 // Set date to current date 396 comment.setCommentDate(Comment.createNewDate()); 397 Number commentId = commentsDao.insertComment(comment, uid); 398 comment.setId(commentId.toString()); 399 } else { 400 throw new ComponentRegistryException( 401 "Cannot insert comment into this registry. Unknown profileId or componentId"); 402 } 403 return 0; 404 } catch (DataAccessException ex) { 405 LOG.error("Database error while registering component", ex); 406 return -1; 407 } 408 } 409 410 /** 411 * Calling service sets user id to principle. Our task is to convert this to 412 * an id for later reference. If none is set and this is a user's workspace, 413 * set from that user's id. 414 * 415 * It also sets the name in the description according to the display name in 416 * the database. 417 * 418 * @param description 419 * Description containing principle name as userId 420 * @return Id (from database) 421 * @throws DataAccessException 422 */ 423 private Number convertUserInDescription(AbstractDescription description) 424 throws DataAccessException { 425 Number uid = null; 426 String name = null; 427 if (description.getUserId() != null) { 428 RegistryUser user = userDao.getByPrincipalName(description 429 .getUserId()); 430 if (user != null) { 431 uid = user.getId(); 432 name = user.getName(); 433 } 434 } else { 435 uid = getUserId(); // this can be null as well 436 } 437 if (uid != null) { 438 description.setUserId(uid.toString()); 439 } 440 if (name != null) { 441 description.setCreatorName(name); 442 } 443 return uid; 444 } 445 446 /** 447 * Calling service sets user id to principle. Our task is to convert this to 448 * an id for later reference. If none is set and this is a user's workspace, 449 * set from that user's id. 450 * 451 * @param comment 452 * Comment containing principle name as userId 453 * @return Id (from database) 454 * @throws DataAccessException 455 */ 456 private Number convertUserIdInComment(Comment comment, String principalName) 457 throws DataAccessException, ComponentRegistryException { 458 if (principalName != null) { 459 RegistryUser user = userDao.getByPrincipalName(principalName); 460 if (user != null) { 461 Number id = user.getId(); 462 if (id != null) { 463 // Set user id in comment for convenience of calling method 464 comment.setUserId(id.toString()); 465 // Set name to user's preferred display name 466 comment.setUserName(user.getName()); 467 return id; 57 public class ComponentRegistryDbImpl extends ComponentRegistryImplBase implements ComponentRegistry { 58 59 private final static Logger LOG = LoggerFactory.getLogger(ComponentRegistryDbImpl.class); 60 private Owner registryOwner; 61 private ComponentStatus registryStatus; 62 @Autowired 63 private Configuration configuration; 64 @Autowired 65 @Qualifier("componentsCache") 66 private CMDComponentSpecCache componentsCache; 67 @Autowired 68 @Qualifier("profilesCache") 69 private CMDComponentSpecCache profilesCache; 70 // DAO's 71 @Autowired 72 private ProfileDescriptionDao profileDescriptionDao; 73 @Autowired 74 private ComponentDescriptionDao componentDescriptionDao; 75 @Autowired 76 private UserDao userDao; 77 @Autowired 78 private CommentsDao commentsDao; 79 @Autowired 80 private MDMarshaller marshaller; 81 @Autowired 82 private GroupService groupService; 83 84 /** 85 * Default constructor, to use this as a (spring) bean. The public registry 86 * by default. Use setStatus() and setOwner() to make it another kind of 87 * registry. 88 * 89 * @see setUser 90 */ 91 public ComponentRegistryDbImpl() throws TransformerException { 92 this.registryStatus = ComponentStatus.PUBLISHED; 93 } 94 95 /** 96 * Creates a new ComponentRegistry (either public or not) for the provided 97 * user. Only use for test and/or make sure to inject all dao's and other 98 * services 99 * 100 * @param userId 101 * User id of the user to create registry for. Pass null for 102 * public 103 */ 104 public ComponentRegistryDbImpl(ComponentStatus status, Owner owner) { 105 this.registryStatus = status; 106 this.registryOwner = owner; 107 } 108 109 @Override 110 public List<ProfileDescription> getProfileDescriptions() throws ComponentRegistryException { 111 try { 112 switch (registryStatus) { 113 // TODO: support other status types 114 case PRIVATE: 115 if (registryOwner == null) { 116 throw new ComponentRegistryException("Private workspace without owner!"); 117 } 118 // TODO: Support group space 119 return profileDescriptionDao.getUserspaceDescriptions(registryOwner.getId()); 120 case PUBLISHED: 121 return profileDescriptionDao.getPublicProfileDescriptions(); 122 default: 123 throw new ComponentRegistryException("Unsupported status type" + registryStatus); 124 } 125 } catch (DataAccessException ex) { 126 throw new ComponentRegistryException("Database access error while trying to get profile descriptions", ex); 127 } 128 } 129 130 @Override 131 public ProfileDescription getProfileDescription(String id) throws ComponentRegistryException { 132 try { 133 return profileDescriptionDao.getByCmdId(id, getUserId()); 134 } catch (DataAccessException ex) { 135 throw new ComponentRegistryException("Database access error while trying to get profile description", ex); 136 } 137 } 138 139 @Override 140 public List<ComponentDescription> getComponentDescriptions() throws ComponentRegistryException { 141 try { 142 if (isPublic()) { 143 return componentDescriptionDao.getPublicComponentDescriptions(); 144 } else { 145 return componentDescriptionDao.getUserspaceDescriptions(getUserId()); 146 } 147 } catch (DataAccessException ex) { 148 throw new ComponentRegistryException("Database access error while trying to get component descriptions", ex); 149 } 150 } 151 152 @Override 153 public ComponentDescription getComponentDescription(String id) throws ComponentRegistryException { 154 try { 155 return componentDescriptionDao.getByCmdId(id, getUserId()); 156 } catch (DataAccessException ex) { 157 throw new ComponentRegistryException("Database access error while trying to get component description", ex); 158 } 159 } 160 161 @Override 162 public List<Comment> getCommentsInProfile(String profileId, Principal principal) throws ComponentRegistryException { 163 try { 164 if (profileDescriptionDao.isInRegistry(profileId, getUserId())) { 165 final List<Comment> commentsFromProfile = commentsDao.getCommentsFromProfile(profileId); 166 setCanDeleteInComments(commentsFromProfile, principal); 167 return commentsFromProfile; 168 } else { 169 // Profile does not exist (at least not in this registry) 170 throw new ComponentRegistryException("Profile " + profileId + " does not exist in specified registry"); 171 } 172 } catch (DataAccessException ex) { 173 throw new ComponentRegistryException( 174 "Database access error while trying to get list of comments from profile", ex); 175 } 176 } 177 178 @Override 179 public Comment getSpecifiedCommentInProfile(String profileId, String commentId, Principal principal) 180 throws ComponentRegistryException { 181 try { 182 Comment comment = commentsDao.getSpecifiedCommentFromProfile(commentId); 183 if (comment != null && profileId.equals(comment.getProfileDescriptionId()) 184 && profileDescriptionDao.isInRegistry(comment.getProfileDescriptionId(), getUserId())) { 185 setCanDeleteInComments(Collections.singleton(comment), principal); 186 return comment; 187 } else { 188 // Comment exists in DB, but profile is not in this registry 189 throw new ComponentRegistryException("Comment " + commentId + " cannot be found in specified registry"); 190 } 191 } catch (DataAccessException ex) { 192 throw new ComponentRegistryException("Database access error while trying to get comment from profile", ex); 193 } 194 } 195 196 @Override 197 public List<Comment> getCommentsInComponent(String componentId, Principal principal) 198 throws ComponentRegistryException { 199 try { 200 if (componentDescriptionDao.isInRegistry(componentId, getUserId())) { 201 final List<Comment> commentsFromComponent = commentsDao.getCommentsFromComponent(componentId); 202 setCanDeleteInComments(commentsFromComponent, principal); 203 return commentsFromComponent; 204 } else { 205 // Component does not exist (at least not in this registry) 206 throw new ComponentRegistryException("Component " + componentId 207 + " does not exist in specified registry"); 208 } 209 } catch (DataAccessException ex) { 210 throw new ComponentRegistryException( 211 "Database access error while trying to get list of comments from component", ex); 212 } 213 } 214 215 @Override 216 public Comment getSpecifiedCommentInComponent(String componentId, String commentId, Principal principal) 217 throws ComponentRegistryException { 218 try { 219 Comment comment = commentsDao.getSpecifiedCommentFromComponent(commentId); 220 if (comment != null && componentId.equals(comment.getComponentDescriptionId()) 221 && componentDescriptionDao.isInRegistry(comment.getComponentDescriptionId(), getUserId())) { 222 setCanDeleteInComments(Collections.singleton(comment), principal); 223 return comment; 224 } else { 225 // Comment does not exists in DB or component is not in this 226 // registry 227 throw new ComponentRegistryException("Comment " + commentId 228 + " cannot be found in specified registry for specified component"); 229 } 230 } catch (DataAccessException ex) { 231 throw new ComponentRegistryException("Database access error while trying to get comment from component", ex); 232 } 233 } 234 235 /** 236 * Sets the {@link Comment#setCanDelete(boolean) canDelete} property on all 237 * comments in the provided collection for the perspective of the specified 238 * principal. Comment owners (determined by {@link Comment#getUserId() }) and 239 * admins can delete, others cannot. 240 * 241 * @param comments 242 * comments to configure 243 * @param principal 244 * user to configure for 245 * @see Comment#isCanDelete() 246 */ 247 private void setCanDeleteInComments(Collection<Comment> comments, Principal principal) { 248 if (principal != null && principal.getName() != null) { 249 final RegistryUser registryUser = userDao.getByPrincipalName(principal.getName()); 250 final String registryUserId = registryUser == null ? null : registryUser.getId().toString(); 251 final boolean isAdmin = registryUser != null && configuration.isAdminUser(principal); 252 for (Comment comment : comments) { 253 comment.setCanDelete(isAdmin || comment.getUserId().equals(registryUserId)); 254 } 255 } 256 } 257 258 @Override 259 public CMDComponentSpec getMDProfile(String id) throws ComponentRegistryException { 260 if (inWorkspace(profileDescriptionDao, id)||canCurrentUserAccessDescription(profileDescriptionDao, id)) { 261 CMDComponentSpec result = profilesCache.get(id); 262 if (result == null && !profilesCache.containsKey(id)) { 263 result = getUncachedMDProfile(id); 264 profilesCache.put(id, result); 265 } 266 return result; 468 267 } else { 469 throw new ComponentRegistryException( 470 "Cannot find user with principal name: " 471 + principalName); 472 } 473 } 474 } 475 return null; 476 } 477 478 @Override 479 public int update(AbstractDescription description, CMDComponentSpec spec, 480 Principal principal, boolean forceUpdate) { 481 try { 482 checkAuthorisation(description, principal); 483 checkAge(description, principal); 484 // For public components, check if used in other components or 485 // profiles (unless forced) 486 if (!forceUpdate && this.isPublic() && !description.isProfile()) { 487 checkStillUsed(description.getId()); 488 } 489 AbstractDescriptionDao<?> dao = getDaoForDescription(description); 490 dao.updateDescription(getIdForDescription(description), 491 description, componentSpecToString(spec)); 492 invalidateCache(description); 493 return 0; 494 } catch (JAXBException ex) { 495 LOG.error("Error while updating component", ex); 496 return -1; 497 } catch (UnsupportedEncodingException ex) { 498 LOG.error("Error while updating component", ex); 499 return -1; 500 } catch (IllegalArgumentException ex) { 501 LOG.error("Error while updating component", ex); 502 return -1; 503 } catch (UserUnauthorizedException e) { 504 LOG.error("Error while updating component", e); 505 return -1; 506 } catch (DeleteFailedException e) { 507 LOG.error("Error while updating component", e); 508 return -1; 509 } catch (ComponentRegistryException e) { 510 LOG.error("Error while updating component", e); 511 return -1; 512 } 513 } 514 515 @Override 516 public int publish(AbstractDescription desc, CMDComponentSpec spec, 517 Principal principal) { 518 int result = 0; 519 AbstractDescriptionDao<?> dao = getDaoForDescription(desc); 520 if (!isPublic()) { // if already in public workspace there is nothing 521 // todo 522 desc.setHref(AbstractDescription.createPublicHref(desc.getHref())); 523 Number id = getIdForDescription(desc); 524 try { 525 // Update description & content 526 dao.updateDescription(id, desc, componentSpecToString(spec)); 527 // Set to public 528 dao.setPublished(id, true); 529 } catch (DataAccessException ex) { 530 LOG.error("Database error while updating component", ex); 531 return -1; 532 } catch (JAXBException ex) { 533 LOG.error("Error while updating component", ex); 534 return -2; 535 } catch (UnsupportedEncodingException ex) { 536 LOG.error("Error while updating component", ex); 537 return -3; 538 } 539 } 540 return result; 541 } 542 543 @Override 544 public void getMDProfileAsXml(String profileId, OutputStream output) 545 throws ComponentRegistryException { 546 CMDComponentSpec expandedSpec = CMDComponentSpecExpanderDbImpl 547 .expandProfile(profileId, this); 548 writeXml(expandedSpec, output); 549 } 550 551 @Override 552 public void getMDProfileAsXsd(String profileId, OutputStream outputStream) 553 throws ComponentRegistryException { 554 CMDComponentSpec expandedSpec = CMDComponentSpecExpanderDbImpl 555 .expandProfile(profileId, this); 556 writeXsd(expandedSpec, outputStream); 557 } 558 559 @Override 560 public void getMDComponentAsXml(String componentId, OutputStream output) 561 throws ComponentRegistryException { 562 CMDComponentSpec expandedSpec = CMDComponentSpecExpanderDbImpl 563 .expandComponent(componentId, this); 564 writeXml(expandedSpec, output); 565 } 566 567 @Override 568 public void getMDComponentAsXsd(String componentId, 569 OutputStream outputStream) throws ComponentRegistryException { 570 CMDComponentSpec expandedSpec = CMDComponentSpecExpanderDbImpl 571 .expandComponent(componentId, this); 572 writeXsd(expandedSpec, outputStream); 573 } 574 575 @Override 576 public void deleteMDProfile(String profileId, Principal principal) 577 throws UserUnauthorizedException, DeleteFailedException, 578 ComponentRegistryException { 579 ProfileDescription desc = getProfileDescription(profileId); 580 if (desc != null) { 581 try { 582 checkAuthorisation(desc, principal); 583 checkAge(desc, principal); 584 profileDescriptionDao.setDeleted(desc, true); 585 invalidateCache(desc); 586 } catch (DataAccessException ex) { 587 throw new DeleteFailedException( 588 "Database access error while trying to delete profile", 589 ex); 590 } 591 } 592 } 593 594 @Override 595 public void deleteMDComponent(String componentId, Principal principal, 596 boolean forceDelete) throws UserUnauthorizedException, 597 DeleteFailedException, ComponentRegistryException { 598 ComponentDescription desc = componentDescriptionDao 599 .getByCmdId(componentId); 600 if (desc != null) { 601 try { 602 checkAuthorisation(desc, principal); 603 checkAge(desc, principal); 604 605 if (!forceDelete) { 606 checkStillUsed(componentId); 607 } 608 componentDescriptionDao.setDeleted(desc, true); 609 invalidateCache(desc); 610 } catch (DataAccessException ex) { 611 throw new DeleteFailedException( 612 "Database access error while trying to delete component", 613 ex); 614 } 615 } 616 } 617 618 /** 619 * 620 * @return whether this is the public registry 621 * @deprecated use {@link #getStatus() } to check if this is the 622 * {@link ComponentStatus#PUBLISHED public registry} 623 */ 624 @Override 625 @Deprecated 626 public boolean isPublic() { 627 return registryStatus == ComponentStatus.PUBLISHED; 628 } 629 630 /** 631 * @return The user id, or null if there is no owner or it is not a user. 632 */ 633 private Number getUserId() { 634 if (registryOwner instanceof OwnerUser) { 635 return registryOwner.getId(); 636 } else { 637 return null; 638 } 639 } 640 641 @Override 642 public Owner getOwner() { 643 return registryOwner; 644 } 645 646 /** 647 * Sets status and owner of this registry 648 * 649 * @param status 650 * new status for registry 651 * @param owner 652 * new owner for registry 653 */ 654 public void setStatus(ComponentStatus status, Owner owner) { 655 setStatus(status); 656 this.registryOwner = owner; 657 } 658 659 public void setStatus(ComponentStatus status) { 660 this.registryStatus = status; 661 } 662 663 @Override 664 public ComponentStatus getStatus() { 665 return registryStatus; 666 } 667 668 private void invalidateCache(AbstractDescription description) { 669 if (description.isProfile()) { 670 profilesCache.remove(description.getId()); 671 } else { 672 componentsCache.remove(description.getId()); 673 } 674 } 675 676 private AbstractDescriptionDao<?> getDaoForDescription( 677 AbstractDescription description) { 678 return description.isProfile() ? profileDescriptionDao 679 : componentDescriptionDao; 680 } 681 682 /** 683 * Looks up description on basis of CMD Id. This will also check if such a 684 * record even exists. 685 * 686 * @param description 687 * Description to look up 688 * @return Database id for description 689 * @throws IllegalArgumentException 690 * If description with non-existing id is passed 691 */ 692 private Number getIdForDescription(AbstractDescription description) 693 throws IllegalArgumentException { 694 Number dbId = null; 695 AbstractDescriptionDao<?> dao = getDaoForDescription(description); 696 try { 697 dbId = dao.getDbId(description.getId()); 698 } catch (DataAccessException ex) { 699 LOG.error( 700 "Error getting dbId for component with id " 701 + description.getId(), ex); 702 } 703 if (dbId == null) { 704 throw new IllegalArgumentException( 705 "Could not get database Id for description"); 706 } else { 707 return dbId; 708 } 709 } 710 711 private String componentSpecToString(CMDComponentSpec spec) 712 throws UnsupportedEncodingException, JAXBException { 713 ByteArrayOutputStream os = new ByteArrayOutputStream(); 714 getMarshaller().marshal(spec, os); 715 String xml = os.toString("UTF-8"); 716 return xml; 717 } 718 719 private CMDComponentSpec getUncachedMDComponent(String id, 720 AbstractDescriptionDao dao) { 721 String xml = dao.getContent(false, id); 722 if (xml != null) { 723 try { 724 InputStream is = new ByteArrayInputStream(xml.getBytes("UTF-8")); 725 return getMarshaller().unmarshal(CMDComponentSpec.class, is, 726 null); 727 728 } catch (JAXBException ex) { 729 LOG.error("Error while unmarshalling", ex); 730 } catch (UnsupportedEncodingException ex) { 731 LOG.error("Exception while reading XML from database", ex); 732 } 733 } 734 return null; 735 } 736 737 private void checkAuthorisation(AbstractDescription desc, 738 Principal principal) throws UserUnauthorizedException { 739 if (!isOwnerOfDescription(desc, principal.getName()) 740 && !configuration.isAdminUser(principal)) { 741 throw new UserUnauthorizedException("Unauthorized operation user '" 742 + principal.getName() 743 + "' is not the creator (nor an administrator) of the " 744 + (desc.isProfile() ? "profile" : "component") + "(" + desc 745 + ")."); 746 } 747 } 748 749 private void checkAuthorisationComment(Comment desc, Principal principal) 750 throws UserUnauthorizedException { 751 if (!isOwnerOfComment(desc, principal.getName()) 752 && !configuration.isAdminUser(principal)) { 753 throw new UserUnauthorizedException("Unauthorized operation user '" 754 + principal.getName() 755 + "' is not the creator (nor an administrator) of the " 756 + (desc.getId()) + "(" + desc + ")."); 757 } 758 } 759 760 private boolean isOwnerOfDescription(AbstractDescription desc, 761 String principalName) { 762 String owner = getDaoForDescription(desc).getOwnerPrincipalName( 763 getIdForDescription(desc)); 764 return owner != null // If owner is null, no one can be owner 765 && principalName.equals(owner); 766 } 767 768 private boolean isOwnerOfComment(Comment com, String principalName) { 769 String owner = commentsDao.getOwnerPrincipalName(Integer.parseInt(com 770 .getId())); 771 return owner != null // If owner is null, no one can be owner 772 && principalName.equals(owner); 773 } 774 775 private void checkAge(AbstractDescription desc, Principal principal) 776 throws DeleteFailedException { 777 if (isPublic() && !configuration.isAdminUser(principal)) { 778 try { 779 Date regDate = AbstractDescription.getDate(desc 780 .getRegistrationDate()); 781 Calendar calendar = Calendar.getInstance(); 782 calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1); 783 if (regDate.before(calendar.getTime())) { // More then month old 784 throw new DeleteFailedException( 785 "The " 786 + (desc.isProfile() ? "Profile" 787 : "Component") 788 + " is more then a month old and cannot be deleted anymore. It might have been used to create metadata, deleting it would invalidate that metadata."); 789 } 790 } catch (ParseException e) { 791 LOG.error("Cannot parse date of " + desc + " Error:" + e); 792 } 793 } 794 } 795 796 private boolean inWorkspace(AbstractDescriptionDao<?> dao, String cmdId) { 797 if (isPublic()) { 798 return dao.isPublic(cmdId); 799 } else { 800 return dao.isInUserSpace(cmdId, getUserId()); 801 } 802 } 803 804 @Override 805 public String getName() { 806 if (isPublic()) { 807 return ComponentRegistry.PUBLIC_NAME; 808 } else { 809 return "Registry of " + userDao.getById(getUserId()).getName(); 810 } 811 } 812 813 @Override 814 public List<ProfileDescription> getDeletedProfileDescriptions() { 815 return profileDescriptionDao.getDeletedDescriptions(getUserId()); 816 } 817 818 @Override 819 public List<ComponentDescription> getDeletedComponentDescriptions() { 820 return componentDescriptionDao.getDeletedDescriptions(getUserId()); 821 } 822 823 @Override 824 public void deleteComment(String commentId, Principal principal) 825 throws IOException, ComponentRegistryException, 826 UserUnauthorizedException, DeleteFailedException { 827 try { 828 Comment comment = commentsDao.getById(Integer.parseInt(commentId)); 829 if (comment != null 830 // Comment must have an existing (in this registry) 831 // componentId or profileId 832 && (comment.getComponentDescriptionId() != null 833 && componentDescriptionDao.isInRegistry( 834 comment.getComponentDescriptionId(), 835 getUserId()) || comment 836 .getProfileDescriptionId() != null 837 && profileDescriptionDao.isInRegistry( 838 comment.getProfileDescriptionId(), 839 getUserId()))) { 840 checkAuthorisationComment(comment, principal); 841 commentsDao.deleteComment(comment); 842 } else { 843 // Comment exists in DB, but component is not in this registry 844 throw new ComponentRegistryException("Comment " + commentId 845 + " cannot be found in specified registry"); 846 } 847 } catch (DataAccessException ex) { 848 throw new DeleteFailedException( 849 "Database access error while trying to delete component", 850 ex); 851 } catch (NumberFormatException ex) { 852 throw new DeleteFailedException( 853 "Illegal comment ID, cannot parse integer", ex); 854 } 855 } 856 857 @Override 858 public CMDComponentSpecExpander getExpander() { 859 return new CMDComponentSpecExpanderDbImpl(this); 860 } 861 862 @Override 863 protected MDMarshaller getMarshaller() { 864 return marshaller; 865 } 866 867 @Override 868 public String toString() { 869 return getName(); 870 } 871 872 @Override 873 public List<ComponentDescription> getComponentDescriptionsInGroup( 874 String principalName, String groupId) throws ComponentRegistryException { 875 List<String> componentIds = groupService.getComponentIdsInGroup(Long.parseLong(groupId)); 876 List<ComponentDescription> components = new ArrayList<ComponentDescription>(); 877 for (String id:componentIds) { 878 ComponentDescription componentDescription = getComponentDescription(id); 879 //minor robustness consideration: if, for whatever reason, the component for an ownership has been removed, don't return a null but just skip it 880 if (componentDescription!=null) 881 components.add(componentDescription); 882 } 883 return components; 884 } 885 886 @Override 887 public List<ProfileDescription> getProfileDescriptionsForMetadaEditor( 888 String groupId) throws ComponentRegistryException { 889 List<String> componentIds = groupService.getProfileIdsInGroup(Long.parseLong(groupId)); 890 List<ProfileDescription> profiles = new ArrayList<ProfileDescription>(); 891 for (String id:componentIds) { 892 ProfileDescription profile = getProfileDescription(id); 893 if (profile!=null) 894 profiles.add(profile); 895 } 896 return profiles; 897 } 898 899 @Override 900 public List<ProfileDescription> getProfileDescriptionsInGroup(String groupId) 901 throws ComponentRegistryException { 902 List<String> componentIds = groupService.getProfileIdsInGroup(Long.parseLong(groupId)); 903 List<ProfileDescription> profiles = new ArrayList<ProfileDescription>(); 904 for (String id:componentIds) 905 profiles.add(getProfileDescription(id)); 906 return profiles; 907 } 268 // May exist, but not in this workspace 269 LOG.debug("Could not find profile '{}' in registry '{}'", new Object[] { id, this.toString() }); 270 return null; 271 } 272 } 273 274 public CMDComponentSpec getUncachedMDProfile(String id) throws ComponentRegistryException { 275 try { 276 return getUncachedMDComponent(id, profileDescriptionDao); 277 } catch (DataAccessException ex) { 278 throw new ComponentRegistryException("Database access error while trying to get profile", ex); 279 } 280 } 281 282 @Override 283 public CMDComponentSpec getMDComponent(String id) throws ComponentRegistryException { 284 if (inWorkspace(componentDescriptionDao, id)||canCurrentUserAccessDescription(componentDescriptionDao, id)) { 285 CMDComponentSpec result = componentsCache.get(id); 286 if (result == null && !componentsCache.containsKey(id)) { 287 result = getUncachedMDComponent(id); 288 componentsCache.put(id, result); 289 } 290 return result; 291 } else { 292 // May exist, but not in this workspace 293 LOG.info("Could not find component '{}' was in registry '{}'", new Object[] { id, this.toString() }); 294 return null; 295 } 296 } 297 298 public CMDComponentSpec getUncachedMDComponent(String id) throws ComponentRegistryException { 299 try { 300 return getUncachedMDComponent(id, componentDescriptionDao); 301 } catch (DataAccessException ex) { 302 throw new ComponentRegistryException("Database access error while trying to get component", ex); 303 } 304 } 305 306 @Override 307 public int register(AbstractDescription description, CMDComponentSpec spec) { 308 enrichSpecHeader(spec, description); 309 try { 310 String xml = componentSpecToString(spec); 311 // Convert principal name to user record id 312 Number uid = convertUserInDescription(description); 313 getDaoForDescription(description).insertDescription(description, xml, isPublic(), uid); 314 invalidateCache(description); 315 return 0; 316 } catch (DataAccessException ex) { 317 LOG.error("Database error while registering component", ex); 318 return -1; 319 } catch (JAXBException ex) { 320 LOG.error("Error while registering component", ex); 321 return -2; 322 } catch (UnsupportedEncodingException ex) { 323 LOG.error("Error while registering component", ex); 324 return -3; 325 } 326 } 327 328 @Override 329 public int registerComment(Comment comment, String principalName) throws ComponentRegistryException { 330 try { 331 if (comment.getComponentDescriptionId() != null 332 && componentDescriptionDao.isInRegistry(comment.getComponentDescriptionId(), getUserId()) 333 || comment.getProfileDescriptionId() != null 334 && profileDescriptionDao.isInRegistry(comment.getProfileDescriptionId(), getUserId())) { 335 // Convert principal name to user record id 336 Number uid = convertUserIdInComment(comment, principalName); 337 // Set date to current date 338 comment.setCommentDate(Comment.createNewDate()); 339 Number commentId = commentsDao.insertComment(comment, uid); 340 comment.setId(commentId.toString()); 341 } else { 342 throw new ComponentRegistryException( 343 "Cannot insert comment into this registry. Unknown profileId or componentId"); 344 } 345 return 0; 346 } catch (DataAccessException ex) { 347 LOG.error("Database error while registering component", ex); 348 return -1; 349 } 350 } 351 352 /** 353 * Calling service sets user id to principle. Our task is to convert this to 354 * an id for later reference. If none is set and this is a user's workspace, 355 * set from that user's id. 356 * 357 * It also sets the name in the description according to the display name in 358 * the database. 359 * 360 * @param description 361 * Description containing principle name as userId 362 * @return Id (from database) 363 * @throws DataAccessException 364 */ 365 private Number convertUserInDescription(AbstractDescription description) throws DataAccessException { 366 Number uid = null; 367 String name = null; 368 if (description.getUserId() != null) { 369 RegistryUser user = userDao.getByPrincipalName(description.getUserId()); 370 if (user != null) { 371 uid = user.getId(); 372 name = user.getName(); 373 } 374 } else { 375 uid = getUserId(); // this can be null as well 376 } 377 if (uid != null) { 378 description.setUserId(uid.toString()); 379 } 380 if (name != null) { 381 description.setCreatorName(name); 382 } 383 return uid; 384 } 385 386 /** 387 * Calling service sets user id to principle. Our task is to convert this to 388 * an id for later reference. If none is set and this is a user's workspace, 389 * set from that user's id. 390 * 391 * @param comment 392 * Comment containing principle name as userId 393 * @return Id (from database) 394 * @throws DataAccessException 395 */ 396 private Number convertUserIdInComment(Comment comment, String principalName) throws DataAccessException, 397 ComponentRegistryException { 398 if (principalName != null) { 399 RegistryUser user = userDao.getByPrincipalName(principalName); 400 if (user != null) { 401 Number id = user.getId(); 402 if (id != null) { 403 // Set user id in comment for convenience of calling method 404 comment.setUserId(id.toString()); 405 // Set name to user's preferred display name 406 comment.setUserName(user.getName()); 407 return id; 408 } else { 409 throw new ComponentRegistryException("Cannot find user with principal name: " + principalName); 410 } 411 } 412 } 413 return null; 414 } 415 416 @Override 417 public int update(AbstractDescription description, CMDComponentSpec spec, Principal principal, boolean forceUpdate) { 418 try { 419 checkAuthorisation(description, principal); 420 checkAge(description, principal); 421 // For public components, check if used in other components or 422 // profiles (unless forced) 423 if (!forceUpdate && this.isPublic() && !description.isProfile()) { 424 checkStillUsed(description.getId()); 425 } 426 AbstractDescriptionDao<?> dao = getDaoForDescription(description); 427 dao.updateDescription(getIdForDescription(description), description, componentSpecToString(spec)); 428 invalidateCache(description); 429 return 0; 430 } catch (JAXBException ex) { 431 LOG.error("Error while updating component", ex); 432 return -1; 433 } catch (UnsupportedEncodingException ex) { 434 LOG.error("Error while updating component", ex); 435 return -1; 436 } catch (IllegalArgumentException ex) { 437 LOG.error("Error while updating component", ex); 438 return -1; 439 } catch (UserUnauthorizedException e) { 440 LOG.error("Error while updating component", e); 441 return -1; 442 } catch (DeleteFailedException e) { 443 LOG.error("Error while updating component", e); 444 return -1; 445 } catch (ComponentRegistryException e) { 446 LOG.error("Error while updating component", e); 447 return -1; 448 } 449 } 450 451 @Override 452 public int publish(AbstractDescription desc, CMDComponentSpec spec, Principal principal) { 453 int result = 0; 454 AbstractDescriptionDao<?> dao = getDaoForDescription(desc); 455 if (!isPublic()) { // if already in public workspace there is nothing 456 // todo 457 desc.setHref(AbstractDescription.createPublicHref(desc.getHref())); 458 Number id = getIdForDescription(desc); 459 try { 460 // Update description & content 461 dao.updateDescription(id, desc, componentSpecToString(spec)); 462 // Set to public 463 dao.setPublished(id, true); 464 } catch (DataAccessException ex) { 465 LOG.error("Database error while updating component", ex); 466 return -1; 467 } catch (JAXBException ex) { 468 LOG.error("Error while updating component", ex); 469 return -2; 470 } catch (UnsupportedEncodingException ex) { 471 LOG.error("Error while updating component", ex); 472 return -3; 473 } 474 } 475 return result; 476 } 477 478 @Override 479 public void getMDProfileAsXml(String profileId, OutputStream output) throws ComponentRegistryException { 480 CMDComponentSpec expandedSpec = CMDComponentSpecExpanderDbImpl.expandProfile(profileId, this); 481 writeXml(expandedSpec, output); 482 } 483 484 @Override 485 public void getMDProfileAsXsd(String profileId, OutputStream outputStream) throws ComponentRegistryException { 486 CMDComponentSpec expandedSpec = CMDComponentSpecExpanderDbImpl.expandProfile(profileId, this); 487 writeXsd(expandedSpec, outputStream); 488 } 489 490 @Override 491 public void getMDComponentAsXml(String componentId, OutputStream output) throws ComponentRegistryException { 492 CMDComponentSpec expandedSpec = CMDComponentSpecExpanderDbImpl.expandComponent(componentId, this); 493 writeXml(expandedSpec, output); 494 } 495 496 @Override 497 public void getMDComponentAsXsd(String componentId, OutputStream outputStream) throws ComponentRegistryException { 498 CMDComponentSpec expandedSpec = CMDComponentSpecExpanderDbImpl.expandComponent(componentId, this); 499 writeXsd(expandedSpec, outputStream); 500 } 501 502 @Override 503 public void deleteMDProfile(String profileId, Principal principal) throws UserUnauthorizedException, 504 DeleteFailedException, ComponentRegistryException { 505 ProfileDescription desc = getProfileDescription(profileId); 506 if (desc != null) { 507 try { 508 checkAuthorisation(desc, principal); 509 checkAge(desc, principal); 510 profileDescriptionDao.setDeleted(desc, true); 511 invalidateCache(desc); 512 } catch (DataAccessException ex) { 513 throw new DeleteFailedException("Database access error while trying to delete profile", ex); 514 } 515 } 516 } 517 518 @Override 519 public void deleteMDComponent(String componentId, Principal principal, boolean forceDelete) 520 throws UserUnauthorizedException, DeleteFailedException, ComponentRegistryException { 521 ComponentDescription desc = componentDescriptionDao.getByCmdId(componentId); 522 if (desc != null) { 523 try { 524 checkAuthorisation(desc, principal); 525 checkAge(desc, principal); 526 527 if (!forceDelete) { 528 checkStillUsed(componentId); 529 } 530 componentDescriptionDao.setDeleted(desc, true); 531 invalidateCache(desc); 532 } catch (DataAccessException ex) { 533 throw new DeleteFailedException("Database access error while trying to delete component", ex); 534 } 535 } 536 } 537 538 /** 539 * 540 * @return whether this is the public registry 541 * @deprecated use {@link #getStatus() } to check if this is the 542 * {@link ComponentStatus#PUBLISHED public registry} 543 */ 544 @Override 545 @Deprecated 546 public boolean isPublic() { 547 return registryStatus == ComponentStatus.PUBLISHED; 548 } 549 550 /** 551 * @return The user id, or null if there is no owner or it is not a user. 552 */ 553 private Number getUserId() { 554 if (registryOwner instanceof OwnerUser) { 555 return registryOwner.getId(); 556 } else { 557 return null; 558 } 559 } 560 561 @Override 562 public Owner getOwner() { 563 return registryOwner; 564 } 565 566 /** 567 * Sets status and owner of this registry 568 * 569 * @param status 570 * new status for registry 571 * @param owner 572 * new owner for registry 573 */ 574 public void setStatus(ComponentStatus status, Owner owner) { 575 setStatus(status); 576 this.registryOwner = owner; 577 } 578 579 public void setStatus(ComponentStatus status) { 580 this.registryStatus = status; 581 } 582 583 @Override 584 public ComponentStatus getStatus() { 585 return registryStatus; 586 } 587 588 private void invalidateCache(AbstractDescription description) { 589 if (description.isProfile()) { 590 profilesCache.remove(description.getId()); 591 } else { 592 componentsCache.remove(description.getId()); 593 } 594 } 595 596 private AbstractDescriptionDao<?> getDaoForDescription(AbstractDescription description) { 597 return description.isProfile() ? profileDescriptionDao : componentDescriptionDao; 598 } 599 600 /** 601 * Looks up description on basis of CMD Id. This will also check if such a 602 * record even exists. 603 * 604 * @param description 605 * Description to look up 606 * @return Database id for description 607 * @throws IllegalArgumentException 608 * If description with non-existing id is passed 609 */ 610 private Number getIdForDescription(AbstractDescription description) throws IllegalArgumentException { 611 Number dbId = null; 612 AbstractDescriptionDao<?> dao = getDaoForDescription(description); 613 try { 614 dbId = dao.getDbId(description.getId()); 615 } catch (DataAccessException ex) { 616 LOG.error("Error getting dbId for component with id " + description.getId(), ex); 617 } 618 if (dbId == null) { 619 throw new IllegalArgumentException("Could not get database Id for description"); 620 } else { 621 return dbId; 622 } 623 } 624 625 private String componentSpecToString(CMDComponentSpec spec) throws UnsupportedEncodingException, JAXBException { 626 ByteArrayOutputStream os = new ByteArrayOutputStream(); 627 getMarshaller().marshal(spec, os); 628 String xml = os.toString("UTF-8"); 629 return xml; 630 } 631 632 private CMDComponentSpec getUncachedMDComponent(String id, AbstractDescriptionDao dao) { 633 String xml = dao.getContent(false, id); 634 if (xml != null) { 635 try { 636 InputStream is = new ByteArrayInputStream(xml.getBytes("UTF-8")); 637 return getMarshaller().unmarshal(CMDComponentSpec.class, is, null); 638 639 } catch (JAXBException ex) { 640 LOG.error("Error while unmarshalling", ex); 641 } catch (UnsupportedEncodingException ex) { 642 LOG.error("Exception while reading XML from database", ex); 643 } 644 } 645 return null; 646 } 647 648 private void checkAuthorisation(AbstractDescription desc, Principal principal) throws UserUnauthorizedException { 649 if (!isOwnerOfDescription(desc, principal.getName()) && !configuration.isAdminUser(principal)) { 650 throw new UserUnauthorizedException("Unauthorized operation user '" + principal.getName() 651 + "' is not the creator (nor an administrator) of the " 652 + (desc.isProfile() ? "profile" : "component") + "(" + desc + ")."); 653 } 654 } 655 656 private void checkAuthorisationComment(Comment desc, Principal principal) throws UserUnauthorizedException { 657 if (!isOwnerOfComment(desc, principal.getName()) && !configuration.isAdminUser(principal)) { 658 throw new UserUnauthorizedException("Unauthorized operation user '" + principal.getName() 659 + "' is not the creator (nor an administrator) of the " + (desc.getId()) + "(" + desc + ")."); 660 } 661 } 662 663 private boolean isOwnerOfDescription(AbstractDescription desc, String principalName) { 664 String owner = getDaoForDescription(desc).getOwnerPrincipalName(getIdForDescription(desc)); 665 return owner != null // If owner is null, no one can be owner 666 && principalName.equals(owner); 667 } 668 669 private boolean isOwnerOfComment(Comment com, String principalName) { 670 String owner = commentsDao.getOwnerPrincipalName(Integer.parseInt(com.getId())); 671 return owner != null // If owner is null, no one can be owner 672 && principalName.equals(owner); 673 } 674 675 private void checkAge(AbstractDescription desc, Principal principal) throws DeleteFailedException { 676 if (isPublic() && !configuration.isAdminUser(principal)) { 677 try { 678 Date regDate = AbstractDescription.getDate(desc.getRegistrationDate()); 679 Calendar calendar = Calendar.getInstance(); 680 calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1); 681 if (regDate.before(calendar.getTime())) { // More then month old 682 throw new DeleteFailedException( 683 "The " 684 + (desc.isProfile() ? "Profile" : "Component") 685 + " is more then a month old and cannot be deleted anymore. It might have been used to create metadata, deleting it would invalidate that metadata."); 686 } 687 } catch (ParseException e) { 688 LOG.error("Cannot parse date of " + desc + " Error:" + e); 689 } 690 } 691 } 692 693 private boolean inWorkspace(AbstractDescriptionDao<?> dao, String cmdId) { 694 if (isPublic()) { 695 return dao.isPublic(cmdId); 696 } else { 697 return dao.isInUserSpace(cmdId, getUserId()); 698 } 699 } 700 701 private boolean canCurrentUserAccessDescription(AbstractDescriptionDao<?> dao, String cmdId) { 702 if (cmdId == null) 703 return false; 704 RegistryUser user = userDao.getById(getUserId()); 705 if (user == null) 706 return false; 707 AbstractDescription description = dao.getByCmdId(cmdId); 708 if (description == null) 709 return false; 710 if (cmdId.startsWith(ComponentDescription.COMPONENT_PREFIX)){ 711 return groupService.canUserAccessComponentEitherOnHisOwnOrThroughGroupMembership(user, (ComponentDescription)description); 712 } 713 if (cmdId.startsWith(ProfileDescription.PROFILE_PREFIX)){ 714 return groupService.canUserAccessProfileEitherOnHisOwnOrThroughGroupMembership(user, (ProfileDescription)description); 715 } 716 return false; 717 } 718 719 @Override 720 public String getName() { 721 if (isPublic()) { 722 return ComponentRegistry.PUBLIC_NAME; 723 } else { 724 return "Registry of " + userDao.getById(getUserId()).getName(); 725 } 726 } 727 728 @Override 729 public List<ProfileDescription> getDeletedProfileDescriptions() { 730 return profileDescriptionDao.getDeletedDescriptions(getUserId()); 731 } 732 733 @Override 734 public List<ComponentDescription> getDeletedComponentDescriptions() { 735 return componentDescriptionDao.getDeletedDescriptions(getUserId()); 736 } 737 738 @Override 739 public void deleteComment(String commentId, Principal principal) throws IOException, ComponentRegistryException, 740 UserUnauthorizedException, DeleteFailedException { 741 try { 742 Comment comment = commentsDao.getById(Integer.parseInt(commentId)); 743 if (comment != null 744 // Comment must have an existing (in this registry) 745 // componentId or profileId 746 && (comment.getComponentDescriptionId() != null 747 && componentDescriptionDao.isInRegistry(comment.getComponentDescriptionId(), getUserId()) || comment 748 .getProfileDescriptionId() != null 749 && profileDescriptionDao.isInRegistry(comment.getProfileDescriptionId(), getUserId()))) { 750 checkAuthorisationComment(comment, principal); 751 commentsDao.deleteComment(comment); 752 } else { 753 // Comment exists in DB, but component is not in this registry 754 throw new ComponentRegistryException("Comment " + commentId + " cannot be found in specified registry"); 755 } 756 } catch (DataAccessException ex) { 757 throw new DeleteFailedException("Database access error while trying to delete component", ex); 758 } catch (NumberFormatException ex) { 759 throw new DeleteFailedException("Illegal comment ID, cannot parse integer", ex); 760 } 761 } 762 763 @Override 764 public CMDComponentSpecExpander getExpander() { 765 return new CMDComponentSpecExpanderDbImpl(this); 766 } 767 768 @Override 769 protected MDMarshaller getMarshaller() { 770 return marshaller; 771 } 772 773 @Override 774 public String toString() { 775 return getName(); 776 } 777 778 @Override 779 public List<ComponentDescription> getComponentDescriptionsInGroup(String principalName, String groupId) 780 throws ComponentRegistryException { 781 List<String> componentIds = groupService.getComponentIdsInGroup(Long.parseLong(groupId)); 782 List<ComponentDescription> components = new ArrayList<ComponentDescription>(); 783 for (String id : componentIds) { 784 ComponentDescription componentDescription = componentDescriptionDao.getByCmdId(id); 785 // minor robustness consideration: if, for whatever reason, the 786 // component for an ownership has been removed, don't return a null 787 // but just skip it 788 if (componentDescription != null) 789 components.add(componentDescription); 790 } 791 return components; 792 } 793 794 @Override 795 public List<ProfileDescription> getProfileDescriptionsForMetadaEditor(String groupId) 796 throws ComponentRegistryException { 797 List<String> componentIds = groupService.getProfileIdsInGroup(Long.parseLong(groupId)); 798 List<ProfileDescription> profiles = new ArrayList<ProfileDescription>(); 799 for (String id : componentIds) { 800 ProfileDescription profile = getProfileDescription(id); 801 if (profile != null) 802 profiles.add(profile); 803 } 804 return profiles; 805 } 806 807 @Override 808 public List<ProfileDescription> getProfileDescriptionsInGroup(String groupId) throws ComponentRegistryException { 809 List<String> componentIds = groupService.getProfileIdsInGroup(Long.parseLong(groupId)); 810 List<ProfileDescription> profiles = new ArrayList<ProfileDescription>(); 811 for (String id : componentIds) 812 profiles.add(profileDescriptionDao.getByCmdId(id)); 813 return profiles; 814 } 908 815 } -
ComponentRegistry/branches/ComponentRegistry-1.14.0/ComponentRegistry/src/main/java/clarin/cmdi/componentregistry/impl/database/GroupServiceImpl.java
r3893 r4168 44 44 public class GroupServiceImpl implements GroupService { 45 45 46 @Autowired 47 private GroupDao groupDao; 48 @Autowired 49 private GroupMembershipDao groupMembershipDao; 50 @Autowired 51 private OwnershipDao ownershipDao; 52 @Autowired 53 private ProfileDescriptionDao profileDescriptionDao; 54 @Autowired 55 private ComponentDescriptionDao componentDescriptionDao; 56 @Autowired 57 private UserDao userDao; 58 59 public void setGroupDao(GroupDao groupDao) { 60 this.groupDao = groupDao; 61 } 62 63 public void setGroupMembershipDao(GroupMembershipDao groupMembershipDao) { 64 this.groupMembershipDao = groupMembershipDao; 65 } 66 67 public void setOwnershipDao(OwnershipDao ownershipDao) { 68 this.ownershipDao = ownershipDao; 69 } 70 71 @Override 72 public List<Group> getGroupsOwnedByUser(String ownerPrincipalName) { 73 RegistryUser owner = userDao.getByPrincipalName(ownerPrincipalName); 74 return groupDao.findGroupOwnedByUser(owner.getId().longValue()); 75 } 76 77 @Override 78 public boolean isUserOwnerOfGroup(long groupId, RegistryUser user) { 79 List<Group> groups = getGroupsOwnedByUser(user.getPrincipalName()); 80 for (Group group : groups) 81 if (group.getId() == groupId) 82 return true; 83 return false; 84 } 85 86 private void checkOwnership(Ownership ownership) { 87 if (ownership.getComponentId() == null 88 && ownership.getProfileId() == null) 89 throw new RuntimeException( 90 "Ownership needs either a componentId or a profileId"); 91 if (ownership.getComponentId() != null 92 && ownership.getProfileId() != null) 93 throw new RuntimeException( 94 "Ownership has both a componentId and a profileId"); 95 if (ownership.getUserId() == 0 && ownership.getGroupId() == 0) 96 throw new RuntimeException("Ownership needs a groupId or userId"); 97 if (ownership.getUserId() != 0 && ownership.getGroupId() != 0) 98 throw new RuntimeException( 99 "Ownership has both a groupId and a userId "); 100 } 101 102 private void assertOwnershipDoesNotExist(Ownership ownership) { 103 Ownership o = ownershipDao.findOwnershipByGroupAndComponent( 104 ownership.getGroupId(), ownership.getComponentId()); 105 if (o != null) 106 throw new ValidationException("Ownership exists"); 107 o = ownershipDao.findOwnershipByGroupAndProfile(ownership.getGroupId(), 108 ownership.getProfileId()); 109 if (o != null) 110 throw new ValidationException("Ownership exists"); 111 o = ownershipDao.findOwnershipByUserAndProfile(ownership.getUserId(), 112 ownership.getProfileId()); 113 if (o != null) 114 throw new ValidationException("Ownership exists"); 115 // o = 116 // ownershipDao.findOwnershipByUserAndComponent(ownership.getUserId(), 117 // ownership.getComponentId()); 118 // if (o != null) 119 // throw new ValidationException("Ownership exists"); 120 } 121 122 @Override 123 public void addOwnership(Ownership ownership) { 124 checkOwnership(ownership); 125 assertOwnershipDoesNotExist(ownership); 126 ownershipDao.save(ownership); 127 } 128 129 @Override 130 public void removeOwnership(Ownership ownership) { 131 throw new RuntimeException("not implemented"); 132 } 133 134 protected boolean canUserAccessAbstractDescriptionEitherOnHisOwnOrThroughGroupMembership( 135 RegistryUser user, AbstractDescription description) { 136 // TODO make some joins and multi-id queries to speed the entire method 137 // up 138 boolean isProfile = (description instanceof ProfileDescription); 139 AbstractDescriptionDao<? extends AbstractDescription> dao = isProfile ? profileDescriptionDao 140 : componentDescriptionDao; 141 long userId = user.getId().longValue(); 142 // anyone can access public profile 143 if (dao.isPublic(description.getId())) 144 return true; 145 // the creator can also access any profile 146 if (description.getUserId().equals(user.getId() + "")) 147 return true; 148 149 // a co-ownership on the profile also allows access 150 Ownership ownership = isProfile ? ownershipDao 151 .findOwnershipByUserAndProfile(userId, description.getId()) 152 : ownershipDao.findOwnershipByUserAndComponent(userId, 153 description.getId()); 154 if (ownership != null) 155 return true; 156 157 // get a list of groups the user owns and is a member of 158 List<Group> groups = groupDao.findGroupOwnedByUser(userId); 159 Set<Long> groupIds = new HashSet<Long>(); 160 for (Group group : groups) 161 groupIds.add(group.getId()); 162 163 List<GroupMembership> memberships = groupMembershipDao 164 .findGroupsTheUserIsAmemberOf(userId); 165 for (GroupMembership gm : memberships) 166 groupIds.add(gm.getGroupId()); 167 168 for (Long groupId : groupIds) { 169 ownership = isProfile ? ownershipDao 170 .findOwnershipByGroupAndProfile(groupId, 171 description.getId()) : ownershipDao 172 .findOwnershipByGroupAndComponent(groupId, 173 description.getId()); 174 if (ownership != null) 175 return true; 176 } 177 return false; 178 } 179 180 @Override 181 public boolean canUserAccessProfileEitherOnHisOwnOrThroughGroupMembership( 182 RegistryUser user, ProfileDescription profile) { 183 return canUserAccessAbstractDescriptionEitherOnHisOwnOrThroughGroupMembership( 184 user, profile); 185 } 186 187 @Override 188 public boolean canUserAccessComponentEitherOnHisOwnOrThroughGroupMembership( 189 RegistryUser user, ComponentDescription component) { 190 return canUserAccessAbstractDescriptionEitherOnHisOwnOrThroughGroupMembership( 191 user, component); 192 } 193 194 @Override 195 @ManagedOperation(description = "Mage a user member of a group") 196 @ManagedOperationParameters({ 197 @ManagedOperationParameter(name = "principalName", description = "Principal name of the user to make a member"), 198 @ManagedOperationParameter(name = "groupName", description = "Name of the group") }) 199 public long makeMember(String userPrincipalName, String groupName) { 200 RegistryUser user = userDao.getByPrincipalName(userPrincipalName); 201 Group group = groupDao.findGroupByName(groupName); 202 GroupMembership gm = groupMembershipDao.findMembership(user.getId() 203 .longValue(), group.getId()); 204 if (gm != null) 205 return gm.getId(); 206 gm = new GroupMembership(); 207 gm.setGroupId(group.getId()); 208 gm.setUserId(user.getId().longValue()); 209 return groupMembershipDao.save(gm).getId(); 210 } 211 212 @ManagedOperation(description = "Create a new group") 213 @ManagedOperationParameters({ 214 @ManagedOperationParameter(name = "name", description = "Name of the group, must be unique"), 215 @ManagedOperationParameter(name = "ownerPrincipalName", description = "Principal name of the user") }) 216 @Override 217 public long createNewGroup(String name, String ownerPrincipalName) { 218 RegistryUser owner = userDao.getByPrincipalName(ownerPrincipalName); 219 if (owner == null) 220 throw new ValidationException("No principal '" + ownerPrincipalName 221 + "' found"); 222 Group group = groupDao.findGroupByName(name); 223 if (group != null) 224 throw new ValidationException("Group '" + name + "' already exists"); 225 group = new Group(); 226 group.setName(name); 227 group.setOwnerId(owner.getId().longValue()); 228 group = groupDao.save(group); 229 return group.getId(); 230 } 231 232 @ManagedOperation(description = "List available groups") 233 @Override 234 public List<String> listGroupNames() { 235 List<String> groupNames = new ArrayList<String>(); 236 for (Group group : groupDao.findAll()) 237 groupNames.add(group.getName()); 238 return groupNames; 239 } 240 241 protected void transferAbstractDescriptionOwnershipFromUserToGroup( 242 String principal, String groupName, String descriptionId, 243 boolean isProfile) { 244 RegistryUser user = userDao.getByPrincipalName(principal); 245 Group group = groupDao.findGroupByName(groupName); 246 Ownership ownership = null; 247 List<Ownership> oldOwnerships = isProfile ? ownershipDao 248 .findOwnershipByProfileId(descriptionId) : ownershipDao 249 .findOwnershipByComponentId(descriptionId); 250 ownershipDao.delete(oldOwnerships); 251 ownership = new Ownership(); 252 if (isProfile) 253 ownership.setProfileId(descriptionId); 254 else 255 ownership.setComponentId(descriptionId); 256 ownership.setGroupId(group.getId()); 257 addOwnership(ownership); 258 } 259 260 @ManagedOperation(description = "Make a component owned by a group instead of a user") 261 @ManagedOperationParameters({ 262 @ManagedOperationParameter(name = "principal", description = "Name of the principal who owns the component"), 263 @ManagedOperationParameter(name = "groupName", description = "Name of the group to move the component to"), 264 @ManagedOperationParameter(name = "componentId", description = "Id of component") }) 265 @Override 266 public void transferComponentOwnershipFromUserToGroup(String principal, 267 String groupName, String componentId) { 268 transferAbstractDescriptionOwnershipFromUserToGroup(principal, 269 groupName, componentId, false); 270 } 271 272 @ManagedOperation(description = "Make a profile owned by a group instead of a user") 273 @ManagedOperationParameters({ 274 @ManagedOperationParameter(name = "principal", description = "Name of the principal who owns the profile"), 275 @ManagedOperationParameter(name = "groupName", description = "Name of the group to move the profile to"), 276 @ManagedOperationParameter(name = "componentId", description = "Id of profile") }) 277 @Override 278 public void transferProfileOwnershipFromUserToGroup(String principal, 279 String groupName, String profileId) { 280 transferAbstractDescriptionOwnershipFromUserToGroup(principal, 281 groupName, profileId, true); 282 } 283 284 @Override 285 public List<Group> getGroupsOfWhichUserIsAMember(String principal) { 286 RegistryUser user = userDao.getByPrincipalName(principal); 287 if (user == null || user.getId() == null) 288 return new ArrayList<Group>(); 289 List<GroupMembership> memberships = groupMembershipDao 290 .findGroupsTheUserIsAmemberOf(user.getId().longValue()); 291 List<Group> groups = new ArrayList<Group>(); 292 for (GroupMembership m : memberships) 293 groups.add(groupDao.findOne(m.getGroupId())); 294 return groups; 295 } 296 297 @Override 298 public List<String> getComponentIdsInGroup(long groupId) { 299 List<Ownership> ownerships = ownershipDao.findOwnershipByGroup(groupId); 300 Set<String> componentIds = new HashSet<String>(); 301 for (Ownership o : ownerships) 302 if (o.getComponentId() != null) 303 componentIds.add(o.getComponentId()); 304 List<String> idsList = new ArrayList<String>(componentIds); 305 Collections.sort(idsList); 306 return idsList; 307 } 308 309 @Override 310 public List<String> getProfileIdsInGroup(long groupId) { 311 List<Ownership> ownerships = ownershipDao.findOwnershipByGroup(groupId); 312 Set<String> profileIds = new HashSet<String>(); 313 for (Ownership o : ownerships) 314 if (o.getProfileId() != null) 315 profileIds.add(o.getProfileId()); 316 List<String> idsList = new ArrayList<String>(profileIds); 317 Collections.sort(idsList); 318 return idsList; 319 } 320 321 @Override 322 public List<Group> getGroupsTheItemIsAMemberOf(String itemId) { 323 Set<Ownership> ownerships = new HashSet<Ownership>(); 324 ownerships.addAll(ownershipDao.findOwnershipByProfileId(itemId)); 325 ownerships.addAll(ownershipDao.findOwnershipByComponentId(itemId)); 326 Set<Group> groups = new HashSet<Group>(); 327 for (Ownership ownership : ownerships) 328 groups.add(groupDao.findOne(ownership.getGroupId())); 329 List<Group> groupList = new ArrayList<Group>(groups); 330 Collections.sort(groupList, new Comparator<Group>() { 331 332 @Override 333 public int compare(Group g1, Group g2) { 334 return (int) (g1.getId() - g2.getId()); 335 } 336 }); 337 return groupList; 338 } 339 340 @Override 341 public void transferItemOwnershipFromUserToGroup(String principal, 342 long groupId, String itemId) { 343 344 AbstractDescription item = null; 345 item = profileDescriptionDao.getByCmdId(itemId); 346 boolean isProfile = true; 347 if (item == null) { 348 item = componentDescriptionDao.getByCmdId(itemId); 349 isProfile = false; 350 } 351 if (item == null) 352 throw new ValidationException( 353 "No profile or component found with ID " + itemId); 354 Group group = groupDao.findOne(groupId); 355 if (group == null) 356 throw new ValidationException("No group found with ID " + groupId); 357 String groupName = group.getName(); 358 if (isProfile) 359 transferProfileOwnershipFromUserToGroup(principal, groupName, 360 item.getId()); 361 else 362 transferComponentOwnershipFromUserToGroup(principal, groupName, 363 item.getId()); 364 } 46 @Autowired 47 private GroupDao groupDao; 48 @Autowired 49 private GroupMembershipDao groupMembershipDao; 50 @Autowired 51 private OwnershipDao ownershipDao; 52 @Autowired 53 private ProfileDescriptionDao profileDescriptionDao; 54 @Autowired 55 private ComponentDescriptionDao componentDescriptionDao; 56 @Autowired 57 private UserDao userDao; 58 59 public void setGroupDao(GroupDao groupDao) { 60 this.groupDao = groupDao; 61 } 62 63 public void setGroupMembershipDao(GroupMembershipDao groupMembershipDao) { 64 this.groupMembershipDao = groupMembershipDao; 65 } 66 67 public void setOwnershipDao(OwnershipDao ownershipDao) { 68 this.ownershipDao = ownershipDao; 69 } 70 71 @Override 72 public List<Group> getGroupsOwnedByUser(String ownerPrincipalName) { 73 RegistryUser owner = userDao.getByPrincipalName(ownerPrincipalName); 74 return groupDao.findGroupOwnedByUser(owner.getId().longValue()); 75 } 76 77 @Override 78 public boolean isUserOwnerOfGroup(long groupId, RegistryUser user) { 79 List<Group> groups = getGroupsOwnedByUser(user.getPrincipalName()); 80 for (Group group : groups) 81 if (group.getId() == groupId) 82 return true; 83 return false; 84 } 85 86 private void checkOwnership(Ownership ownership) { 87 if (ownership.getComponentId() == null && ownership.getProfileId() == null) 88 throw new RuntimeException("Ownership needs either a componentId or a profileId"); 89 if (ownership.getComponentId() != null && ownership.getProfileId() != null) 90 throw new RuntimeException("Ownership has both a componentId and a profileId"); 91 if (ownership.getUserId() == 0 && ownership.getGroupId() == 0) 92 throw new RuntimeException("Ownership needs a groupId or userId"); 93 if (ownership.getUserId() != 0 && ownership.getGroupId() != 0) 94 throw new RuntimeException("Ownership has both a groupId and a userId "); 95 } 96 97 private void assertOwnershipDoesNotExist(Ownership ownership) { 98 Ownership o = ownershipDao.findOwnershipByGroupAndComponent(ownership.getGroupId(), ownership.getComponentId()); 99 if (o != null) 100 throw new ValidationException("Ownership exists"); 101 o = ownershipDao.findOwnershipByGroupAndProfile(ownership.getGroupId(), ownership.getProfileId()); 102 if (o != null) 103 throw new ValidationException("Ownership exists"); 104 o = ownershipDao.findOwnershipByUserAndProfile(ownership.getUserId(), ownership.getProfileId()); 105 if (o != null) 106 throw new ValidationException("Ownership exists"); 107 // o = 108 // ownershipDao.findOwnershipByUserAndComponent(ownership.getUserId(), 109 // ownership.getComponentId()); 110 // if (o != null) 111 // throw new ValidationException("Ownership exists"); 112 } 113 114 @Override 115 public void addOwnership(Ownership ownership) { 116 checkOwnership(ownership); 117 assertOwnershipDoesNotExist(ownership); 118 ownershipDao.save(ownership); 119 } 120 121 @Override 122 public void removeOwnership(Ownership ownership) { 123 throw new RuntimeException("not implemented"); 124 } 125 126 protected boolean canUserAccessAbstractDescriptionEitherOnHisOwnOrThroughGroupMembership(RegistryUser user, 127 AbstractDescription description) { 128 // TODO make some joins and multi-id queries to speed the entire method 129 // up 130 boolean isProfile = (description instanceof ProfileDescription); 131 AbstractDescriptionDao<? extends AbstractDescription> dao = isProfile ? profileDescriptionDao 132 : componentDescriptionDao; 133 long userId = user.getId().longValue(); 134 // anyone can access public profile 135 if (dao.isPublic(description.getId())) 136 return true; 137 // the creator can also access any profile 138 if (description.getUserId().equals(user.getId() + "")) 139 return true; 140 141 // a co-ownership on the profile also allows access 142 Ownership ownership = isProfile ? ownershipDao.findOwnershipByUserAndProfile(userId, description.getId()) 143 : ownershipDao.findOwnershipByUserAndComponent(userId, description.getId()); 144 if (ownership != null) 145 return true; 146 147 // get a list of groups the user owns and is a member of 148 List<Group> groups = groupDao.findGroupOwnedByUser(userId); 149 Set<Long> groupIds = new HashSet<Long>(); 150 for (Group group : groups) 151 groupIds.add(group.getId()); 152 153 List<GroupMembership> memberships = groupMembershipDao.findGroupsTheUserIsAmemberOf(userId); 154 for (GroupMembership gm : memberships) 155 groupIds.add(gm.getGroupId()); 156 157 for (Long groupId : groupIds) { 158 ownership = isProfile ? ownershipDao.findOwnershipByGroupAndProfile(groupId, description.getId()) 159 : ownershipDao.findOwnershipByGroupAndComponent(groupId, description.getId()); 160 if (ownership != null) 161 return true; 162 } 163 return false; 164 } 165 166 @Override 167 public boolean canUserAccessProfileEitherOnHisOwnOrThroughGroupMembership(RegistryUser user, 168 ProfileDescription profile) { 169 return canUserAccessAbstractDescriptionEitherOnHisOwnOrThroughGroupMembership(user, profile); 170 } 171 172 @Override 173 public boolean canUserAccessComponentEitherOnHisOwnOrThroughGroupMembership(RegistryUser user, 174 ComponentDescription component) { 175 return canUserAccessAbstractDescriptionEitherOnHisOwnOrThroughGroupMembership(user, component); 176 } 177 178 @Override 179 @ManagedOperation(description = "Make a user member of a group") 180 @ManagedOperationParameters({ 181 @ManagedOperationParameter(name = "principalName", description = "Principal name of the user to make a member"), 182 @ManagedOperationParameter(name = "groupName", description = "Name of the group") }) 183 public long makeMember(String userPrincipalName, String groupName) { 184 RegistryUser user = userDao.getByPrincipalName(userPrincipalName); 185 Group group = groupDao.findGroupByName(groupName); 186 GroupMembership gm = groupMembershipDao.findMembership(user.getId().longValue(), group.getId()); 187 if (gm != null) 188 return gm.getId(); 189 gm = new GroupMembership(); 190 gm.setGroupId(group.getId()); 191 gm.setUserId(user.getId().longValue()); 192 return groupMembershipDao.save(gm).getId(); 193 } 194 195 @ManagedOperation(description = "Create a new group") 196 @ManagedOperationParameters({ 197 @ManagedOperationParameter(name = "name", description = "Name of the group, must be unique"), 198 @ManagedOperationParameter(name = "ownerPrincipalName", description = "Principal name of the user") }) 199 @Override 200 public long createNewGroup(String name, String ownerPrincipalName) { 201 RegistryUser owner = userDao.getByPrincipalName(ownerPrincipalName); 202 if (owner == null) 203 throw new ValidationException("No principal '" + ownerPrincipalName + "' found"); 204 Group group = groupDao.findGroupByName(name); 205 if (group != null) 206 throw new ValidationException("Group '" + name + "' already exists"); 207 group = new Group(); 208 group.setName(name); 209 group.setOwnerId(owner.getId().longValue()); 210 group = groupDao.save(group); 211 return group.getId(); 212 } 213 214 @ManagedOperation(description = "List available groups") 215 @Override 216 public List<String> listGroupNames() { 217 List<String> groupNames = new ArrayList<String>(); 218 for (Group group : groupDao.findAll()) 219 groupNames.add(group.getName()); 220 return groupNames; 221 } 222 223 protected void transferAbstractDescriptionOwnershipFromUserToGroup(String principal, String groupName, 224 String descriptionId, boolean isProfile) { 225 RegistryUser user = userDao.getByPrincipalName(principal); 226 Group group = groupDao.findGroupByName(groupName); 227 Ownership ownership = null; 228 List<Ownership> oldOwnerships = isProfile ? ownershipDao.findOwnershipByProfileId(descriptionId) : ownershipDao 229 .findOwnershipByComponentId(descriptionId); 230 ownershipDao.delete(oldOwnerships); 231 ownership = new Ownership(); 232 if (isProfile) 233 ownership.setProfileId(descriptionId); 234 else 235 ownership.setComponentId(descriptionId); 236 ownership.setGroupId(group.getId()); 237 addOwnership(ownership); 238 } 239 240 @ManagedOperation(description = "Make a component owned by a group instead of a user") 241 @ManagedOperationParameters({ 242 @ManagedOperationParameter(name = "principal", description = "Name of the principal who owns the component"), 243 @ManagedOperationParameter(name = "groupName", description = "Name of the group to move the component to"), 244 @ManagedOperationParameter(name = "componentId", description = "Id of component") }) 245 @Override 246 public void transferComponentOwnershipFromUserToGroup(String principal, String groupName, String componentId) { 247 transferAbstractDescriptionOwnershipFromUserToGroup(principal, groupName, componentId, false); 248 } 249 250 @ManagedOperation(description = "Make a profile owned by a group instead of a user") 251 @ManagedOperationParameters({ 252 @ManagedOperationParameter(name = "principal", description = "Name of the principal who owns the profile"), 253 @ManagedOperationParameter(name = "groupName", description = "Name of the group to move the profile to"), 254 @ManagedOperationParameter(name = "componentId", description = "Id of profile") }) 255 @Override 256 public void transferProfileOwnershipFromUserToGroup(String principal, String groupName, String profileId) { 257 transferAbstractDescriptionOwnershipFromUserToGroup(principal, groupName, profileId, true); 258 } 259 260 @Override 261 public List<Group> getGroupsOfWhichUserIsAMember(String principal) { 262 RegistryUser user = userDao.getByPrincipalName(principal); 263 if (user == null || user.getId() == null) 264 return new ArrayList<Group>(); 265 List<GroupMembership> memberships = groupMembershipDao.findGroupsTheUserIsAmemberOf(user.getId().longValue()); 266 List<Group> groups = new ArrayList<Group>(); 267 for (GroupMembership m : memberships) 268 groups.add(groupDao.findOne(m.getGroupId())); 269 return groups; 270 } 271 272 @Override 273 public List<String> getComponentIdsInGroup(long groupId) { 274 List<Ownership> ownerships = ownershipDao.findOwnershipByGroup(groupId); 275 Set<String> componentIds = new HashSet<String>(); 276 for (Ownership o : ownerships) 277 if (o.getComponentId() != null) 278 componentIds.add(o.getComponentId()); 279 List<String> idsList = new ArrayList<String>(componentIds); 280 Collections.sort(idsList); 281 return idsList; 282 } 283 284 @Override 285 public List<String> getProfileIdsInGroup(long groupId) { 286 List<Ownership> ownerships = ownershipDao.findOwnershipByGroup(groupId); 287 Set<String> profileIds = new HashSet<String>(); 288 for (Ownership o : ownerships) 289 if (o.getProfileId() != null) 290 profileIds.add(o.getProfileId()); 291 List<String> idsList = new ArrayList<String>(profileIds); 292 Collections.sort(idsList); 293 return idsList; 294 } 295 296 @Override 297 public List<Group> getGroupsTheItemIsAMemberOf(String itemId) { 298 Set<Ownership> ownerships = new HashSet<Ownership>(); 299 ownerships.addAll(ownershipDao.findOwnershipByProfileId(itemId)); 300 ownerships.addAll(ownershipDao.findOwnershipByComponentId(itemId)); 301 Set<Group> groups = new HashSet<Group>(); 302 for (Ownership ownership : ownerships) 303 groups.add(groupDao.findOne(ownership.getGroupId())); 304 List<Group> groupList = new ArrayList<Group>(groups); 305 Collections.sort(groupList, new Comparator<Group>() { 306 307 @Override 308 public int compare(Group g1, Group g2) { 309 return (int) (g1.getId() - g2.getId()); 310 } 311 }); 312 return groupList; 313 } 314 315 @Override 316 public void transferItemOwnershipFromUserToGroup(String principal, long groupId, String itemId) { 317 318 AbstractDescription item = null; 319 item = profileDescriptionDao.getByCmdId(itemId); 320 boolean isProfile = true; 321 if (item == null) { 322 item = componentDescriptionDao.getByCmdId(itemId); 323 isProfile = false; 324 } 325 if (item == null) 326 throw new ValidationException("No profile or component found with ID " + itemId); 327 Group group = groupDao.findOne(groupId); 328 if (group == null) 329 throw new ValidationException("No group found with ID " + groupId); 330 String groupName = group.getName(); 331 if (isProfile) 332 transferProfileOwnershipFromUserToGroup(principal, groupName, item.getId()); 333 else 334 transferComponentOwnershipFromUserToGroup(principal, groupName, item.getId()); 335 } 365 336 366 337 }
Note: See TracChangeset
for help on using the changeset viewer.