001/* 002 * Copyright 2018 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.repository.data.repositorydata.impl; 017 018import java.io.InputStream; 019import java.util.ArrayList; 020import java.util.Calendar; 021import java.util.LinkedHashMap; 022import java.util.LinkedHashSet; 023import java.util.List; 024import java.util.Map; 025import java.util.Set; 026 027import javax.jcr.Binary; 028import javax.jcr.Node; 029import javax.jcr.NodeIterator; 030import javax.jcr.PathNotFoundException; 031import javax.jcr.Property; 032import javax.jcr.PropertyIterator; 033import javax.jcr.PropertyType; 034import javax.jcr.RepositoryException; 035import javax.jcr.Session; 036import javax.jcr.Value; 037import javax.jcr.lock.Lock; 038import javax.jcr.lock.LockManager; 039 040import org.apache.commons.lang3.StringUtils; 041 042import org.ametys.plugins.repository.AmetysObjectResolver; 043import org.ametys.plugins.repository.AmetysRepositoryException; 044import org.ametys.plugins.repository.RepositoryConstants; 045import org.ametys.plugins.repository.data.UnknownDataException; 046import org.ametys.plugins.repository.data.repositorydata.ModifiableRepositoryData; 047import org.ametys.plugins.repository.data.repositorydata.RepositoryData; 048import org.ametys.plugins.repository.jcr.NodeHelper; 049import org.ametys.plugins.repository.jcr.NodeTypeHelper; 050 051/** 052 * Class for data values management in JCR repository 053 */ 054public class JCRRepositoryData implements ModifiableRepositoryData 055{ 056 private static final Map<Integer, String> __DATA_TYPES; 057 058 static 059 { 060 __DATA_TYPES = new LinkedHashMap<>(6); 061 __DATA_TYPES.put(PropertyType.STRING, RepositoryData.STRING_REPOSITORY_DATA_TYPE); 062 __DATA_TYPES.put(PropertyType.LONG, RepositoryData.LONG_REPOSITORY_DATA_TYPE); 063 __DATA_TYPES.put(PropertyType.DOUBLE, RepositoryData.DOUBLE_REPOSITORY_DATA_TYPE); 064 __DATA_TYPES.put(PropertyType.BOOLEAN, RepositoryData.BOOLEAN_REPOSITORY_DATA_TYPE); 065 __DATA_TYPES.put(PropertyType.DATE, RepositoryData.CALENDAR_REPOSITORY_DATA_TYPE); 066 __DATA_TYPES.put(PropertyType.BINARY, RepositoryData.STREAM_REPOSITORY_DATA_TYPE); 067 } 068 069 private Node _node; 070 private boolean _lockAlreadyChecked; 071 private String _defaultPrefix; 072 073 /** 074 * Creates a JCR repository data from the given node 075 * @param node the Node supporting this repository data 076 */ 077 public JCRRepositoryData(Node node) 078 { 079 this(node, RepositoryConstants.NAMESPACE_PREFIX); 080 } 081 082 /** 083 * Creates a JCR repository data from the given node 084 * @param node the Node supporting this repository data 085 * @param defaultPrefix prefix to use for properties and child nodes 086 */ 087 public JCRRepositoryData(Node node, String defaultPrefix) 088 { 089 _node = node; 090 _defaultPrefix = defaultPrefix; 091 } 092 093 public String getString(String name, String prefix) 094 { 095 try 096 { 097 Value value = _getValue(name, prefix); 098 return value.getString(); 099 } 100 catch (RepositoryException e) 101 { 102 throw new AmetysRepositoryException("Unable to get the value of string data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 103 } 104 } 105 106 public String[] getStrings(String name, String prefix) 107 { 108 try 109 { 110 Value[] values = _getValues(name, prefix); 111 String[] results = new String[values.length]; 112 113 for (int i = 0; i < values.length; i++) 114 { 115 Value value = values[i]; 116 results[i] = value.getString(); 117 } 118 119 return results; 120 } 121 catch (RepositoryException e) 122 { 123 throw new AmetysRepositoryException("Unable to get the values of multiple string data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 124 } 125 } 126 127 public Calendar getDate(String name, String prefix) 128 { 129 try 130 { 131 Value value = _getValue(name, prefix); 132 return value.getDate(); 133 } 134 catch (RepositoryException e) 135 { 136 throw new AmetysRepositoryException("Unable to get the value of date data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 137 } 138 } 139 140 public Calendar[] getDates(String name, String prefix) 141 { 142 try 143 { 144 Value[] values = _getValues(name, prefix); 145 Calendar[] results = new Calendar[values.length]; 146 147 for (int i = 0; i < values.length; i++) 148 { 149 Value value = values[i]; 150 results[i] = value.getDate(); 151 } 152 153 return results; 154 } 155 catch (RepositoryException e) 156 { 157 throw new AmetysRepositoryException("Unable to get the values of multiple date data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 158 } 159 } 160 161 public Long getLong(String name, String prefix) 162 { 163 try 164 { 165 Value value = _getValue(name, prefix); 166 return value.getLong(); 167 } 168 catch (RepositoryException e) 169 { 170 throw new AmetysRepositoryException("Unable to get the value on long data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 171 } 172 } 173 174 public Long[] getLongs(String name, String prefix) 175 { 176 try 177 { 178 Value[] values = _getValues(name, prefix); 179 Long[] results = new Long[values.length]; 180 181 for (int i = 0; i < values.length; i++) 182 { 183 Value value = values[i]; 184 results[i] = value.getLong(); 185 } 186 187 return results; 188 } 189 catch (RepositoryException e) 190 { 191 throw new AmetysRepositoryException("Unable to get the values of multiple long data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 192 } 193 } 194 195 public Double getDouble(String name, String prefix) 196 { 197 try 198 { 199 Value value = _getValue(name, prefix); 200 return value.getDouble(); 201 } 202 catch (RepositoryException e) 203 { 204 throw new AmetysRepositoryException("Unable to get the value of double data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 205 } 206 } 207 208 public Double[] getDoubles(String name, String prefix) 209 { 210 try 211 { 212 Value[] values = _getValues(name, prefix); 213 Double[] results = new Double[values.length]; 214 215 for (int i = 0; i < values.length; i++) 216 { 217 Value value = values[i]; 218 results[i] = value.getDouble(); 219 } 220 221 return results; 222 } 223 catch (RepositoryException e) 224 { 225 throw new AmetysRepositoryException("Unable to get the values of multiple double data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 226 } 227 } 228 229 public Boolean getBoolean(String name, String prefix) 230 { 231 try 232 { 233 Value value = _getValue(name, prefix); 234 return value.getBoolean(); 235 } 236 catch (RepositoryException e) 237 { 238 throw new AmetysRepositoryException("Unable to get the value of boolean data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 239 } 240 } 241 242 public Boolean[] getBooleans(String name, String prefix) 243 { 244 try 245 { 246 Value[] values = _getValues(name, prefix); 247 Boolean[] results = new Boolean[values.length]; 248 249 for (int i = 0; i < values.length; i++) 250 { 251 Value value = values[i]; 252 results[i] = value.getBoolean(); 253 } 254 255 return results; 256 } 257 catch (RepositoryException e) 258 { 259 throw new AmetysRepositoryException("Unable to get the values of multiple boolean data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 260 } 261 } 262 263 public InputStream[] getStreams(String name, String prefix) 264 { 265 try 266 { 267 Value[] values = _getValues(name, prefix); 268 InputStream[] results = new InputStream[values.length]; 269 270 for (int i = 0; i < values.length; i++) 271 { 272 Value value = values[i]; 273 results[i] = value.getBinary().getStream(); 274 } 275 276 return results; 277 } 278 catch (RepositoryException e) 279 { 280 throw new AmetysRepositoryException("Unable to get the values of multiple stream data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 281 } 282 } 283 284 public InputStream getStream(String name, String prefix) 285 { 286 try 287 { 288 Value value = _getValue(name, prefix); 289 return value.getBinary().getStream(); 290 } 291 catch (RepositoryException e) 292 { 293 throw new AmetysRepositoryException("Unable to get the value of stream data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 294 } 295 } 296 297 public Long getStreamLength(String name, String prefix) 298 { 299 try 300 { 301 return _node.getProperty(_getFullName(name, prefix)).getLength(); 302 } 303 catch (RepositoryException e) 304 { 305 throw new AmetysRepositoryException("Unable to get the length of the value of stream data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 306 } 307 } 308 309 private Value _getValue(String name, String prefix) 310 { 311 try 312 { 313 Property property = _node.getProperty(_getFullName(name, prefix)); 314 315 if (property.getDefinition().isMultiple()) 316 { 317 Value[] values = property.getValues(); 318 319 if (values.length > 0) 320 { 321 return values[0]; 322 } 323 else 324 { 325 throw new AmetysRepositoryException("Cannot get the value of data '" + _getFullName(name, prefix) + "' from an empty array in repository data at path '" + this + "'."); 326 } 327 } 328 329 return property.getValue(); 330 } 331 catch (PathNotFoundException e) 332 { 333 throw new UnknownDataException("Unknown data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 334 } 335 catch (RepositoryException e) 336 { 337 throw new AmetysRepositoryException("Unable to get the value of data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 338 } 339 } 340 341 private Value[] _getValues(String name, String prefix) 342 { 343 try 344 { 345 Property property = _node.getProperty(_getFullName(name, prefix)); 346 347 if (property.getDefinition().isMultiple()) 348 { 349 return property.getValues(); 350 } 351 352 Value value = property.getValue(); 353 return new Value[] {value}; 354 } 355 catch (PathNotFoundException e) 356 { 357 throw new UnknownDataException("Unknown data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 358 } 359 catch (RepositoryException e) 360 { 361 throw new AmetysRepositoryException("Unable to get the multiple value of data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 362 } 363 } 364 365 public ModifiableRepositoryData getRepositoryData(String name, String prefix) 366 { 367 try 368 { 369 if (_node.hasNode(_getFullName(name, prefix))) 370 { 371 Node node = _node.getNode(_getFullName(name, prefix)); 372 return new JCRRepositoryData(node); 373 } 374 else 375 { 376 throw new UnknownDataException("Unknown repository data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'."); 377 } 378 } 379 catch (RepositoryException e) 380 { 381 throw new AmetysRepositoryException("Unable to get the repository data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 382 } 383 } 384 385 public RepositoryData[] getAllRepositoryData(String name, String prefix) 386 { 387 try 388 { 389 if (_node.hasNode(_getFullName(name, prefix))) 390 { 391 List<RepositoryData> results = new ArrayList<>(); 392 NodeIterator nodeIterator = _node.getNodes(_getFullName(name, prefix)); 393 394 while (nodeIterator.hasNext()) 395 { 396 results.add(new JCRRepositoryData((Node) nodeIterator.next())); 397 } 398 399 return results.toArray(new RepositoryData[results.size()]); 400 } 401 else 402 { 403 throw new UnknownDataException("Unknown repository data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'."); 404 } 405 } 406 catch (RepositoryException e) 407 { 408 throw new AmetysRepositoryException("Unable to get the repository data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 409 } 410 } 411 412 public Set<String> getDataNames(String prefix) throws AmetysRepositoryException 413 { 414 final String finalPrefix; 415 if (prefix == null) 416 { 417 finalPrefix = "*:"; 418 } 419 else if (StringUtils.isEmpty(prefix)) 420 { 421 finalPrefix = prefix; 422 } 423 else 424 { 425 finalPrefix = prefix + ":"; 426 } 427 428 try 429 { 430 PropertyIterator propertiesIterator = _node.getProperties(finalPrefix + "*"); 431 NodeIterator itNode = _node.getNodes(finalPrefix + "*"); 432 433 Set<String> names = new LinkedHashSet<>(); 434 435 while (propertiesIterator.hasNext()) 436 { 437 Property property = propertiesIterator.nextProperty(); 438 String propertyName = property.getName(); 439 440 if (!StringUtils.isEmpty(finalPrefix) || !propertyName.contains(":")) 441 { 442 names.add(propertyName.substring(finalPrefix.length())); 443 } 444 } 445 446 while (itNode.hasNext()) 447 { 448 Node node = itNode.nextNode(); 449 450 // Filtering out AmetysObjects: they're not data (except users). 451 if (!NodeTypeHelper.isNodeType(node, AmetysObjectResolver.OBJECT_TYPE) || NodeTypeHelper.isNodeType(node, RepositoryConstants.USER_NODETYPE)) 452 { 453 names.add(node.getName().substring(finalPrefix.length())); 454 } 455 } 456 457 return names; 458 } 459 catch (RepositoryException e) 460 { 461 throw new AmetysRepositoryException("Unable to get the data names of the repository data at path '" + this + "'.", e); 462 } 463 } 464 465 public String getName() 466 { 467 try 468 { 469 return getName(_node); 470 } 471 catch (RepositoryException e) 472 { 473 throw new AmetysRepositoryException("Unable to get the name of the repository data at path '" + this + "'.", e); 474 } 475 } 476 477 /** 478 * Retrieves the name of the given node, excluding its prefix 479 * @param node the node 480 * @return the name of the given node 481 * @throws RepositoryException if an error occurs 482 */ 483 protected String getName(Node node) throws RepositoryException 484 { 485 String fullName = node.getName(); 486 int prefixLength = fullName.indexOf(":") + 1; 487 return prefixLength > 0 ? fullName.substring(prefixLength) : fullName; 488 } 489 490 public boolean hasValue(String name, String prefix) 491 { 492 try 493 { 494 return _node.hasProperty(_getFullName(name, prefix)) || _node.hasNode(_getFullName(name, prefix)); 495 } 496 catch (RepositoryException e) 497 { 498 throw new AmetysRepositoryException("Unable to determine if there is a value for data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 499 } 500 } 501 502 public String getType(String name, String prefix) throws UnknownDataException 503 { 504 try 505 { 506 String dataName = _getFullName(name, prefix); 507 508 if (_node.hasProperty(dataName)) 509 { 510 Property property = _node.getProperty(dataName); 511 int jcrType = property.getType(); 512 513 String dataType = __DATA_TYPES.get(jcrType); 514 if (dataType == null) 515 { 516 throw new AmetysRepositoryException("Unable to get the type of data '" + dataName + "' in repository data at path '" + this + "'."); 517 } 518 519 return dataType; 520 } 521 522 if (_node.hasNode(dataName)) 523 { 524 return NodeTypeHelper.getNodeTypeName(_node.getNode(dataName)); 525 } 526 527 throw new UnknownDataException("No data found for '" + dataName + "' in repository data at path '" + this + "'."); 528 } 529 catch (RepositoryException e) 530 { 531 throw new AmetysRepositoryException("Unable to get the type of data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 532 } 533 } 534 535 public boolean isMultiple(String name, String prefix) throws UnknownDataException 536 { 537 try 538 { 539 String dataName = _getFullName(name, prefix); 540 541 if (_node.hasProperty(dataName)) 542 { 543 Property property = _node.getProperty(dataName); 544 545 if (property.getDefinition().isMultiple()) 546 { 547 return true; 548 } 549 550 return false; 551 } 552 553 if (_node.hasNode(dataName)) 554 { 555 String nodeTypeName = NodeTypeHelper.getNodeTypeName(_node.getNode(dataName)); 556 return RepositoryConstants.MULTIPLE_ITEM_NODETYPE.equals(nodeTypeName); 557 } 558 559 throw new UnknownDataException("No data found for '" + dataName + "' in repository data at path '" + this + "'."); 560 } 561 catch (RepositoryException e) 562 { 563 throw new AmetysRepositoryException("Unable to determine if data '" + _getFullName(name, prefix) + "' is multiple in repository data at path '" + this + "'.", e); 564 } 565 } 566 567 public void rename(String newName, String prefix) 568 { 569 NodeHelper.rename(_node, prefix + ":" + newName); 570 } 571 572 public void setValue(String name, String value, String prefix) 573 { 574 if (value == null) 575 { 576 throw new NullPointerException("Unable to set a 'null' data for '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'."); 577 } 578 579 _checkDataName(name, prefix); 580 581 try 582 { 583 _checkLock(); 584 _node.setProperty(_getFullName(name, prefix), value); 585 } 586 catch (RepositoryException e) 587 { 588 throw new AmetysRepositoryException("Unable to set the value '" + value + "' for data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 589 } 590 } 591 592 public void setValues(String name, String[] values, String prefix) 593 { 594 if (values == null) 595 { 596 throw new NullPointerException("Unable to set a 'null' data for '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'."); 597 } 598 599 _checkDataName(name, prefix); 600 601 try 602 { 603 _checkLock(); 604 _node.setProperty(_getFullName(name, prefix), values); 605 } 606 catch (RepositoryException e) 607 { 608 throw new AmetysRepositoryException("Unable to set the values '" + values + "' for data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 609 } 610 } 611 612 public void setValue(String name, Calendar value, String prefix) 613 { 614 if (value == null) 615 { 616 throw new NullPointerException("Unable to set a 'null' data for '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'."); 617 } 618 619 _checkDataName(name, prefix); 620 621 try 622 { 623 _checkLock(); 624 _node.setProperty(_getFullName(name, prefix), value); 625 } 626 catch (RepositoryException e) 627 { 628 throw new AmetysRepositoryException("Unable to set the value '" + value + "' for data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 629 } 630 } 631 632 public void setValues(String name, Calendar[] values, String prefix) 633 { 634 if (values == null) 635 { 636 throw new NullPointerException("Unable to set a 'null' data for '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'."); 637 } 638 639 _checkDataName(name, prefix); 640 641 try 642 { 643 _checkLock(); 644 645 Value[] jcrValues = new Value[values.length]; 646 for (int i = 0; i < values.length; i++) 647 { 648 Calendar value = values[i]; 649 jcrValues[i] = _node.getSession().getValueFactory().createValue(value); 650 } 651 652 _node.setProperty(_getFullName(name, prefix), jcrValues, PropertyType.DATE); 653 } 654 catch (RepositoryException e) 655 { 656 throw new AmetysRepositoryException("Unable to set the values '" + values + "' for data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 657 } 658 } 659 660 public void setValue(String name, Long value, String prefix) 661 { 662 if (value == null) 663 { 664 throw new NullPointerException("Unable to set a 'null' data for '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'."); 665 } 666 667 _checkDataName(name, prefix); 668 669 try 670 { 671 _checkLock(); 672 _node.setProperty(_getFullName(name, prefix), value); 673 } 674 catch (RepositoryException e) 675 { 676 throw new AmetysRepositoryException("Unable to set the value '" + value + "' for data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 677 } 678 } 679 680 public void setValues(String name, Long[] values, String prefix) 681 { 682 if (values == null) 683 { 684 throw new NullPointerException("Unable to set a 'null' data for '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'."); 685 } 686 687 _checkDataName(name, prefix); 688 689 try 690 { 691 _checkLock(); 692 693 Value[] jcrValues = new Value[values.length]; 694 for (int i = 0; i < values.length; i++) 695 { 696 long value = values[i]; 697 jcrValues[i] = _node.getSession().getValueFactory().createValue(value); 698 } 699 700 _node.setProperty(_getFullName(name, prefix), jcrValues, PropertyType.LONG); 701 } 702 catch (RepositoryException e) 703 { 704 throw new AmetysRepositoryException("Unable to set the values '" + values + "' for data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 705 } 706 } 707 708 public void setValue(String name, Double value, String prefix) 709 { 710 if (value == null) 711 { 712 throw new NullPointerException("Unable to set a 'null' data for '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'."); 713 } 714 715 _checkDataName(name, prefix); 716 717 try 718 { 719 _checkLock(); 720 _node.setProperty(_getFullName(name, prefix), value); 721 } 722 catch (RepositoryException e) 723 { 724 throw new AmetysRepositoryException("Unable to set the value '" + value + "' for data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 725 } 726 } 727 728 public void setValues(String name, Double[] values, String prefix) 729 { 730 if (values == null) 731 { 732 throw new NullPointerException("Unable to set a 'null' data for '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'."); 733 } 734 735 _checkDataName(name, prefix); 736 737 try 738 { 739 _checkLock(); 740 741 Value[] jcrValues = new Value[values.length]; 742 for (int i = 0; i < values.length; i++) 743 { 744 double value = values[i]; 745 jcrValues[i] = _node.getSession().getValueFactory().createValue(value); 746 } 747 748 _node.setProperty(_getFullName(name, prefix), jcrValues, PropertyType.DOUBLE); 749 } 750 catch (RepositoryException e) 751 { 752 throw new AmetysRepositoryException("Unable to set the values '" + values + "' for data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 753 } 754 } 755 756 public void setValue(String name, Boolean value, String prefix) 757 { 758 if (value == null) 759 { 760 throw new NullPointerException("Unable to set a 'null' data for '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'."); 761 } 762 763 _checkDataName(name, prefix); 764 765 try 766 { 767 _checkLock(); 768 _node.setProperty(_getFullName(name, prefix), value); 769 } 770 catch (RepositoryException e) 771 { 772 throw new AmetysRepositoryException("Unable to set the value '" + value + "' for data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 773 } 774 } 775 776 public void setValues(String name, Boolean[] values, String prefix) 777 { 778 if (values == null) 779 { 780 throw new NullPointerException("Unable to set a 'null' data for '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'."); 781 } 782 783 _checkDataName(name, prefix); 784 785 try 786 { 787 _checkLock(); 788 789 Value[] jcrValues = new Value[values.length]; 790 for (int i = 0; i < values.length; i++) 791 { 792 boolean value = values[i]; 793 jcrValues[i] = _node.getSession().getValueFactory().createValue(value); 794 } 795 796 _node.setProperty(_getFullName(name, prefix), jcrValues, PropertyType.BOOLEAN); 797 } 798 catch (RepositoryException e) 799 { 800 throw new AmetysRepositoryException("Unable to set the values '" + values + "' for data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 801 } 802 } 803 804 public void setValue(String name, InputStream value, String prefix) 805 { 806 if (value == null) 807 { 808 throw new NullPointerException("Unable to set a 'null' data for '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'."); 809 } 810 811 _checkDataName(name, prefix); 812 813 try 814 { 815 _checkLock(); 816 Binary binary = _node.getSession().getValueFactory().createBinary(value); 817 _node.setProperty(_getFullName(name, prefix), binary); 818 } 819 catch (RepositoryException e) 820 { 821 throw new AmetysRepositoryException("Unable to set the value '" + value + "' for data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 822 } 823 } 824 825 public void setValues(String name, InputStream[] values, String prefix) 826 { 827 if (values == null) 828 { 829 throw new NullPointerException("Unable to set a 'null' data for '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'."); 830 } 831 832 _checkDataName(name, prefix); 833 834 try 835 { 836 _checkLock(); 837 838 Value[] jcrValues = new Value[values.length]; 839 for (int i = 0; i < values.length; i++) 840 { 841 InputStream value = values[i]; 842 Binary binary = _node.getSession().getValueFactory().createBinary(value); 843 jcrValues[i] = _node.getSession().getValueFactory().createValue(binary); 844 } 845 846 _node.setProperty(_getFullName(name, prefix), jcrValues, PropertyType.BINARY); 847 } 848 catch (RepositoryException e) 849 { 850 throw new AmetysRepositoryException("Unable to set the values '" + values + "' for data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 851 } 852 } 853 854 public ModifiableRepositoryData addRepositoryData(String name, String dataTypeName, String prefix) 855 { 856 try 857 { 858 _checkLock(); 859 Node node = _node.addNode(_getFullName(name, prefix), dataTypeName); 860 return new JCRRepositoryData(node); 861 } 862 catch (RepositoryException e) 863 { 864 throw new AmetysRepositoryException("Unable to create repository data '" + _getFullName(name, prefix) + "' with type '" + dataTypeName + "' in repository data at path '" + this + "'.", e); 865 } 866 } 867 868 private void _checkDataName(String name, String prefix) 869 { 870 // Name null 871 if (name == null) 872 { 873 throw new AmetysRepositoryException("Unable to set a value with the invalid data name (null) in repository data at path '" + this + "'."); 874 } 875 876 // Valid name 877 if (!DATA_NAME_PATTERN.matcher(name).matches()) 878 { 879 throw new AmetysRepositoryException("Unable to set a value with the invalid data name '" + name + "'. Only [a-zA-Z][a-zA-Z0-9-_]* are allowed."); 880 } 881 882 // Has value 883 if (hasValue(name, prefix)) 884 { 885 // Remove existing value to avoid values with same name (node + property) 886 removeValue(name, prefix); 887 } 888 } 889 890 public void removeValue(String name, String prefix) throws UnknownDataException 891 { 892 try 893 { 894 _checkLock(); 895 String dataName = _getFullName(name, prefix); 896 897 if (_node.hasProperty(dataName)) 898 { 899 _node.getProperty(dataName).remove(); 900 } 901 else if (_node.hasNode(dataName)) 902 { 903 // Remove all existing nodes 904 NodeIterator it = _node.getNodes(dataName); 905 while (it.hasNext()) 906 { 907 Node next = it.nextNode(); 908 next.remove(); 909 } 910 } 911 else 912 { 913 throw new UnknownDataException("No data found for '" + dataName + "' in repository data at path '" + this + "'."); 914 } 915 } 916 catch (RepositoryException e) 917 { 918 throw new AmetysRepositoryException("Unable to remove data '" + _getFullName(name, prefix) + "' in repository data at path '" + this + "'.", e); 919 } 920 } 921 922 private String _getFullName(String name, String prefix) 923 { 924 return StringUtils.isEmpty(prefix) ? name : prefix + ":" + name; 925 } 926 927 private void _checkLock() throws RepositoryException 928 { 929 if (!_lockAlreadyChecked && _node.isLocked()) 930 { 931 LockManager lockManager = _node.getSession().getWorkspace().getLockManager(); 932 933 Lock lock = lockManager.getLock(_node.getPath()); 934 Node lockHolder = lock.getNode(); 935 936 lockManager.addLockToken(lockHolder.getProperty(RepositoryConstants.METADATA_LOCKTOKEN).getString()); 937 _lockAlreadyChecked = true; 938 } 939 } 940 941 /** 942 * Retrieves the underlying node. 943 * @return the underlying node. 944 */ 945 public Node getNode() 946 { 947 return _node; 948 } 949 950 /** 951 * Retrieves the current session 952 * @return he session 953 * @throws AmetysRepositoryException if an error occurs 954 */ 955 public Session getSession() throws AmetysRepositoryException 956 { 957 try 958 { 959 return _node.getSession(); 960 } 961 catch (RepositoryException e) 962 { 963 throw new AmetysRepositoryException("unable to retrieve the session of the repository data at path '" + this + "'.", e); 964 } 965 } 966 967 public String getDefaultPrefix() 968 { 969 return _defaultPrefix; 970 } 971 972 @Override 973 public String toString() 974 { 975 try 976 { 977 return _node.getPath() + " (" + _node.getIdentifier() + ")"; 978 } 979 catch (RepositoryException e) 980 { 981 throw new AmetysRepositoryException("Unable to get infos about the repository data of node '" + _node + "'.", e); 982 } 983 } 984}