3 import java
.io
.ByteArrayOutputStream
;
4 import java
.io
.IOException
;
5 import java
.io
.InputStream
;
6 import java
.math
.BigDecimal
;
7 import java
.text
.MessageFormat
;
8 import java
.time
.Instant
;
9 import java
.util
.ArrayList
;
10 import java
.util
.Arrays
;
11 import java
.util
.Calendar
;
12 import java
.util
.Collections
;
13 import java
.util
.Date
;
14 import java
.util
.GregorianCalendar
;
15 import java
.util
.Iterator
;
16 import java
.util
.List
;
18 import javax
.jcr
.Binary
;
19 import javax
.jcr
.ItemNotFoundException
;
20 import javax
.jcr
.Node
;
21 import javax
.jcr
.NodeIterator
;
22 import javax
.jcr
.Property
;
23 import javax
.jcr
.PropertyType
;
24 import javax
.jcr
.Repository
;
25 import javax
.jcr
.RepositoryException
;
26 import javax
.jcr
.Session
;
27 import javax
.jcr
.Value
;
28 import javax
.jcr
.Workspace
;
29 import javax
.jcr
.nodetype
.NodeType
;
30 import javax
.jcr
.query
.Query
;
31 import javax
.jcr
.query
.QueryManager
;
32 import javax
.jcr
.security
.Privilege
;
33 import javax
.jcr
.version
.Version
;
34 import javax
.jcr
.version
.VersionHistory
;
35 import javax
.jcr
.version
.VersionIterator
;
36 import javax
.jcr
.version
.VersionManager
;
38 import org
.apache
.commons
.io
.IOUtils
;
41 * Utility class whose purpose is to make using JCR less verbose by
42 * systematically using unchecked exceptions and returning <code>null</code>
43 * when something is not found. This is especially useful when writing user
44 * interfaces (such as with SWT) where listeners and callbacks expect unchecked
45 * exceptions. Loosely inspired by Java's <code>Files</code> singleton.
49 * The name of a node which will be serialized as XML text, as per section 7.3.1
50 * of the JCR 2.0 specifications.
52 public final static String JCR_XMLTEXT
= "jcr:xmltext";
54 * The name of a property which will be serialized as XML text, as per section
55 * 7.3.1 of the JCR 2.0 specifications.
57 public final static String JCR_XMLCHARACTERS
= "jcr:xmlcharacters";
59 * <code>jcr:name</code>, when used in another context than
60 * {@link Property#JCR_NAME}, typically to name a node rather than a property.
62 public final static String JCR_NAME
= "jcr:name";
64 * <code>jcr:path</code>, when used in another context than
65 * {@link Property#JCR_PATH}, typically to name a node rather than a property.
67 public final static String JCR_PATH
= "jcr:path";
69 * <code>jcr:primaryType</code> with prefix instead of namespace (as in
70 * {@link Property#JCR_PRIMARY_TYPE}.
72 public final static String JCR_PRIMARY_TYPE
= "jcr:primaryType";
74 * <code>jcr:mixinTypes</code> with prefix instead of namespace (as in
75 * {@link Property#JCR_MIXIN_TYPES}.
77 public final static String JCR_MIXIN_TYPES
= "jcr:mixinTypes";
79 * <code>jcr:uuid</code> with prefix instead of namespace (as in
80 * {@link Property#JCR_UUID}.
82 public final static String JCR_UUID
= "jcr:uuid";
84 * <code>jcr:created</code> with prefix instead of namespace (as in
85 * {@link Property#JCR_CREATED}.
87 public final static String JCR_CREATED
= "jcr:created";
89 * <code>jcr:createdBy</code> with prefix instead of namespace (as in
90 * {@link Property#JCR_CREATED_BY}.
92 public final static String JCR_CREATED_BY
= "jcr:createdBy";
94 * <code>jcr:lastModified</code> with prefix instead of namespace (as in
95 * {@link Property#JCR_LAST_MODIFIED}.
97 public final static String JCR_LAST_MODIFIED
= "jcr:lastModified";
99 * <code>jcr:lastModifiedBy</code> with prefix instead of namespace (as in
100 * {@link Property#JCR_LAST_MODIFIED_BY}.
102 public final static String JCR_LAST_MODIFIED_BY
= "jcr:lastModifiedBy";
105 * @see Node#isNodeType(String)
106 * @throws JcrException caused by {@link RepositoryException}
108 public static boolean isNodeType(Node node
, String nodeTypeName
) {
110 return node
.isNodeType(nodeTypeName
);
111 } catch (RepositoryException e
) {
112 throw new JcrException("Cannot get whether " + node
+ " is of type " + nodeTypeName
, e
);
117 * @see Node#hasNodes()
118 * @throws JcrException caused by {@link RepositoryException}
120 public static boolean hasNodes(Node node
) {
122 return node
.hasNodes();
123 } catch (RepositoryException e
) {
124 throw new JcrException("Cannot get whether " + node
+ " has children.", e
);
129 * @see Node#getParent()
130 * @throws JcrException caused by {@link RepositoryException}
132 public static Node
getParent(Node node
) {
134 return isRoot(node
) ?
null : node
.getParent();
135 } catch (RepositoryException e
) {
136 throw new JcrException("Cannot get parent of " + node
, e
);
141 * @see Node#getParent()
142 * @throws JcrException caused by {@link RepositoryException}
144 public static String
getParentPath(Node node
) {
145 return getPath(getParent(node
));
149 * Whether this node is the root node.
151 * @throws JcrException caused by {@link RepositoryException}
153 public static boolean isRoot(Node node
) {
155 return node
.getDepth() == 0;
156 } catch (RepositoryException e
) {
157 throw new JcrException("Cannot get depth of " + node
, e
);
162 * @see Node#getPath()
163 * @throws JcrException caused by {@link RepositoryException}
165 public static String
getPath(Node node
) {
167 return node
.getPath();
168 } catch (RepositoryException e
) {
169 throw new JcrException("Cannot get path of " + node
, e
);
174 * @see Node#getSession()
175 * @see Session#getWorkspace()
176 * @see Workspace#getName()
178 public static String
getWorkspaceName(Node node
) {
179 return session(node
).getWorkspace().getName();
183 * @see Node#getIdentifier()
184 * @throws JcrException caused by {@link RepositoryException}
186 public static String
getIdentifier(Node node
) {
188 return node
.getIdentifier();
189 } catch (RepositoryException e
) {
190 throw new JcrException("Cannot get identifier of " + node
, e
);
195 * @see Node#getName()
196 * @throws JcrException caused by {@link RepositoryException}
198 public static String
getName(Node node
) {
200 return node
.getName();
201 } catch (RepositoryException e
) {
202 throw new JcrException("Cannot get name of " + node
, e
);
207 * @see Node#getProperty(String)
208 * @throws JcrException caused by {@link RepositoryException}
210 public static Property
getProperty(Node node
, String property
) {
212 if (node
.hasProperty(property
))
213 return node
.getProperty(property
);
216 } catch (RepositoryException e
) {
217 throw new JcrException("Cannot get property " + property
+ " of " + node
, e
);
222 * @see Node#getIndex()
223 * @throws JcrException caused by {@link RepositoryException}
225 public static int getIndex(Node node
) {
227 return node
.getIndex();
228 } catch (RepositoryException e
) {
229 throw new JcrException("Cannot get index of " + node
, e
);
234 * If node has mixin {@link NodeType#MIX_TITLE}, return
235 * {@link Property#JCR_TITLE}, otherwise return {@link #getName(Node)}.
237 public static String
getTitle(Node node
) {
238 if (Jcr
.isNodeType(node
, NodeType
.MIX_TITLE
))
239 return get(node
, Property
.JCR_TITLE
);
241 return Jcr
.getName(node
);
244 /** Accesses a {@link NodeIterator} as an {@link Iterable}. */
245 @SuppressWarnings("unchecked")
246 public static Iterable
<Node
> iterate(NodeIterator nodeIterator
) {
247 return new Iterable
<Node
>() {
250 public Iterator
<Node
> iterator() {
257 * @return the children as an {@link Iterable} for use in for-each llops.
258 * @see Node#getNodes()
259 * @throws JcrException caused by {@link RepositoryException}
261 public static Iterable
<Node
> nodes(Node node
) {
263 return iterate(node
.getNodes());
264 } catch (RepositoryException e
) {
265 throw new JcrException("Cannot get children of " + node
, e
);
270 * @return the children as a (possibly empty) {@link List}.
271 * @see Node#getNodes()
272 * @throws JcrException caused by {@link RepositoryException}
274 public static List
<Node
> getNodes(Node node
) {
275 List
<Node
> nodes
= new ArrayList
<>();
277 if (node
.hasNodes()) {
278 NodeIterator nit
= node
.getNodes();
279 while (nit
.hasNext())
280 nodes
.add(nit
.nextNode());
284 } catch (RepositoryException e
) {
285 throw new JcrException("Cannot get children of " + node
, e
);
290 * @return the child or <code>null</node> if not found
291 * @see Node#getNode(String)
292 * @throws JcrException caused by {@link RepositoryException}
294 public static Node
getNode(Node node
, String child
) {
296 if (node
.hasNode(child
))
297 return node
.getNode(child
);
300 } catch (RepositoryException e
) {
301 throw new JcrException("Cannot get child of " + node
, e
);
306 * @return the node at this path or <code>null</node> if not found
307 * @see Session#getNode(String)
308 * @throws JcrException caused by {@link RepositoryException}
310 public static Node
getNode(Session session
, String path
) {
312 if (session
.nodeExists(path
))
313 return session
.getNode(path
);
316 } catch (RepositoryException e
) {
317 throw new JcrException("Cannot get node " + path
, e
);
322 * Add a node to this parent, setting its primary type and its mixins.
324 * @param parent the parent node
325 * @param name the name of the node, if <code>null</code>, the primary
326 * type will be used (typically for XML structures)
327 * @param primaryType the primary type, if <code>null</code>
328 * {@link NodeType#NT_UNSTRUCTURED} will be used.
329 * @param mixins the mixins
330 * @return the created node
331 * @see Node#addNode(String, String)
332 * @see Node#addMixin(String)
334 public static Node
addNode(Node parent
, String name
, String primaryType
, String
... mixins
) {
335 if (name
== null && primaryType
== null)
336 throw new IllegalArgumentException("Both node name and primary type cannot be null");
338 Node newNode
= parent
.addNode(name
== null ? primaryType
: name
,
339 primaryType
== null ? NodeType
.NT_UNSTRUCTURED
: primaryType
);
340 for (String mixin
: mixins
) {
341 newNode
.addMixin(mixin
);
344 } catch (RepositoryException e
) {
345 throw new JcrException("Cannot add node " + name
+ " to " + parent
, e
);
350 * Add an {@link NodeType#NT_BASE} node to this parent.
352 * @param parent the parent node
353 * @param name the name of the node, cannot be <code>null</code>
354 * @return the created node
356 * @see Node#addNode(String)
358 public static Node
addNode(Node parent
, String name
) {
360 throw new IllegalArgumentException("Node name cannot be null");
362 Node newNode
= parent
.addNode(name
);
364 } catch (RepositoryException e
) {
365 throw new JcrException("Cannot add node " + name
+ " to " + parent
, e
);
370 * Add mixins to a node.
372 * @param node the node
373 * @param mixins the mixins
374 * @return the created node
375 * @see Node#addMixin(String)
377 public static void addMixin(Node node
, String
... mixins
) {
379 for (String mixin
: mixins
) {
380 node
.addMixin(mixin
);
382 } catch (RepositoryException e
) {
383 throw new JcrException("Cannot add mixins " + Arrays
.asList(mixins
) + " to " + node
, e
);
392 public static void remove(Node node
) {
395 } catch (RepositoryException e
) {
396 throw new JcrException("Cannot remove node " + node
, e
);
401 * @return the node with htis id or <code>null</node> if not found
402 * @see Session#getNodeByIdentifier(String)
403 * @throws JcrException caused by {@link RepositoryException}
405 public static Node
getNodeById(Session session
, String id
) {
407 return session
.getNodeByIdentifier(id
);
408 } catch (ItemNotFoundException e
) {
410 } catch (RepositoryException e
) {
411 throw new JcrException("Cannot get node with id " + id
, e
);
416 * Set a property to the given value, or remove it if the value is
419 * @throws JcrException caused by {@link RepositoryException}
421 public static void set(Node node
, String property
, Object value
) {
423 if (!node
.hasProperty(property
)) {
425 if (value
instanceof List
) {// multiple
426 List
<?
> lst
= (List
<?
>) value
;
427 String
[] values
= new String
[lst
.size()];
428 for (int i
= 0; i
< lst
.size(); i
++) {
429 values
[i
] = lst
.get(i
).toString();
431 node
.setProperty(property
, values
);
433 node
.setProperty(property
, value
.toString());
438 Property prop
= node
.getProperty(property
);
445 if (value
instanceof List
) {
446 List
<?
> lst
= (List
<?
>) value
;
447 String
[] values
= new String
[lst
.size()];
449 for (int i
= 0; i
< lst
.size(); i
++) {
450 values
[i
] = lst
.get(i
).toString();
452 if (!prop
.isMultiple())
454 node
.setProperty(property
, values
);
459 if (prop
.isMultiple()) {
461 node
.setProperty(property
, value
.toString());
465 if (value
instanceof String
)
466 prop
.setValue((String
) value
);
467 else if (value
instanceof Long
)
468 prop
.setValue((Long
) value
);
469 else if (value
instanceof Integer
)
470 prop
.setValue(((Integer
) value
).longValue());
471 else if (value
instanceof Double
)
472 prop
.setValue((Double
) value
);
473 else if (value
instanceof Float
)
474 prop
.setValue(((Float
) value
).doubleValue());
475 else if (value
instanceof Calendar
)
476 prop
.setValue((Calendar
) value
);
477 else if (value
instanceof BigDecimal
)
478 prop
.setValue((BigDecimal
) value
);
479 else if (value
instanceof Boolean
)
480 prop
.setValue((Boolean
) value
);
481 else if (value
instanceof byte[])
482 JcrUtils
.setBinaryAsBytes(prop
, (byte[]) value
);
483 else if (value
instanceof Instant
) {
484 Instant instant
= (Instant
) value
;
485 GregorianCalendar calendar
= new GregorianCalendar();
486 calendar
.setTime(Date
.from(instant
));
487 prop
.setValue(calendar
);
488 } else // try with toString()
489 prop
.setValue(value
.toString());
490 } catch (RepositoryException e
) {
491 throw new JcrException("Cannot set property " + property
+ " of " + node
+ " to " + value
, e
);
496 * Get property as {@link String}.
498 * @return the value of
499 * {@link Node#getProperty(String)}.{@link Property#getString()} or
500 * <code>null</code> if the property does not exist.
501 * @throws JcrException caused by {@link RepositoryException}
503 public static String
get(Node node
, String property
) {
504 return get(node
, property
, null);
508 * Get property as a {@link String}. If the property is multiple it returns the
511 * @return the value of
512 * {@link Node#getProperty(String)}.{@link Property#getString()} or
513 * <code>defaultValue</code> if the property does not exist.
514 * @throws JcrException caused by {@link RepositoryException}
516 public static String
get(Node node
, String property
, String defaultValue
) {
518 if (node
.hasProperty(property
)) {
519 Property p
= node
.getProperty(property
);
521 return p
.getString();
523 Value
[] values
= p
.getValues();
524 if (values
.length
== 0)
527 return values
[0].getString();
531 } catch (RepositoryException e
) {
532 throw new JcrException("Cannot retrieve property " + property
+ " from " + node
, e
);
537 * Get property as a {@link Value}.
539 * @return {@link Node#getProperty(String)} or <code>null</code> if the property
541 * @throws JcrException caused by {@link RepositoryException}
543 public static Value
getValue(Node node
, String property
) {
545 if (node
.hasProperty(property
))
546 return node
.getProperty(property
).getValue();
549 } catch (RepositoryException e
) {
550 throw new JcrException("Cannot retrieve property " + property
+ " from " + node
, e
);
555 * Get property doing a best effort to cast it as the target object.
557 * @return the value of {@link Node#getProperty(String)} or
558 * <code>defaultValue</code> if the property does not exist.
559 * @throws IllegalArgumentException if the value could not be cast
560 * @throws JcrException in case of unexpected
561 * {@link RepositoryException}
563 @SuppressWarnings("unchecked")
564 public static <T
> T
getAs(Node node
, String property
, T defaultValue
) {
566 // TODO deal with multiple
567 if (node
.hasProperty(property
)) {
568 Property p
= node
.getProperty(property
);
570 if (p
.isMultiple()) {
571 throw new UnsupportedOperationException("Multiple values properties are not supported");
573 Value value
= p
.getValue();
574 return (T
) get(value
);
575 } catch (ClassCastException e
) {
576 throw new IllegalArgumentException(
577 "Cannot cast property of type " + PropertyType
.nameFromValue(p
.getType()), e
);
582 } catch (RepositoryException e
) {
583 throw new JcrException("Cannot retrieve property " + property
+ " from " + node
, e
);
588 * Get a multiple property as a list, doing a best effort to cast it as the
591 * @return the value of {@link Node#getProperty(String)}.
592 * @throws IllegalArgumentException if the value could not be cast
593 * @throws JcrException in case of unexpected
594 * {@link RepositoryException}
596 public static <T
> List
<T
> getMultiple(Node node
, String property
) {
598 if (node
.hasProperty(property
)) {
599 Property p
= node
.getProperty(property
);
600 return getMultiple(p
);
604 } catch (RepositoryException e
) {
605 throw new JcrException("Cannot retrieve multiple values property " + property
+ " from " + node
, e
);
610 * Get a multiple property as a list, doing a best effort to cast it as the
613 @SuppressWarnings("unchecked")
614 public static <T
> List
<T
> getMultiple(Property p
) {
616 List
<T
> res
= new ArrayList
<>();
617 if (!p
.isMultiple()) {
618 res
.add((T
) get(p
.getValue()));
621 Value
[] values
= p
.getValues();
622 for (Value value
: values
) {
623 res
.add((T
) get(value
));
626 } catch (ClassCastException
| RepositoryException e
) {
627 throw new IllegalArgumentException("Cannot get property " + p
, e
);
631 /** Cast a {@link Value} to a standard Java object. */
632 public static Object
get(Value value
) {
633 Binary binary
= null;
635 switch (value
.getType()) {
636 case PropertyType
.STRING
:
637 return value
.getString();
638 case PropertyType
.DOUBLE
:
639 return (Double
) value
.getDouble();
640 case PropertyType
.LONG
:
641 return (Long
) value
.getLong();
642 case PropertyType
.BOOLEAN
:
643 return (Boolean
) value
.getBoolean();
644 case PropertyType
.DATE
:
645 return value
.getDate();
646 case PropertyType
.BINARY
:
647 binary
= value
.getBinary();
649 try (InputStream in
= binary
.getStream(); ByteArrayOutputStream out
= new ByteArrayOutputStream();) {
650 IOUtils
.copy(in
, out
);
651 arr
= out
.toByteArray();
652 } catch (IOException e
) {
653 throw new RuntimeException("Cannot read binary from " + value
, e
);
657 return value
.getString();
659 } catch (RepositoryException e
) {
660 throw new JcrException("Cannot cast value from " + value
, e
);
668 * Retrieves the {@link Session} related to this node.
670 * @deprecated Use {@link #getSession(Node)} instead.
673 public static Session
session(Node node
) {
674 return getSession(node
);
677 /** Retrieves the {@link Session} related to this node. */
678 public static Session
getSession(Node node
) {
680 return node
.getSession();
681 } catch (RepositoryException e
) {
682 throw new JcrException("Cannot retrieve session related to " + node
, e
);
686 /** Retrieves the root node related to this session. */
687 public static Node
getRootNode(Session session
) {
689 return session
.getRootNode();
690 } catch (RepositoryException e
) {
691 throw new JcrException("Cannot get root node for " + session
, e
);
695 /** Whether this item exists. */
696 public static boolean itemExists(Session session
, String path
) {
698 return session
.itemExists(path
);
699 } catch (RepositoryException e
) {
700 throw new JcrException("Cannot check whether " + path
+ " exists", e
);
705 * Saves the {@link Session} related to this node. Note that all other unrelated
706 * modifications in this session will also be saved.
708 public static void save(Node node
) {
710 Session session
= node
.getSession();
711 // if (node.isNodeType(NodeType.MIX_LAST_MODIFIED)) {
712 // set(node, Property.JCR_LAST_MODIFIED, Instant.now());
713 // set(node, Property.JCR_LAST_MODIFIED_BY, session.getUserID());
715 if (session
.hasPendingChanges())
717 } catch (RepositoryException e
) {
718 throw new JcrException("Cannot save session related to " + node
+ " in workspace "
719 + session(node
).getWorkspace().getName(), e
);
723 /** Login to a JCR repository. */
724 public static Session
login(Repository repository
, String workspace
) {
726 return repository
.login(workspace
);
727 } catch (RepositoryException e
) {
728 throw new IllegalArgumentException("Cannot login to repository", e
);
732 /** Safely and silently logs out a session. */
733 public static void logout(Session session
) {
736 if (session
.isLive())
738 } catch (Exception e
) {
743 /** Safely and silently logs out the underlying session. */
744 public static void logout(Node node
) {
745 Jcr
.logout(session(node
));
752 * Add a single privilege to a node.
756 public static void addPrivilege(Node node
, String principal
, String privilege
) {
758 Session session
= node
.getSession();
759 JcrUtils
.addPrivilege(session
, node
.getPath(), principal
, privilege
);
760 } catch (RepositoryException e
) {
761 throw new JcrException("Cannot add privilege " + privilege
+ " to " + node
, e
);
768 /** Get checked out status. */
769 public static boolean isCheckedOut(Node node
) {
771 return node
.isCheckedOut();
772 } catch (RepositoryException e
) {
773 throw new JcrException("Cannot retrieve checked out status of " + node
, e
);
777 /** @see VersionManager#checkpoint(String) */
778 public static void checkpoint(Node node
) {
780 versionManager(node
).checkpoint(node
.getPath());
781 } catch (RepositoryException e
) {
782 throw new JcrException("Cannot check in " + node
, e
);
786 /** @see VersionManager#checkin(String) */
787 public static void checkin(Node node
) {
789 versionManager(node
).checkin(node
.getPath());
790 } catch (RepositoryException e
) {
791 throw new JcrException("Cannot check in " + node
, e
);
795 /** @see VersionManager#checkout(String) */
796 public static void checkout(Node node
) {
798 versionManager(node
).checkout(node
.getPath());
799 } catch (RepositoryException e
) {
800 throw new JcrException("Cannot check out " + node
, e
);
804 /** Get the {@link VersionManager} related to this node. */
805 public static VersionManager
versionManager(Node node
) {
807 return node
.getSession().getWorkspace().getVersionManager();
808 } catch (RepositoryException e
) {
809 throw new JcrException("Cannot get version manager from " + node
, e
);
813 /** Get the {@link VersionHistory} related to this node. */
814 public static VersionHistory
getVersionHistory(Node node
) {
816 return versionManager(node
).getVersionHistory(node
.getPath());
817 } catch (RepositoryException e
) {
818 throw new JcrException("Cannot get version history from " + node
, e
);
823 * The linear versions of this version history in reverse order and without the
826 public static List
<Version
> getLinearVersions(VersionHistory versionHistory
) {
828 List
<Version
> lst
= new ArrayList
<>();
829 VersionIterator vit
= versionHistory
.getAllLinearVersions();
830 while (vit
.hasNext())
831 lst
.add(vit
.nextVersion());
833 Collections
.reverse(lst
);
835 } catch (RepositoryException e
) {
836 throw new JcrException("Cannot get linear versions from " + versionHistory
, e
);
840 /** The frozen node related to this {@link Version}. */
841 public static Node
getFrozenNode(Version version
) {
843 return version
.getFrozenNode();
844 } catch (RepositoryException e
) {
845 throw new JcrException("Cannot get frozen node from " + version
, e
);
849 /** Get the base {@link Version} related to this node. */
850 public static Version
getBaseVersion(Node node
) {
852 return versionManager(node
).getBaseVersion(node
.getPath());
853 } catch (RepositoryException e
) {
854 throw new JcrException("Cannot get base version from " + node
, e
);
862 * Returns the size of this file.
864 * @see NodeType#NT_FILE
866 public static long getFileSize(Node fileNode
) {
868 if (!fileNode
.isNodeType(NodeType
.NT_FILE
))
869 throw new IllegalArgumentException(fileNode
+ " must be a file.");
870 return getBinarySize(fileNode
.getNode(Node
.JCR_CONTENT
).getProperty(Property
.JCR_DATA
).getBinary());
871 } catch (RepositoryException e
) {
872 throw new JcrException("Cannot get file size of " + fileNode
, e
);
876 /** Returns the size of this {@link Binary}. */
877 public static long getBinarySize(Binary binaryArg
) {
879 try (Bin binary
= new Bin(binaryArg
)) {
880 return binary
.getSize();
882 } catch (RepositoryException e
) {
883 throw new JcrException("Cannot get file size of binary " + binaryArg
, e
);
888 /** Creates a JCR-SQL2 query using {@link MessageFormat}. */
889 public static Query
createQuery(QueryManager qm
, String sql
, Object
... args
) {
890 String query
= MessageFormat
.format(sql
, args
);
892 return qm
.createQuery(query
, Query
.JCR_SQL2
);
893 } catch (RepositoryException e
) {
894 throw new JcrException("Cannot create JCR-SQL2 query from " + query
, e
);
898 /** Executes a JCR-SQL2 query using {@link MessageFormat}. */
899 public static NodeIterator
executeQuery(QueryManager qm
, String sql
, Object
... args
) {
900 Query query
= createQuery(qm
, sql
, args
);
902 return query
.execute().getNodes();
903 } catch (RepositoryException e
) {
904 throw new JcrException("Cannot execute query " + sql
+ " with arguments " + Arrays
.asList(args
), e
);
908 /** Executes a JCR-SQL2 query using {@link MessageFormat}. */
909 public static NodeIterator
executeQuery(Session session
, String sql
, Object
... args
) {
910 QueryManager queryManager
;
912 queryManager
= session
.getWorkspace().getQueryManager();
913 } catch (RepositoryException e
) {
914 throw new JcrException("Cannot get query manager from session " + session
, e
);
916 return executeQuery(queryManager
, sql
, args
);
920 * Executes a JCR-SQL2 query using {@link MessageFormat}, which must return a
921 * single node at most.
923 * @return the node or <code>null</code> if not found.
925 public static Node
getNode(QueryManager qm
, String sql
, Object
... args
) {
926 NodeIterator nit
= executeQuery(qm
, sql
, args
);
928 Node node
= nit
.nextNode();
930 throw new IllegalStateException(
931 "Query " + sql
+ " with arguments " + Arrays
.asList(args
) + " returned more than one node.");
939 * Executes a JCR-SQL2 query using {@link MessageFormat}, which must return a
940 * single node at most.
942 * @return the node or <code>null</code> if not found.
944 public static Node
getNode(Session session
, String sql
, Object
... args
) {
945 QueryManager queryManager
;
947 queryManager
= session
.getWorkspace().getQueryManager();
948 } catch (RepositoryException e
) {
949 throw new JcrException("Cannot get query manager from session " + session
, e
);
951 return getNode(queryManager
, sql
, args
);