/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.sling.jcr.classloader.internal; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import javax.jcr.Item; import javax.jcr.ItemNotFoundException; import javax.jcr.Node; import javax.jcr.Property; import javax.jcr.PropertyType; import javax.jcr.RepositoryException; import javax.jcr.ValueFormatException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * The <code>Util</code> provides helper methods for the repository * classloader and its class path entry and resource classes. * <p> * This class may not be extended or instantiated, it just contains static * utility methods. */ public class Util { /** default logging */ private static final Logger log = LoggerFactory.getLogger(Util.class); /** Private constructor to not instantiate */ private Util() { } /** * Resolves the given <code>item</code> to a <code>Property</code> from * which contents can be read. * <p> * The following mechanism is used to derive the contents: * <ol> * <li>If the <code>item</code> is a property, this property is used</li> * <li>If the <code>item</code> is a node, three steps are tested: * <ol> * <li>If the node has a <code>jcr:content</code> child node, use that * child node in the next steps. Otherwise continue with the node.</li> * <li>Check for a <code>jcr:data</code> property and use that property * if existing.</li> * <li>Otherwise call <code>getPrimaryItem</code> method repeatedly until * a property is returned or until no more primary item is available.</li> * </ol> * </ol> * If no property can be resolved using the above algorithm or if the * resulting property is a multivalue property, <code>null</code> is * returned. Otherwise if the resulting property is a <code>REFERENCE</code> * property, the node referred to is retrieved and this method is called * recursively with the node. Otherwise, the resulting property is returned. * * @param item The <code>Item</code> to resolve to a <code>Property</code>. * @return The resolved <code>Property</code> or <code>null</code> if * the resolved property is a multi-valued property or the * <code>item</code> is a node which cannot be resolved to a data * property. * @throws ValueFormatException If the <code>item</code> resolves to a * single-valued <code>REFERENCE</code> type property which * cannot be resolved to the node referred to. * @throws RepositoryException if another error occurrs accessing the * repository. */ public static Property getProperty(Item item) throws ValueFormatException, RepositoryException { Property prop; if (item.isNode()) { // check whether the node has a jcr:content node (e.g. nt:file) Node node = (Node) item; if (node.hasNode("jcr:content")) { node = node.getNode("jcr:content"); } // if the node has a jcr:data property, use that property if (node.hasProperty("jcr:data")) { prop = node.getProperty("jcr:data"); } else { // otherwise try to follow default item trail try { item = node.getPrimaryItem(); while (item.isNode()) { item = ((Node) item).getPrimaryItem(); } prop = (Property) item; } catch (ItemNotFoundException infe) { // we don't actually care, but log for completeness log.debug("getProperty: No primary items for " + node.getPath(), infe); return null; } } } else { prop = (Property) item; } // we get here with a property - otherwise an exception has already // been thrown if (prop.getDefinition().isMultiple()) { log.error("{} is a multivalue property", prop.getPath()); return null; } else if (prop.getType() == PropertyType.REFERENCE) { Node node = prop.getNode(); log.info("Property {} refers to node {}; finding primary item", prop.getPath(), node.getPath()); return getProperty(node); } return prop; } /** * Returns the resource as an array of bytes */ public static byte[] getBytes(final Node node) throws IOException, RepositoryException { InputStream in = null; try { in = getProperty(node).getStream(); final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final byte[] buffer = new byte[2048]; int l = 0; while ( (l = in.read(buffer)) > -1 ) { baos.write(buffer, 0, l); } return baos.toByteArray(); } finally { if (in != null) { try { in.close(); } catch (final IOException ignore) { // ignore } } } } }