You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by vr...@apache.org on 2012/02/02 13:47:01 UTC
svn commit: r1239587 [6/9] - in
/sling/whiteboard/resourceresolverfactory/jcr-resource: ./ src/ src/main/
src/main/appended-resources/ src/main/appended-resources/META-INF/
src/main/java/ src/main/java/org/ src/main/java/org/apache/
src/main/java/org/a...
Added: sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/URIException.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/URIException.java?rev=1239587&view=auto
==============================================================================
--- sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/URIException.java (added)
+++ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/URIException.java Thu Feb 2 12:46:58 2012
@@ -0,0 +1,124 @@
+/*
+ * 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.resource.internal.helper;
+
+import org.apache.sling.api.SlingException;
+
+/**
+ * The URI parsing and escape encoding exception.
+ * <p>
+ * This class is a slightly modified version of the URIException class
+ * distributed with Http Client 3.1. The changes are removal of deprecated
+ * methods and have the class itself extend the <code>SlingException</code> to
+ * adapt it to the exception hierarchy of Sling.
+ */
+@SuppressWarnings("serial")
+public class URIException extends SlingException {
+
+ // ----------------------------------------------------------- constructors
+
+ /**
+ * Default constructor.
+ */
+ public URIException() {
+ }
+
+ /**
+ * The constructor with a reason code argument.
+ *
+ * @param reasonCode the reason code
+ */
+ public URIException(int reasonCode) {
+ this.reasonCode = reasonCode;
+ }
+
+ /**
+ * The constructor with a reason string and its code arguments.
+ *
+ * @param reasonCode the reason code
+ * @param reason the reason
+ */
+ public URIException(int reasonCode, String reason) {
+ super(reason); // for backward compatibility of Throwable
+ this.reason = reason;
+ this.reasonCode = reasonCode;
+ }
+
+ /**
+ * The constructor with a reason string argument.
+ *
+ * @param reason the reason
+ */
+ public URIException(String reason) {
+ super(reason); // for backward compatibility of Throwable
+ this.reason = reason;
+ this.reasonCode = UNKNOWN;
+ }
+
+ // -------------------------------------------------------------- constants
+
+ /**
+ * No specified reason code.
+ */
+ public static final int UNKNOWN = 0;
+
+ /**
+ * The URI parsing error.
+ */
+ public static final int PARSING = 1;
+
+ /**
+ * The unsupported character encoding.
+ */
+ public static final int UNSUPPORTED_ENCODING = 2;
+
+ /**
+ * The URI escape encoding and decoding error.
+ */
+ public static final int ESCAPING = 3;
+
+ /**
+ * The DNS punycode encoding or decoding error.
+ */
+ public static final int PUNYCODE = 4;
+
+ // ------------------------------------------------------------- properties
+
+ /**
+ * The reason code.
+ */
+ protected int reasonCode;
+
+ /**
+ * The reason message.
+ */
+ protected String reason;
+
+ // ---------------------------------------------------------------- methods
+
+ /**
+ * Get the reason code.
+ *
+ * @return the reason code
+ */
+ public int getReasonCode() {
+ return reasonCode;
+ }
+
+}
Added: sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/WrappedResourceProvider.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/WrappedResourceProvider.java?rev=1239587&view=auto
==============================================================================
--- sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/WrappedResourceProvider.java (added)
+++ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/WrappedResourceProvider.java Thu Feb 2 12:46:58 2012
@@ -0,0 +1,107 @@
+/*
+ * 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 SF 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.resource.internal.helper;
+
+import java.util.Iterator;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceProvider;
+import org.apache.sling.api.resource.ResourceResolver;
+
+/**
+ *
+ */
+public class WrappedResourceProvider implements ResourceProvider {
+
+ private ResourceProvider resourceProvider;
+ private Comparable<?> serviceReference;
+
+ /**
+ *
+ */
+ public WrappedResourceProvider(ResourceProvider resourceProvider, Comparable<?> serviceReference) {
+ this.resourceProvider = resourceProvider;
+ this.serviceReference = serviceReference;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see org.apache.sling.api.resource.ResourceProvider#getResource(org.apache.sling.api.resource.ResourceResolver, java.lang.String)
+ */
+ public Resource getResource(ResourceResolver arg0, String arg1) {
+ return resourceProvider.getResource(arg0, arg1);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see org.apache.sling.api.resource.ResourceProvider#getResource(org.apache.sling.api.resource.ResourceResolver, javax.servlet.http.HttpServletRequest, java.lang.String)
+ */
+ public Resource getResource(ResourceResolver arg0, HttpServletRequest arg1, String arg2) {
+ return resourceProvider.getResource(arg0, arg1, arg2);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see org.apache.sling.api.resource.ResourceProvider#listChildren(org.apache.sling.api.resource.Resource)
+ */
+ public Iterator<Resource> listChildren(Resource arg0) {
+ return resourceProvider.listChildren(arg0);
+ }
+
+ /**
+ *
+ */
+ public Comparable<?> getComparable() {
+ return serviceReference;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return resourceProvider.hashCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if ( obj instanceof WrappedResourceProvider ) {
+ return resourceProvider.equals(((WrappedResourceProvider) obj).resourceProvider);
+ } else if ( obj instanceof ResourceProvider) {
+ return resourceProvider.equals(obj);
+ }
+ return super.equals(obj);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return resourceProvider.toString();
+ }
+}
Added: sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResource.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResource.java?rev=1239587&view=auto
==============================================================================
--- sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResource.java (added)
+++ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResource.java Thu Feb 2 12:46:58 2012
@@ -0,0 +1,119 @@
+/*
+ * 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.resource.internal.helper.jcr;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Iterator;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+
+import org.apache.sling.api.resource.AbstractResource;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceMetadata;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.jcr.resource.JcrResourceConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+abstract class JcrItemResource extends AbstractResource implements Resource {
+
+ /**
+ * default log
+ */
+ private static final Logger LOGGER = LoggerFactory.getLogger(JcrItemResource.class);
+
+ private final ResourceResolver resourceResolver;
+
+ private final String path;
+
+ private final ResourceMetadata metadata;
+
+ protected JcrItemResource(ResourceResolver resourceResolver,
+ String path) {
+
+ this.resourceResolver = resourceResolver;
+ this.path = path;
+
+ metadata = new ResourceMetadata();
+ metadata.setResolutionPath(path);
+ }
+
+ public ResourceResolver getResourceResolver() {
+ return resourceResolver;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public ResourceMetadata getResourceMetadata() {
+ return metadata;
+ }
+
+ /**
+ * Compute the resource type of the given node, using either the
+ * SLING_RESOURCE_TYPE_PROPERTY, or the node's primary node type, if the
+ * property is not set
+ */
+ protected String getResourceTypeForNode(Node node)
+ throws RepositoryException {
+ String result = null;
+
+ if (node.hasProperty(JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY)) {
+ result = node.getProperty(JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY).getValue().getString();
+ }
+
+ if (result == null || result.length() == 0) {
+ result = node.getPrimaryNodeType().getName();
+ }
+
+ return result;
+ }
+
+ protected void setContentLength(final Property property) throws RepositoryException {
+ if (property.isMultiple()) {
+ return;
+ }
+
+ try {
+ final long length;
+ if (property.getType() == PropertyType.BINARY ) {
+ // we're interested in the number of bytes, not the
+ // number of characters
+ length = property.getLength();
+ } else {
+ length = property.getString().getBytes("UTF-8").length;
+ }
+ getResourceMetadata().setContentLength(length);
+ } catch (UnsupportedEncodingException uee) {
+ LOGGER.warn("getPropertyContentLength: Cannot determine length of non-binary property {}: {}",
+ toString(), uee);
+ }
+ }
+
+ /**
+ * Returns an iterator over the child resources or <code>null</code> if
+ * there are none.
+ */
+ abstract Iterator<Resource> listJcrChildren();
+
+}
Added: sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java?rev=1239587&view=auto
==============================================================================
--- sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java (added)
+++ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java Thu Feb 2 12:46:58 2012
@@ -0,0 +1,297 @@
+/*
+ * 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.resource.internal.helper.jcr;
+
+import static org.apache.jackrabbit.JcrConstants.JCR_CONTENT;
+import static org.apache.jackrabbit.JcrConstants.JCR_CREATED;
+import static org.apache.jackrabbit.JcrConstants.JCR_DATA;
+import static org.apache.jackrabbit.JcrConstants.JCR_ENCODING;
+import static org.apache.jackrabbit.JcrConstants.JCR_LASTMODIFIED;
+import static org.apache.jackrabbit.JcrConstants.JCR_MIMETYPE;
+import static org.apache.jackrabbit.JcrConstants.NT_FILE;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.security.AccessControlException;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.jcr.Item;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.ValueFormatException;
+
+import org.apache.jackrabbit.net.URLFactory;
+import org.apache.sling.adapter.annotations.Adaptable;
+import org.apache.sling.adapter.annotations.Adapter;
+import org.apache.sling.api.resource.PersistableValueMap;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceMetadata;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.jcr.resource.JcrModifiablePropertyMap;
+import org.apache.sling.jcr.resource.JcrPropertyMap;
+import org.apache.sling.jcr.resource.JcrResourceConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** A Resource that wraps a JCR Node */
+@Adaptable(adaptableClass=Resource.class, adapters={
+ @Adapter({Node.class, Map.class, Item.class, ValueMap.class, URL.class}),
+ @Adapter(value=PersistableValueMap.class, condition="If the resource is a JcrNodeResource and the user has set property privileges on the node."),
+ @Adapter(value=InputStream.class, condition="If the resource is a JcrNodeResource and has a jcr:data property or is an nt:file node.")
+})
+public class JcrNodeResource extends JcrItemResource {
+
+ /** marker value for the resourceSupertType before trying to evaluate */
+ private static final String UNSET_RESOURCE_SUPER_TYPE = "<unset>";
+
+ /** default log */
+ private static final Logger LOGGER = LoggerFactory.getLogger(JcrNodeResource.class);
+
+ private final Node node;
+
+ private final String resourceType;
+
+ protected String resourceSuperType;
+
+ private final ClassLoader dynamicClassLoader;
+
+ /**
+ * Constructor
+ * @param resourceResolver
+ * @param node
+ * @param dynamicClassLoader Dynamic class loader for loading serialized objects.
+ * @throws RepositoryException
+ */
+ public JcrNodeResource(final ResourceResolver resourceResolver,
+ final Node node,
+ final ClassLoader dynamicClassLoader)
+ throws RepositoryException {
+ super(resourceResolver, node.getPath());
+ this.dynamicClassLoader = dynamicClassLoader;
+ this.node = node;
+ resourceType = getResourceTypeForNode(node);
+ resourceSuperType = UNSET_RESOURCE_SUPER_TYPE;
+
+ // check for nt:file metadata
+ setMetaData(node, getResourceMetadata());
+ }
+
+ public String getResourceType() {
+ return resourceType;
+ }
+
+ public String getResourceSuperType() {
+ // Yes, this isn't how you're supposed to compare Strings, but this is intentional.
+ if ( resourceSuperType == UNSET_RESOURCE_SUPER_TYPE ) {
+ try {
+ if (node.hasProperty(JcrResourceConstants.SLING_RESOURCE_SUPER_TYPE_PROPERTY)) {
+ resourceSuperType = node.getProperty(JcrResourceConstants.SLING_RESOURCE_SUPER_TYPE_PROPERTY).getValue().getString();
+ }
+ } catch (RepositoryException re) {
+ // we ignore this
+ }
+ if ( resourceSuperType == UNSET_RESOURCE_SUPER_TYPE ) {
+ resourceSuperType = null;
+ }
+ }
+ return resourceSuperType;
+ }
+
+ @SuppressWarnings("unchecked")
+ public <Type> Type adaptTo(Class<Type> type) {
+ if (type == Node.class || type == Item.class) {
+ return (Type) getNode(); // unchecked cast
+ } else if (type == InputStream.class) {
+ return (Type) getInputStream(); // unchecked cast
+ } else if (type == URL.class) {
+ return (Type) getURL(); // unchecked cast
+ } else if (type == Map.class || type == ValueMap.class) {
+ return (Type) new JcrPropertyMap(getNode(), this.dynamicClassLoader); // unchecked cast
+ } else if (type == PersistableValueMap.class) {
+ // check write
+ try {
+ getNode().getSession().checkPermission(getNode().getPath(),
+ "set_property");
+ return (Type) new JcrModifiablePropertyMap(getNode(), this.dynamicClassLoader);
+ } catch (AccessControlException ace) {
+ // the user has no write permission, cannot adapt
+ LOGGER.debug(
+ "adaptTo(PersistableValueMap): Cannot set properties on {}",
+ this);
+ } catch (RepositoryException e) {
+ // some other problem, cannot adapt
+ LOGGER.debug(
+ "adaptTo(PersistableValueMap): Unexpected problem for {}",
+ this);
+ }
+ }
+
+ // fall back to default implementation
+ return super.adaptTo(type);
+ }
+
+ public String toString() {
+ return getClass().getSimpleName()
+ + ", type=" + getResourceType()
+ + ", superType=" + getResourceSuperType()
+ + ", path=" + getPath();
+ }
+
+ // ---------- internal -----------------------------------------------------
+
+ private Node getNode() {
+ return node;
+ }
+
+ /**
+ * Returns a stream to the <em>jcr:data</em> property if the
+ * {@link #getNode() node} is an <em>nt:file</em> or <em>nt:resource</em>
+ * node. Otherwise returns <code>null</code>. If a valid stream can be
+ * returned, this method also sets the content length resource metadata.
+ */
+ private InputStream getInputStream() {
+ // implement this for nt:file only
+ if (node != null) {
+ try {
+ // find the content node: for nt:file it is jcr:content
+ // otherwise it is the node of this resource
+ Node content = node.isNodeType(NT_FILE)
+ ? node.getNode(JCR_CONTENT)
+ : node;
+
+ Property data;
+
+ // if the node has a jcr:data property, use that property
+ if (content.hasProperty(JCR_DATA)) {
+ data = content.getProperty(JCR_DATA);
+ } else {
+ // otherwise try to follow default item trail
+ try {
+ Item item = content.getPrimaryItem();
+ while (item.isNode()) {
+ item = ((Node) item).getPrimaryItem();
+ }
+ data = ((Property) item);
+
+ // set the content length property as a side effect
+ // for resources which are not nt:file based and whose
+ // data is not in jcr:content/jcr:data this will lazily
+ // set the correct content length
+ this.setContentLength(data);
+
+ } catch (ItemNotFoundException infe) {
+ // we don't actually care, but log for completeness
+ LOGGER.debug("getInputStream: No primary items for {}", toString(), infe);
+ data = null;
+ }
+ }
+
+ if (data != null) {
+ return data.getStream();
+ }
+
+ } catch (RepositoryException re) {
+ LOGGER.error("getInputStream: Cannot get InputStream for " + this,
+ re);
+ }
+ }
+
+ // fallback to non-streamable resource
+ return null;
+ }
+
+ private URL getURL() {
+ try {
+ return URLFactory.createURL(node.getSession(), node.getPath());
+ } catch (Exception ex) {
+ LOGGER.error("getURL: Cannot create URL for " + this, ex);
+ }
+
+ return null;
+ }
+
+ // ---------- Descendable interface ----------------------------------------
+
+ @Override
+ Iterator<Resource> listJcrChildren() {
+ try {
+ if (getNode().hasNodes()) {
+ return new JcrNodeResourceIterator(getResourceResolver(),
+ getNode().getNodes(), this.dynamicClassLoader);
+ }
+ } catch (RepositoryException re) {
+ LOGGER.error("listChildren: Cannot get children of " + this, re);
+ }
+
+ return Collections.<Resource> emptyList().iterator();
+ }
+
+ private void setMetaData(Node node, ResourceMetadata metadata) {
+ try {
+
+ // check stuff for nt:file nodes
+ if (node.isNodeType(NT_FILE)) {
+ metadata.setCreationTime(node.getProperty(JCR_CREATED).getLong());
+
+ // continue our stuff with the jcr:content node
+ // which might be nt:resource, which we support below
+ node = node.getNode(JCR_CONTENT);
+ }
+
+ // check stuff for nt:resource (or similar) nodes
+ if (node.hasProperty(JCR_MIMETYPE)) {
+ metadata.setContentType(node.getProperty(JCR_MIMETYPE).getString());
+ }
+
+ if (node.hasProperty(JCR_ENCODING)) {
+ metadata.setCharacterEncoding(node.getProperty(JCR_ENCODING).getString());
+ }
+
+ if (node.hasProperty(JCR_LASTMODIFIED)) {
+ // We don't check node type, so JCR_LASTMODIFIED might not be a long
+ final Property prop = node.getProperty(JCR_LASTMODIFIED);
+ try {
+ metadata.setModificationTime(prop.getLong());
+ } catch(ValueFormatException vfe) {
+ LOGGER.debug("Property {} cannot be converted to a long, ignored ({})",
+ prop.getPath(), vfe);
+ }
+ }
+
+ if (node.hasProperty(JCR_DATA)) {
+ final Property prop = node.getProperty(JCR_DATA);
+ try {
+ metadata.setContentLength(prop.getLength());
+ } catch (ValueFormatException vfe) {
+ LOGGER.debug(
+ "Length of Property {} cannot be retrieved, ignored ({})",
+ prop.getPath(), vfe);
+ }
+ }
+ } catch (RepositoryException re) {
+ LOGGER.info(
+ "setMetaData: Problem extracting metadata information for "
+ + getPath(), re);
+ }
+ }
+
+}
Added: sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceIterator.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceIterator.java?rev=1239587&view=auto
==============================================================================
--- sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceIterator.java (added)
+++ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceIterator.java Thu Feb 2 12:46:58 2012
@@ -0,0 +1,106 @@
+/*
+ * 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.resource.internal.helper.jcr;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import javax.jcr.NodeIterator;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The <code>JcrNodeResourceIterator</code> class is a resource iterator,
+ * which returns resources for each node of an underlying
+ * <code>NodeIterator</code>. Nodes in the node iterator which cannot be
+ * accessed or for which a resource cannot be created are skipped.
+ */
+public class JcrNodeResourceIterator implements Iterator<Resource> {
+
+ /** default log */
+ private static final Logger LOGGER = LoggerFactory.getLogger(JcrNodeResourceIterator.class);
+
+ /** resource resolver used to create resources from nodes */
+ private ResourceResolver resourceResolver;
+
+ /** underlying node iterator to be used for resources */
+ private NodeIterator nodes;
+
+ /** The prefetched next iterator entry, null at the end of iterating */
+ private Resource nextResult;
+
+ private final ClassLoader dynamicClassLoader;
+
+ /**
+ * Creates an instance using the given resource manager and the nodes
+ * provided as a node iterator.
+ */
+ public JcrNodeResourceIterator(final ResourceResolver resourceResolver,
+ final NodeIterator nodes,
+ final ClassLoader dynamicClassLoader) {
+ this.resourceResolver = resourceResolver;
+ this.nodes = nodes;
+ this.nextResult = seek();
+ this.dynamicClassLoader = dynamicClassLoader;
+ }
+
+ public boolean hasNext() {
+ return nextResult != null;
+ }
+
+ public Resource next() {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+
+ Resource result = nextResult;
+ nextResult = seek();
+ return result;
+ }
+
+ /**
+ * Throws <code>UnsupportedOperationException</code> as this method is not
+ * supported by this implementation.
+ */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ private Resource seek() {
+ while (nodes.hasNext()) {
+ try {
+ Resource resource = new JcrNodeResource(resourceResolver,
+ nodes.nextNode(), dynamicClassLoader);
+ LOGGER.debug("seek: Returning Resource {}", resource);
+ return resource;
+ } catch (Throwable t) {
+ LOGGER.error(
+ "seek: Problem creating Resource for next node, skipping",
+ t);
+ }
+ }
+
+ // no more results
+ LOGGER.debug("seek: No more nodes, iterator exhausted");
+ return null;
+ }
+}
Added: sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResource.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResource.java?rev=1239587&view=auto
==============================================================================
--- sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResource.java (added)
+++ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResource.java Thu Feb 2 12:46:58 2012
@@ -0,0 +1,223 @@
+/*
+ * 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.resource.internal.helper.jcr;
+
+import java.io.InputStream;
+import java.util.Calendar;
+import java.util.Iterator;
+
+import javax.jcr.Item;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFormatException;
+
+import org.apache.sling.adapter.annotations.Adaptable;
+import org.apache.sling.adapter.annotations.Adapter;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Adaptable(adaptableClass = Resource.class, adapters = {
+ @Adapter(value = { Item.class, Property.class, Value.class, String.class, Boolean.class, Long.class,
+ Double.class, Calendar.class, InputStream.class, Value[].class, String[].class,
+ Boolean[].class, Long[].class, Double[].class }),
+ @Adapter(value = Node.class, condition = "If the resource is a JcrPropertyResource and the property is a reference or weak reference property.") })
+public class JcrPropertyResource extends JcrItemResource {
+
+ /** default log */
+ private static final Logger LOGGER = LoggerFactory.getLogger(JcrPropertyResource.class);
+
+ private final Property property;
+
+ private final String resourceType;
+
+ public JcrPropertyResource(ResourceResolver resourceResolver,
+ String path,
+ Property property)
+ throws RepositoryException {
+ super(resourceResolver, path);
+ this.property = property;
+ this.resourceType = getResourceTypeForNode(property.getParent())
+ + "/" + property.getName();
+ if (PropertyType.BINARY != this.property.getType()) {
+ this.getResourceMetadata().setContentType("text/plain");
+ this.getResourceMetadata().setCharacterEncoding("UTF-8");
+ }
+
+ this.setContentLength(property);
+ }
+
+ public JcrPropertyResource(ResourceResolver resourceResolver,
+ Property property)
+ throws RepositoryException {
+ this(resourceResolver, property.getPath(), property);
+ }
+
+ public String getResourceType() {
+ return resourceType;
+ }
+
+ public String getResourceSuperType() {
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
+
+ // the property itself
+ if (type == Property.class || type == Item.class) {
+ return (AdapterType) getProperty();
+ }
+
+ // the property value
+ try {
+ if (type == String.class) {
+ return (AdapterType) getProperty().getString();
+
+ } else if (type == Boolean.class) {
+ return (AdapterType) Boolean.valueOf(getProperty().getBoolean());
+
+ } else if (type == Long.class) {
+ return (AdapterType) Long.valueOf(getProperty().getLong());
+
+ } else if (type == Double.class) {
+ return (AdapterType) new Double(getProperty().getDouble());
+
+ } else if (type == Calendar.class) {
+ return (AdapterType) getProperty().getDate();
+
+ } else if (type == Value.class) {
+ return (AdapterType) getProperty().getValue();
+
+ } else if (type == Node.class
+ && (getProperty().getType() == PropertyType.REFERENCE ||
+ getProperty().getType() == PropertyType.WEAKREFERENCE)) {
+ return (AdapterType) getProperty().getNode();
+
+ } else if (type == InputStream.class) {
+ return (AdapterType) getInputStream();
+
+ } else if ( type == String[].class ) {
+ if ( getProperty().getDefinition().isMultiple() ) {
+ final Value[] values = getProperty().getValues();
+ final String[] result = new String[values.length];
+ for(int i=0; i<values.length; i++) {
+ result[i] = values[i].getString();
+ }
+ return (AdapterType)result;
+ }
+ return (AdapterType)new String[] {getProperty().getString()};
+
+ } else if (type == Boolean[].class) {
+ if ( getProperty().getDefinition().isMultiple() ) {
+ final Value[] values = getProperty().getValues();
+ final Boolean[] result = new Boolean[values.length];
+ for(int i=0; i<values.length; i++) {
+ result[i] = values[i].getBoolean();
+ }
+ return (AdapterType)result;
+ }
+ return (AdapterType)new Boolean[] {getProperty().getBoolean()};
+
+ } else if (type == Long[].class) {
+ if ( getProperty().getDefinition().isMultiple() ) {
+ final Value[] values = getProperty().getValues();
+ final Long[] result = new Long[values.length];
+ for(int i=0; i<values.length; i++) {
+ result[i] = values[i].getLong();
+ }
+ return (AdapterType)result;
+ }
+ return (AdapterType)new Long[] {getProperty().getLong()};
+
+ } else if (type == Double[].class) {
+ if ( getProperty().getDefinition().isMultiple() ) {
+ final Value[] values = getProperty().getValues();
+ final Double[] result = new Double[values.length];
+ for(int i=0; i<values.length; i++) {
+ result[i] = values[i].getDouble();
+ }
+ return (AdapterType)result;
+ }
+ return (AdapterType)new Double[] {getProperty().getDouble()};
+
+ } else if (type == Calendar[].class) {
+ if ( getProperty().getDefinition().isMultiple() ) {
+ final Value[] values = getProperty().getValues();
+ final Calendar[] result = new Calendar[values.length];
+ for(int i=0; i<values.length; i++) {
+ result[i] = values[i].getDate();
+ }
+ return (AdapterType)result;
+ }
+ return (AdapterType)new Calendar[] {getProperty().getDate()};
+
+ } else if (type == Value[].class) {
+ if ( getProperty().getDefinition().isMultiple() ) {
+ return (AdapterType)getProperty().getValues();
+ }
+ return (AdapterType)new Value[] {getProperty().getValue()};
+
+ }
+
+ } catch (ValueFormatException vfe) {
+ LOGGER.debug("adaptTo: Problem accessing the property value of {}: {}",
+ getPath(), vfe.getMessage());
+ LOGGER.debug("adaptTo: Cause", vfe);
+
+ } catch (RepositoryException re) {
+ LOGGER.debug("adaptTo: Problem accessing the property " + getPath(), re);
+ }
+
+ // try to use adapter factories
+ return super.adaptTo(type);
+ }
+
+ public String toString() {
+ return getClass().getSimpleName() + ", type=" + getResourceType()
+ + ", path=" + getPath();
+ }
+
+ private Property getProperty() {
+ return property;
+ }
+
+ private InputStream getInputStream() {
+ Property prop = getProperty();
+
+ try {
+ return prop.getStream();
+ } catch (RepositoryException re) {
+ LOGGER.error("getInputStream: Problem accessing the property "
+ + getPath() + " stream", re);
+ }
+
+ // fall back to none in case of an error
+ return null;
+ }
+
+ @Override
+ Iterator<Resource> listJcrChildren() {
+ return null;
+ }
+}
Added: sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProvider.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProvider.java?rev=1239587&view=auto
==============================================================================
--- sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProvider.java (added)
+++ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProvider.java Thu Feb 2 12:46:58 2012
@@ -0,0 +1,190 @@
+/*
+ * 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.resource.internal.helper.jcr;
+
+import java.util.Iterator;
+
+import javax.jcr.Item;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.sling.api.SlingException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceProvider;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceWrapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The <code>JcrResourceProvider</code> is the main resource provider of this
+ * bundle providing access to JCR resources. This resoure provider is created
+ * for each <code>JcrResourceResolver</code> instance and is bound to the JCR
+ * session for a single request.
+ */
+public class JcrResourceProvider implements ResourceProvider {
+
+ /** default log */
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private final Session session;
+ private final ClassLoader dynamicClassLoader;
+ private final boolean useMultiWorkspaces;
+
+ public JcrResourceProvider(final Session session,
+ final ClassLoader dynamicClassLoader,
+ boolean useMultiWorkspaces) {
+ this.session = session;
+ this.dynamicClassLoader = dynamicClassLoader;
+ this.useMultiWorkspaces = useMultiWorkspaces;
+ }
+
+ // ---------- ResourceProvider interface ----------------------------------
+
+ public String[] getRoots() {
+ return new String[] { "/" };
+ }
+
+ public Resource getResource(ResourceResolver resourceResolver,
+ HttpServletRequest request, String path) throws SlingException {
+ return getResource(resourceResolver, path);
+ }
+
+ public Resource getResource(ResourceResolver resourceResolver, String path)
+ throws SlingException {
+
+ try {
+ return createResource(resourceResolver, path);
+ } catch (RepositoryException re) {
+ throw new SlingException("Problem retrieving node based resource "
+ + path, re);
+ }
+
+ }
+
+ public Iterator<Resource> listChildren(Resource parent) {
+
+ JcrItemResource parentItemResource;
+
+ // short cut for known JCR resources
+ if (parent instanceof JcrItemResource) {
+
+ parentItemResource = (JcrItemResource) parent;
+
+ } else if (parent instanceof ResourceWrapper) {
+
+ return listChildren(((ResourceWrapper) parent).getResource());
+
+ } else {
+
+ // try to get the JcrItemResource for the parent path to list
+ // children
+ try {
+ parentItemResource = createResource(
+ parent.getResourceResolver(), parent.getPath());
+ } catch (RepositoryException re) {
+ parentItemResource = null;
+ }
+
+ }
+
+ // return children if there is a parent item resource, else null
+ return (parentItemResource != null)
+ ? parentItemResource.listJcrChildren()
+ : null;
+ }
+
+ public Session getSession() {
+ return session;
+ }
+
+ // ---------- implementation helper ----------------------------------------
+
+ /**
+ * Creates a <code>Resource</code> instance for the item found at the
+ * given path. If no item exists at that path or the item does not have
+ * read-access for the session of this resolver, <code>null</code> is
+ * returned.
+ *
+ * @param path The absolute path
+ * @return The <code>Resource</code> for the item at the given path.
+ * @throws RepositoryException If an error occurrs accessingor checking the
+ * item in the repository.
+ */
+ private JcrItemResource createResource(ResourceResolver resourceResolver,
+ String path) throws RepositoryException {
+ if (useMultiWorkspaces) {
+ final int wsSepPos = path.indexOf(":/");
+ if (wsSepPos != -1) {
+ final String workspaceName = path.substring(0, wsSepPos);
+ final String expectedWorkspaceName = getSession().getWorkspace().getName();
+ if (workspaceName.equals(expectedWorkspaceName)) {
+ path = path.substring(wsSepPos + 1);
+ } else {
+ throw new RepositoryException("Unexpected workspace name. Expected " +
+ expectedWorkspaceName + ". Actual " + workspaceName);
+ }
+ }
+ }
+
+ if (itemExists(path)) {
+ Item item = getSession().getItem(path);
+ if (item.isNode()) {
+ log.debug(
+ "createResource: Found JCR Node Resource at path '{}'",
+ path);
+ return new JcrNodeResource(resourceResolver, (Node) item, dynamicClassLoader);
+ }
+
+ log.debug(
+ "createResource: Found JCR Property Resource at path '{}'",
+ path);
+ return new JcrPropertyResource(resourceResolver, path,
+ (Property) item);
+ }
+
+ log.debug("createResource: No JCR Item exists at path '{}'", path);
+ return null;
+ }
+
+ /**
+ * Checks whether the item exists and this content manager's session has
+ * read access to the item. If the item does not exist, access control is
+ * ignored by this method and <code>false</code> is returned.
+ *
+ * @param path The path to the item to check
+ * @return <code>true</code> if the item exists and this content manager's
+ * session has read access. If the item does not exist,
+ * <code>false</code> is returned ignoring access control.
+ */
+ public boolean itemExists(String path) {
+
+ try {
+ return getSession().itemExists(path);
+ } catch (RepositoryException re) {
+ log.debug("itemExists: Error checking for existence of {}: {}",
+ path, re.toString());
+ return false;
+ }
+
+ }
+}
Added: sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderEntry.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderEntry.java?rev=1239587&view=auto
==============================================================================
--- sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderEntry.java (added)
+++ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderEntry.java Thu Feb 2 12:46:58 2012
@@ -0,0 +1,152 @@
+/*
+ * 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.resource.internal.helper.jcr;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.jcr.Session;
+
+import org.apache.sling.api.resource.ResourceProvider;
+import org.apache.sling.jcr.resource.internal.helper.ResourceProviderEntry;
+
+public class JcrResourceProviderEntry extends ResourceProviderEntry {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 5672648586247261128L;
+
+ private final ResourceProviderEntry delegatee;
+
+ private final Session session;
+
+ public JcrResourceProviderEntry(Session session,
+ ResourceProviderEntry delegatee,
+ final ClassLoader dynamicClassLoader,
+ boolean useMultiWorkspaces) {
+ super("/", new ResourceProvider[] { new JcrResourceProvider(session,
+ dynamicClassLoader, useMultiWorkspaces) });
+
+ this.delegatee = delegatee;
+ this.session = session;
+ }
+
+ public Session getSession() {
+ return session;
+ }
+
+ @Override
+ public boolean addResourceProvider(String prefix, ResourceProvider provider, Comparable<?> comparable) {
+ return delegatee.addResourceProvider(prefix, provider, comparable);
+ }
+
+ @Override
+ public boolean removeResourceProvider(String prefix,
+ ResourceProvider provider, Comparable<?> comparable) {
+ return delegatee.removeResourceProvider(prefix, provider, comparable);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.sling.jcr.resource.internal.helper.ResourceProviderEntry2#put(java.lang.String,
+ * org.apache.sling.jcr.resource.internal.helper.ResourceProviderEntry2)
+ */
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.sling.jcr.resource.internal.helper.ResourceProviderEntry#get(java.lang.String)
+ */
+ @Override
+ public ResourceProviderEntry get(String key) {
+ ResourceProviderEntry rpe = super.get(key);
+ if (rpe == null) {
+ rpe = delegatee.get(key);
+ }
+ return rpe;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.sling.jcr.resource.internal.helper.ResourceProviderEntry#values()
+ */
+ @Override
+ public Collection<ResourceProviderEntry> values() {
+ List<ResourceProviderEntry> list = new ArrayList<ResourceProviderEntry>(
+ super.values());
+ list.addAll(delegatee.values());
+ return list;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.sling.jcr.resource.internal.helper.ResourceProviderEntry#containsKey(java.lang.String)
+ */
+ @Override
+ public boolean containsKey(String key) {
+ return (super.containsKey(key) || delegatee.containsKey(key));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.sling.jcr.resource.internal.helper.ResourceProviderEntry#getResourceProviders()
+ */
+ @Override
+ public ResourceProvider[] getResourceProviders() {
+ // merge the delegatee and this set of providers,
+ // its probably better to do this every time, as
+
+ ResourceProvider[] delegateeProviders = delegatee
+ .getResourceProviders();
+ ResourceProvider[] superProviders = super.getResourceProviders();
+ if (delegateeProviders == null && superProviders == null) {
+ return null;
+ }
+ if (delegateeProviders == null) {
+ delegateeProviders = new ResourceProvider[0];
+ }
+ if (superProviders == null) {
+ superProviders = new ResourceProvider[0];
+ }
+ ResourceProvider[] resourceProviders = new ResourceProvider[delegateeProviders.length
+ + superProviders.length];
+ System.arraycopy(delegateeProviders, 0, resourceProviders, 0,
+ delegateeProviders.length);
+ System.arraycopy(superProviders, 0, resourceProviders,
+ delegateeProviders.length, superProviders.length);
+ return resourceProviders;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.sling.jcr.resource.internal.helper.ResourceProviderEntry#toString()
+ */
+ @Override
+ public String toString() {
+ return delegatee.toString();
+ }
+
+}
Added: sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/starresource/StarResource.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/starresource/StarResource.java?rev=1239587&view=auto
==============================================================================
--- sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/starresource/StarResource.java (added)
+++ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/starresource/StarResource.java Thu Feb 2 12:46:58 2012
@@ -0,0 +1,109 @@
+/*
+ * 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.resource.internal.helper.starresource;
+
+import java.util.Map;
+
+import org.apache.sling.adapter.annotations.Adaptable;
+import org.apache.sling.adapter.annotations.Adapter;
+import org.apache.sling.api.SlingException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceMetadata;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.api.resource.SyntheticResource;
+import org.apache.sling.api.resource.ValueMap;
+
+/** Used to provide the equivalent of an empty Node for GET requests
+ * to *.something (SLING-344)
+ */
+@Adaptable(adaptableClass = Resource.class, adapters = @Adapter(value = { String.class }))
+public class StarResource extends SyntheticResource {
+
+ final static String SLASH_STAR = "/*";
+ public final static String DEFAULT_RESOURCE_TYPE = "sling:syntheticStarResource";
+
+ private static final String UNSET_RESOURCE_SUPER_TYPE = "<unset>";
+
+ private String resourceSuperType;
+
+ @SuppressWarnings("serial")
+ static class SyntheticStarResourceException extends SlingException {
+ SyntheticStarResourceException(String reason, Throwable cause) {
+ super(reason, cause);
+ }
+ }
+
+ /** True if a StarResource should be used for the given request, if
+ * a real Resource was not found */
+ public static boolean appliesTo(String path) {
+ return path.contains(SLASH_STAR) || path.endsWith(SLASH_STAR);
+ }
+
+ /**
+ * Returns true if the path of the resource ends with the
+ * {@link #SLASH_STAR} and therefore should be considered a star
+ * resource.
+ */
+ public static boolean isStarResource(Resource res) {
+ return res.getPath().endsWith(SLASH_STAR);
+ }
+
+ public StarResource(ResourceResolver resourceResolver, String path) {
+ super(resourceResolver, getResourceMetadata(path), DEFAULT_RESOURCE_TYPE);
+ resourceSuperType = UNSET_RESOURCE_SUPER_TYPE;
+ }
+
+ /**
+ * Calls {@link ResourceUtil#getResourceSuperType(ResourceResolver, String)} method
+ * to dynamically resolve the resource super type of this star resource.
+ */
+ public String getResourceSuperType() {
+ // Yes, this isn't how you're supposed to compare Strings, but this is intentional.
+ if (resourceSuperType == UNSET_RESOURCE_SUPER_TYPE) {
+ resourceSuperType = ResourceUtil.getResourceSuperType(this.getResourceResolver(),
+ this.getResourceType());
+ }
+ return resourceSuperType;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <Type> Type adaptTo(Class<Type> type) {
+ if ( type == String.class ) {
+ return (Type)"";
+ }
+ return super.adaptTo(type);
+ }
+
+ /** Get our ResourceMetadata for given path */
+ static ResourceMetadata getResourceMetadata(String path) {
+ ResourceMetadata result = new ResourceMetadata();
+
+ // The path is up to /*, what follows is pathInfo
+ final int index = path.indexOf(SLASH_STAR);
+ if(index >= 0) {
+ result.setResolutionPath(path.substring(0, index) + SLASH_STAR);
+ result.setResolutionPathInfo(path.substring(index + SLASH_STAR.length()));
+ } else {
+ result.setResolutionPath(path);
+ }
+ return result;
+ }
+}
\ No newline at end of file
Added: sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/scripting/JcrObjectsBindingsValuesProvider.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/scripting/JcrObjectsBindingsValuesProvider.java?rev=1239587&view=auto
==============================================================================
--- sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/scripting/JcrObjectsBindingsValuesProvider.java (added)
+++ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/scripting/JcrObjectsBindingsValuesProvider.java Thu Feb 2 12:46:58 2012
@@ -0,0 +1,64 @@
+/*
+ * 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.resource.internal.scripting;
+
+import javax.jcr.Node;
+import javax.jcr.Session;
+import javax.script.Bindings;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.scripting.api.BindingsValuesProvider;
+import org.osgi.framework.Constants;
+
+/**
+ * BindingsValuesProvider for currentNode and currentSession object.
+ */
+@Component
+@Service
+@Properties({
+ @Property(name=Constants.SERVICE_DESCRIPTION, value="Apache Sling CurrentNode BindingsValuesProvider"),
+ @Property(name=Constants.SERVICE_VENDOR, value="The Apache Software Foundation")
+})
+public class JcrObjectsBindingsValuesProvider implements BindingsValuesProvider {
+
+
+ private static final String PROP_CURRENT_NODE = "currentNode";
+ private static final String PROP_CURRENT_SESSION = "currentSession";
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addBindings(Bindings bindings) {
+ Resource resource = (Resource) bindings.get("resource");
+ if (resource != null) {
+ Node node = resource.adaptTo(Node.class);
+ if (node != null) {
+ bindings.put(PROP_CURRENT_NODE, node);
+ }
+ if ( bindings.get(PROP_CURRENT_SESSION) == null ) {
+ final Session session = resource.getResourceResolver().adaptTo(Session.class);
+ if ( session != null ) {
+ bindings.put(PROP_CURRENT_SESSION, session);
+ }
+ }
+ }
+ }
+}
Added: sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/OSGI-INF/metatype/metatype.properties
URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/OSGI-INF/metatype/metatype.properties?rev=1239587&view=auto
==============================================================================
--- sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/OSGI-INF/metatype/metatype.properties (added)
+++ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/OSGI-INF/metatype/metatype.properties Thu Feb 2 12:46:58 2012
@@ -0,0 +1,78 @@
+#
+# 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.
+#
+
+
+#
+# This file contains localization strings for configuration labels and
+# descriptions as used in the metatype.xml descriptor generated by the
+# the SCR plugin
+
+#
+# Localizations for JcrResourceResolverFactoryImpl configuration
+resource.resolver.name = Apache Sling JCR Resource Resolver
+resource.resolver.description = Configures the JCR Resource Resolver for request \
+ URL and resource path rewriting.
+
+resource.resolver.map.location.name = Mapping Location
+resource.resolver.map.location.description = The path to the root of the \
+ configuration to setup and configure the ResourceResolver mapping. The \
+ default value is /etc/map.
+
+resource.resolver.allowDirect.name = Allow Direct Mapping
+resource.resolver.allowDirect.description = Whether to add a direct URL \
+ mapping to the front of the mapping list.
+
+resource.resolver.virtual.name = Virtual URLs
+resource.resolver.virtual.description = List of virtual URLs and there \
+ mappings to real URLs. Format is <externalURL>:<internalURL>. Mappings are \
+ applied on the complete request URL only.
+
+resource.resolver.mapping.name = URL Mappings
+resource.resolver.mapping.description = List of mappings to apply to URLs. \
+ Incoming mappings are applied to request URLs to map to Content paths, \
+ outgoing mappings are applied to map Content paths to URLs used on subsequent \
+ requests. Form ist <externalURLPrefix><op><internalURLPrefix> where <op> is \
+ ">" for incoming mappings, "<" for outgoing mappings and ":" for mappings \
+ applied in both directions. Mappings are applied in configuration order by \
+ comparing and replacing URL prefixes. Note: The use of "-" as the <op> value \
+ indicating a mapping in both directions is deprecated.
+
+resource.resolver.searchpath.name = Resource Search Path
+resource.resolver.searchpath.description = The list of absolute path prefixes \
+ applied to find resources whose path is just specified with a relative path. \
+ The default value is [ "/apps", "/libs" ]. If an empty path is specified a \
+ single entry path of [ "/" ] is assumed.
+
+resource.resolver.manglenamespaces.name = Namespace Mangling
+resource.resolver.manglenamespaces.description = Defines whether namespace \
+ prefixes of resource names inside the path (e.g. "jcr:" in "/home/path/jcr:content") \
+ are mangled or not. Mangling means that any namespace prefix contained in the \
+ path is replaced as per the generic substitution pattern "/([^:]+):/_$1_/" \
+ when calling the "map" method of the resource resolver. Likewise the \
+ "resolve" methods will unmangle such namespace prefixes according to the \
+ substituation pattern "/_([^_]+)_/$1:/". This feature is provided since \
+ there may be systems out there in the wild which cannot cope with URLs \
+ containing colons, even though they are perfectly valid characters in the \
+ path part of URI references with a scheme. The default value of this property \
+ if no configuration is provided is "true".
+
+resource.resolver.multiworkspace.name=Enable Multi Workspaces
+resource.resolver.multiworkspace.description=If this is enabled, multiple workspaces are supported \
+ This includes registering observation listeners for all workspaces and allows to \
+ resolve resources from other workspaces than the default one.
Added: sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/folder.cnd
URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/folder.cnd?rev=1239587&view=auto
==============================================================================
--- sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/folder.cnd (added)
+++ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/folder.cnd Thu Feb 2 12:46:58 2012
@@ -0,0 +1,46 @@
+//
+// 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.
+//
+
+<sling = 'http://sling.apache.org/jcr/sling/1.0'>
+
+//-----------------------------------------------------------------------------
+// Node type to be used as a replacement for nt:folder: it can be used
+// as a child of nt:folder and allows to add unstructured content
+// (See SLING-663)
+[sling:Folder] > nt:folder
+ - * (undefined) multiple
+ - * (undefined)
+ + * (nt:base) = sling:Folder version
+
+
+//-----------------------------------------------------------------------------
+// Mixin node type to turn any node into an nt:hierarchyNode to place
+// below any nt:folder (or extension thereof such as sling:Folder)
+// (See SLING-663)
+[sling:HierarchyNode] > nt:hierarchyNode
+ mixin
+
+
+//-----------------------------------------------------------------------------
+// Node type extending sling:Folder supporting the creation of folder
+// structured with child node ordering.
+// (See SLING-663)
+[sling:OrderedFolder] > sling:Folder
+ orderable
+ + * (nt:base) = sling:OrderedFolder version
Added: sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/mapping.cnd
URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/mapping.cnd?rev=1239587&view=auto
==============================================================================
--- sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/mapping.cnd (added)
+++ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/mapping.cnd Thu Feb 2 12:46:58 2012
@@ -0,0 +1,70 @@
+//
+// 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.
+//
+
+// for more details on this resource type refer to
+// http://cwiki.apache.org/SLING/flexible-resource-resolution.html
+
+<sling = 'http://sling.apache.org/jcr/sling/1.0'>
+
+//-----------------------------------------------------------------------------
+// Mixin node type to enable setting an alias on a resource
+[sling:ResourceAlias]
+ mixin
+
+ // alias name(s) for the node (single or multi-value)
+ - sling:alias (string)
+ - sling:alias (string) multiple
+
+
+//-----------------------------------------------------------------------------
+// Mixin node type to allow building the /etc/map configuration
+[sling:MappingSpec]
+ mixin
+
+ // optional regular expression used to match the request. If
+ // this property is not set, the node's name is used for matching
+ // this regular expression should only be used to match a single
+ // segment, thus it should not contain any slashes
+ - sling:match (string)
+
+ // Location header value for response
+ - sling:redirect (string)
+
+ // status code for redirect, defaults to 302 if not defined
+ - sling:status (long)
+
+ // internal redirect for further processing
+ - sling:internalRedirect (string)
+ - sling:internalRedirect (string) multiple
+
+
+//-----------------------------------------------------------------------------
+// Primary node type to allow building the /etc/map configuration
+// * sling:MappingSpec -> define properties for redirects
+// * sling:Resource -> allow setting the resource type
+// * nt:hierarchyNode -> allow placing below nt:folder
+[sling:Mapping] > sling:MappingSpec, sling:Resource, nt:hierarchyNode
+
+ // child node order is significant in the resolution process
+ // so allow for custom child node ordering
+ orderable
+
+ // allow any child node, but prefer sling:Mapping nodes
+ + * (nt:base) = sling:Mapping version
+
\ No newline at end of file
Added: sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/redirect.cnd
URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/redirect.cnd?rev=1239587&view=auto
==============================================================================
--- sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/redirect.cnd (added)
+++ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/redirect.cnd Thu Feb 2 12:46:58 2012
@@ -0,0 +1,26 @@
+//
+// 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.
+//
+
+<sling = 'http://sling.apache.org/jcr/sling/1.0'>
+
+//-----------------------------------------------------------------------------
+// Mixin node type for Sling Redirect nodes
+[sling:Redirect] > sling:Resource
+ mixin
+ - sling:target (Undefined)
Added: sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/resource.cnd
URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/resource.cnd?rev=1239587&view=auto
==============================================================================
--- sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/resource.cnd (added)
+++ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/resource.cnd Thu Feb 2 12:46:58 2012
@@ -0,0 +1,33 @@
+//
+// 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.
+//
+
+<sling = 'http://sling.apache.org/jcr/sling/1.0'>
+
+//-----------------------------------------------------------------------------
+// Mixin node type for Sling Resource nodes
+[sling:Resource]
+ mixin
+ - sling:resourceType (string)
+
+
+//-----------------------------------------------------------------------------
+// Mixin node type for nodes providing resource super type information
+[sling:ResourceSuperType]
+ mixin
+ - sling:resourceSuperType (string)
Added: sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/vanitypath.cnd
URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/vanitypath.cnd?rev=1239587&view=auto
==============================================================================
--- sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/vanitypath.cnd (added)
+++ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/vanitypath.cnd Thu Feb 2 12:46:58 2012
@@ -0,0 +1,29 @@
+//
+// 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.
+//
+
+<sling = 'http://sling.apache.org/jcr/sling/1.0'>
+
+//-----------------------------------------------------------------------------
+// Mixin node type for defining vanity resource path.
+[sling:VanityPath]
+ mixin
+ - sling:vanityPath (string) multiple
+ - sling:redirect (boolean)
+ - sling:vanityOrder (long)
+ - sling:redirectStatus (long)
Added: sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrModifiablePropertyMapTest.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrModifiablePropertyMapTest.java?rev=1239587&view=auto
==============================================================================
--- sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrModifiablePropertyMapTest.java (added)
+++ sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrModifiablePropertyMapTest.java Thu Feb 2 12:46:58 2012
@@ -0,0 +1,213 @@
+/*
+ * 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.resource.internal;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.NodeType;
+
+import org.apache.sling.api.resource.PersistableValueMap;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.jcr.resource.JcrModifiablePropertyMap;
+import org.apache.sling.jcr.resource.JcrPropertyMap;
+import org.apache.sling.jcr.resource.JcrResourceUtil;
+
+public class JcrModifiablePropertyMapTest extends JcrPropertyMapTest {
+
+ private String rootPath;
+
+ private Node rootNode;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ rootPath = "/test_" + System.currentTimeMillis();
+ rootNode = getSession().getRootNode().addNode(rootPath.substring(1),
+ "nt:unstructured");
+
+ final Map<String, Object> values = this.initialSet();
+ for(Map.Entry<String, Object> entry : values.entrySet()) {
+ JcrResourceUtil.setProperty(rootNode, entry.getKey().toString(), entry.getValue());
+ }
+ session.save();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (rootNode != null) {
+ rootNode.remove();
+ session.save();
+ }
+
+ super.tearDown();
+ }
+
+ private Map<String, Object> initialSet() {
+ final Map<String, Object> values = new HashMap<String, Object>();
+ values.put("string", "test");
+ values.put("long", 1L);
+ values.put("bool", Boolean.TRUE);
+ return values;
+ }
+
+ public void testPut()
+ throws IOException {
+ final PersistableValueMap pvm = new JcrModifiablePropertyMap(this.rootNode);
+ assertContains(pvm, initialSet());
+ assertNull(pvm.get("something"));
+
+ // now put two values and check set again
+ pvm.put("something", "Another value");
+ pvm.put("string", "overwrite");
+
+ final Map<String, Object> currentlyStored = this.initialSet();
+ currentlyStored.put("something", "Another value");
+ currentlyStored.put("string", "overwrite");
+ assertContains(pvm, currentlyStored);
+
+ pvm.save();
+ assertContains(pvm, currentlyStored);
+
+ final PersistableValueMap pvm2 = new JcrModifiablePropertyMap(this.rootNode);
+ assertContains(pvm2, currentlyStored);
+ }
+
+ public void testReset()
+ throws IOException {
+ final PersistableValueMap pvm = new JcrModifiablePropertyMap(this.rootNode);
+ assertContains(pvm, initialSet());
+ assertNull(pvm.get("something"));
+
+ // now put two values and check set again
+ pvm.put("something", "Another value");
+ pvm.put("string", "overwrite");
+
+ final Map<String, Object> currentlyStored = this.initialSet();
+ currentlyStored.put("something", "Another value");
+ currentlyStored.put("string", "overwrite");
+ assertContains(pvm, currentlyStored);
+
+ pvm.reset();
+ assertContains(pvm, initialSet());
+
+ final PersistableValueMap pvm2 = new JcrModifiablePropertyMap(this.rootNode);
+ assertContains(pvm2, initialSet());
+ }
+
+ public void testSerializable()
+ throws IOException {
+ final PersistableValueMap pvm = new JcrModifiablePropertyMap(this.rootNode);
+ assertContains(pvm, initialSet());
+ assertNull(pvm.get("something"));
+
+ // now put a serializable object
+ final List<String> strings = new ArrayList<String>();
+ strings.add("a");
+ strings.add("b");
+ pvm.put("something", strings);
+
+ // check if we get the list again
+ @SuppressWarnings("unchecked")
+ final List<String> strings2 = (List<String>) pvm.get("something");
+ assertEquals(strings, strings2);
+
+ pvm.save();
+
+ final PersistableValueMap pvm2 = new JcrModifiablePropertyMap(this.rootNode);
+ // check if we get the list again
+ @SuppressWarnings("unchecked")
+ final List<String> strings3 = (List<String>) pvm2.get("something", Serializable.class);
+ assertEquals(strings, strings3);
+
+ }
+
+ public void testExceptions() {
+ final PersistableValueMap pvm = new JcrModifiablePropertyMap(this.rootNode);
+ try {
+ pvm.put(null, "something");
+ fail("Put with null key");
+ } catch (NullPointerException iae) {}
+ try {
+ pvm.put("something", null);
+ fail("Put with null value");
+ } catch (NullPointerException iae) {}
+ try {
+ pvm.put("something", pvm);
+ fail("Put with non serializable");
+ } catch (IllegalArgumentException iae) {}
+ }
+
+ private Set<String> getMixinNodeTypes(final Node node) throws RepositoryException {
+ final Set<String> mixinTypes = new HashSet<String>();
+ for(final NodeType mixinNodeType : node.getMixinNodeTypes() ) {
+ mixinTypes.add(mixinNodeType.getName());
+ }
+ return mixinTypes;
+ }
+
+ public void testMixins() throws Exception {
+ final Node testNode = this.rootNode.addNode("testMixins" + System.currentTimeMillis());
+ testNode.getSession().save();
+ final PersistableValueMap pvm = new JcrModifiablePropertyMap(testNode);
+
+ final String[] types = pvm.get("jcr:mixinTypes", String[].class);
+ final Set<String> exNodeTypes = getMixinNodeTypes(testNode);
+
+ assertEquals(exNodeTypes.size(), (types == null ? 0 : types.length));
+ if ( types != null ) {
+ for(final String name : types) {
+ assertTrue(exNodeTypes.contains(name));
+ }
+ String[] newTypes = new String[types.length + 1];
+ System.arraycopy(types, 0, newTypes, 0, types.length);
+ newTypes[types.length] = "mix:referenceable";
+ pvm.put("jcr:mixinTypes", newTypes);
+ } else {
+ pvm.put("jcr:mixinTypes", "mix:referenceable");
+ }
+ pvm.save();
+
+ final Set<String> newNodeTypes = getMixinNodeTypes(testNode);
+ assertEquals(newNodeTypes.size(), exNodeTypes.size() + 1);
+ }
+
+ protected JcrPropertyMap createPropertyMap(final Node node) {
+ return new JcrModifiablePropertyMap(node);
+ }
+
+ /**
+ * Check that the value map contains all supplied values
+ */
+ private void assertContains(ValueMap map, Map<String, Object> values) {
+ for(Map.Entry<String, Object> entry : values.entrySet()) {
+ final Object stored = map.get(entry.getKey());
+ assertEquals(values.get(entry.getKey()), stored);
+ }
+ }
+}