blob: 30e86475ddea0d511be80c9aa4c25b8c9ebf5823 [file] [log] [blame]
/*
* 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
}
}
}
}
}