001 /* 002 * JBoss DNA (http://www.jboss.org/dna) 003 * See the COPYRIGHT.txt file distributed with this work for information 004 * regarding copyright ownership. Some portions may be licensed 005 * to Red Hat, Inc. under one or more contributor license agreements. 006 * See the AUTHORS.txt file in the distribution for a full listing of 007 * individual contributors. 008 * 009 * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA 010 * is licensed to you under the terms of the GNU Lesser General Public License as 011 * published by the Free Software Foundation; either version 2.1 of 012 * the License, or (at your option) any later version. 013 * 014 * JBoss DNA is distributed in the hope that it will be useful, 015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 017 * Lesser General Public License for more details. 018 * 019 * You should have received a copy of the GNU Lesser General Public 020 * License along with this software; if not, write to the Free 021 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 022 * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 023 */ 024 package org.jboss.dna.repository.util; 025 026 import java.io.IOException; 027 import java.io.InputStream; 028 import java.util.HashMap; 029 import java.util.Map; 030 import javax.jcr.Node; 031 import javax.jcr.NodeIterator; 032 import javax.jcr.PathNotFoundException; 033 import javax.jcr.Property; 034 import javax.jcr.PropertyType; 035 import javax.jcr.RepositoryException; 036 import javax.jcr.Session; 037 import javax.jcr.Value; 038 import javax.jcr.ValueFormatException; 039 import org.jboss.dna.common.collection.Problem; 040 import org.jboss.dna.common.collection.Problems; 041 import org.jboss.dna.common.util.IoUtil; 042 import org.jboss.dna.common.util.Logger; 043 import org.jboss.dna.common.util.StringUtil; 044 import org.jboss.dna.repository.RepositoryI18n; 045 046 /** 047 * @author Randall Hauch 048 */ 049 public class JcrTools { 050 051 public Map<String, Object> loadProperties( Node propertyContainer, Problems problems ) { 052 return loadProperties(propertyContainer, null, problems); 053 } 054 055 public Map<String, Object> loadProperties( Node propertyContainer, Map<String, Object> properties, Problems problems ) { 056 if (properties == null) properties = new HashMap<String, Object>(); 057 if (propertyContainer != null) { 058 try { 059 NodeIterator iter = propertyContainer.getNodes(); 060 while (iter.hasNext()) { 061 Node propertyNode = iter.nextNode(); 062 if (propertyNode != null && propertyNode.getPrimaryNodeType().isNodeType("dna:property")) { 063 String propertyName = propertyNode.getName(); 064 Object propertyValue = getPropertyValue(propertyNode, "dna:propertyValue", true, problems); 065 properties.put(propertyName, propertyValue); 066 } 067 } 068 } catch (RepositoryException e) { 069 problems.addError(e, RepositoryI18n.errorReadingPropertiesFromContainerNode, getReadable(propertyContainer)); 070 } 071 } 072 073 return properties; 074 } 075 076 public boolean removeProblems( Node parent ) throws RepositoryException { 077 Node problemsNode = null; 078 if (parent.hasNode("dna:problems")) { 079 problemsNode = parent.getNode("dna:problems"); 080 problemsNode.remove(); 081 return true; 082 } 083 return false; 084 } 085 086 public boolean storeProblems( Node parent, Problems problems ) throws RepositoryException { 087 Node problemsNode = null; 088 if (parent.hasNode("dna:problems")) { 089 problemsNode = parent.getNode("dna:problems"); 090 // Delete all problems ... 091 removeAllChildren(problemsNode); 092 } 093 if (problems.isEmpty()) { 094 return false; 095 } 096 if (problemsNode == null) { 097 problemsNode = parent.addNode("dna:problems"); // primary type dictated by child definition 098 } 099 100 // Add a child for each problem ... 101 for (Problem problem : problems) { 102 Node problemNode = problemsNode.addNode("problem", "dna:problem"); 103 // - dna:status (string) mandatory copy 104 // < 'ERROR', 'WARNING', 'INFO' 105 // - dna:message (string) mandatory copy 106 // - dna:code (string) copy 107 // - dna:type (string) copy 108 // - dna:resource (string) copy 109 // - dna:location (string) copy 110 // - dna:trace (string) copy 111 problemNode.setProperty("dna:status", problem.getStatus().name()); 112 problemNode.setProperty("dna:message", problem.getMessageString()); 113 if (problem.getCode() != Problem.DEFAULT_CODE) { 114 problemNode.setProperty("dna:code", Integer.toString(problem.getCode())); 115 } 116 String resource = problem.getResource(); 117 if (resource != null) { 118 problemNode.setProperty("dna:resource", resource); 119 } 120 String location = problem.getLocation(); 121 if (location != null) { 122 problemNode.setProperty("dna:location", location); 123 } 124 Throwable t = problem.getThrowable(); 125 if (t != null) { 126 String trace = StringUtil.getStackTrace(t); 127 problemNode.setProperty("dna:trace", trace); 128 } 129 } 130 return true; 131 } 132 133 public int removeAllChildren( Node node ) throws RepositoryException { 134 int childrenRemoved = 0; 135 NodeIterator iter = node.getNodes(); 136 while (iter.hasNext()) { 137 Node child = iter.nextNode(); 138 child.remove(); 139 ++childrenRemoved; 140 } 141 return childrenRemoved; 142 } 143 144 public String getPropertyAsString( Node node, String propertyName, boolean required, Problems problems ) { 145 return getPropertyAsString(node, propertyName, required, null); 146 } 147 148 public String getPropertyAsString( Node node, String propertyName, boolean required, String defaultValue, Problems problems ) { 149 try { 150 Property property = node.getProperty(propertyName); 151 return property.getString(); 152 } catch (ValueFormatException e) { 153 if (required) { 154 problems.addError(e, RepositoryI18n.requiredPropertyOnNodeWasExpectedToBeStringValue, propertyName, getReadable(node)); 155 } else { 156 problems.addError(e, RepositoryI18n.optionalPropertyOnNodeWasExpectedToBeStringValue, propertyName, getReadable(node)); 157 } 158 } catch (PathNotFoundException e) { 159 if (required) { 160 problems.addError(e, RepositoryI18n.requiredPropertyIsMissingFromNode, propertyName, getReadable(node)); 161 } 162 if (!required) return defaultValue; 163 } catch (RepositoryException err) { 164 if (required) { 165 problems.addError(err, RepositoryI18n.errorGettingRequiredPropertyFromNode, propertyName, getReadable(node)); 166 } else { 167 problems.addError(err, RepositoryI18n.errorGettingOptionalPropertyFromNode, propertyName, getReadable(node)); 168 } 169 } 170 return null; 171 } 172 173 public Object getPropertyValue( Node node, String propertyName, boolean required, Problems problems ) { 174 try { 175 Property property = node.getProperty(propertyName); 176 switch (property.getType()) { 177 case PropertyType.BINARY: { 178 InputStream stream = property.getStream(); 179 try { 180 stream = property.getStream(); 181 return IoUtil.readBytes(stream); 182 } finally { 183 if (stream != null) { 184 try { 185 stream.close(); 186 } catch (IOException e) { 187 // Log ... 188 Logger.getLogger(this.getClass()).error(e, RepositoryI18n.errorClosingBinaryStreamForPropertyFromNode, propertyName, node.getPath()); 189 } 190 } 191 } 192 } 193 default: { 194 return property.getString(); 195 } 196 } 197 } catch (IOException e) { 198 if (required) { 199 problems.addError(e, RepositoryI18n.requiredPropertyOnNodeCouldNotBeRead, propertyName, getReadable(node)); 200 } else { 201 problems.addError(e, RepositoryI18n.optionalPropertyOnNodeCouldNotBeRead, propertyName, getReadable(node)); 202 } 203 } catch (PathNotFoundException e) { 204 if (required) { 205 problems.addError(e, RepositoryI18n.requiredPropertyIsMissingFromNode, propertyName, getReadable(node)); 206 } 207 } catch (RepositoryException err) { 208 if (required) { 209 problems.addError(err, RepositoryI18n.errorGettingRequiredPropertyFromNode, propertyName, getReadable(node)); 210 } else { 211 problems.addError(err, RepositoryI18n.errorGettingOptionalPropertyFromNode, propertyName, getReadable(node)); 212 } 213 } 214 return null; 215 } 216 217 public String[] getPropertyAsStringArray( Node node, String propertyName, boolean required, Problems problems, String... defaultValues ) { 218 String[] result = defaultValues; 219 try { 220 Property property = node.getProperty(propertyName); 221 if (property.getDefinition().isMultiple()) { 222 Value[] values = property.getValues(); 223 result = new String[values.length]; 224 int i = 0; 225 for (Value value : values) { 226 result[i++] = value.getString(); 227 } 228 } else { 229 result = new String[] {property.getString()}; 230 } 231 } catch (ValueFormatException e) { 232 if (required) { 233 problems.addError(e, RepositoryI18n.requiredPropertyOnNodeWasExpectedToBeStringArrayValue, propertyName, getReadable(node)); 234 } else { 235 problems.addError(e, RepositoryI18n.optionalPropertyOnNodeWasExpectedToBeStringArrayValue, propertyName, getReadable(node)); 236 } 237 } catch (PathNotFoundException e) { 238 if (required) { 239 problems.addError(e, RepositoryI18n.requiredPropertyIsMissingFromNode, propertyName, getReadable(node)); 240 } 241 } catch (RepositoryException err) { 242 if (required) { 243 problems.addError(err, RepositoryI18n.errorGettingRequiredPropertyFromNode, propertyName, getReadable(node)); 244 } else { 245 problems.addError(err, RepositoryI18n.errorGettingOptionalPropertyFromNode, propertyName, getReadable(node)); 246 } 247 } 248 return result; 249 } 250 251 public Node getNode( Node node, String relativePath, boolean required, Problems problems ) { 252 Node result = null; 253 try { 254 result = node.getNode(relativePath); 255 } catch (PathNotFoundException e) { 256 if (required) problems.addError(e, RepositoryI18n.requiredNodeDoesNotExistRelativeToNode, relativePath, getReadable(node)); 257 } catch (RepositoryException err) { 258 problems.addError(err, RepositoryI18n.errorGettingNodeRelativeToNode, relativePath, getReadable(node)); 259 } 260 return result; 261 } 262 263 public String getReadable( Node node ) { 264 if (node == null) return ""; 265 try { 266 return node.getPath(); 267 } catch (RepositoryException err) { 268 return node.toString(); 269 } 270 } 271 272 public Node findOrCreateNode( Session session, String path ) throws RepositoryException { 273 return findOrCreateNode(session, path, null, null); 274 } 275 276 public Node findOrCreateNode( Session session, String path, String nodeType ) throws RepositoryException { 277 return findOrCreateNode(session, path, nodeType, nodeType); 278 } 279 280 public Node findOrCreateNode( Session session, String path, String defaultNodeType, String finalNodeType ) throws RepositoryException { 281 Node root = session.getRootNode(); 282 return findOrCreateNode(session, root, path, defaultNodeType, finalNodeType); 283 } 284 285 public Node findOrCreateNode( Session session, Node parentNode, String path, String defaultNodeType, String finalNodeType ) throws RepositoryException { 286 // Remove leading and trailing slashes ... 287 String relPath = path.replaceAll("^/+", "").replaceAll("/+$", ""); 288 289 // Look for the node first ... 290 try { 291 return parentNode.getNode(relPath); 292 } catch (PathNotFoundException e) { 293 // continue 294 } 295 // Create the node, which has to be done segment by segment ... 296 String[] pathSegments = relPath.split("/"); 297 Node node = parentNode; 298 for (int i = 0, len = pathSegments.length; i != len; ++i) { 299 String pathSegment = pathSegments[i]; 300 pathSegment = pathSegment.trim(); 301 if (pathSegment.length() == 0) continue; 302 if (node.hasNode(pathSegment)) { 303 // Find the existing node ... 304 node = node.getNode(pathSegment); 305 } else { 306 // Make sure there is no index on the final segment ... 307 String pathSegmentWithNoIndex = pathSegment.replaceAll("(\\[\\d+\\])+$", ""); 308 // Create the node ... 309 String nodeType = defaultNodeType; 310 if (i == len - 1 && finalNodeType != null) nodeType = finalNodeType; 311 if (nodeType != null) { 312 node = node.addNode(pathSegmentWithNoIndex, nodeType); 313 } else { 314 node = node.addNode(pathSegmentWithNoIndex); 315 } 316 } 317 } 318 return node; 319 } 320 321 public Node findOrCreateChild( Session session, Node parent, String name ) throws RepositoryException { 322 return findOrCreateChild(session, parent, name, null); 323 } 324 325 public Node findOrCreateChild( Session session, Node parent, String name, String nodeType ) throws RepositoryException { 326 return findOrCreateNode(session, parent, name, nodeType, nodeType); 327 } 328 329 }