Return-Path: X-Original-To: apmail-sling-commits-archive@www.apache.org Delivered-To: apmail-sling-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 7617E932E for ; Thu, 2 Feb 2012 12:47:29 +0000 (UTC) Received: (qmail 82513 invoked by uid 500); 2 Feb 2012 12:47:29 -0000 Delivered-To: apmail-sling-commits-archive@sling.apache.org Received: (qmail 82466 invoked by uid 500); 2 Feb 2012 12:47:28 -0000 Mailing-List: contact commits-help@sling.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@sling.apache.org Delivered-To: mailing list commits@sling.apache.org Received: (qmail 82459 invoked by uid 99); 2 Feb 2012 12:47:28 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 02 Feb 2012 12:47:28 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 02 Feb 2012 12:47:24 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 615B923889E7; Thu, 2 Feb 2012 12:47:04 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1239587 [1/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... Date: Thu, 02 Feb 2012 12:47:01 -0000 To: commits@sling.apache.org From: vramdal@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20120202124704.615B923889E7@eris.apache.org> Author: vramdal Date: Thu Feb 2 12:46:58 2012 New Revision: 1239587 URL: http://svn.apache.org/viewvc?rev=1239587&view=rev Log: Copy of current jcr/resource bundle to start work on http://markmail.org/message/wp6cghi5nqprpusn Added: sling/whiteboard/resourceresolverfactory/jcr-resource/README.txt sling/whiteboard/resourceresolverfactory/jcr-resource/pom.xml sling/whiteboard/resourceresolverfactory/jcr-resource/src/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/appended-resources/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/appended-resources/META-INF/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrModifiablePropertyMap.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrPropertyMap.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceConstants.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceResolverFactory.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceUtil.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrItemAdapterFactory.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceListener.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverFactoryImpl.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverWebConsolePlugin.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/ResourceDecoratorTracker.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/ResourceIteratorDecorator.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/WorkspaceAuthInfoPostProcessor.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/WorkspaceDecoratedResource.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/JcrPropertyMapCacheEntry.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/LazyInputStream.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/MapEntries.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/MapEntry.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/Mapping.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/RedirectResource.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceIterator.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourcePathIterator.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntry.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/RootResourceProviderEntry.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/URI.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/URIException.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/WrappedResourceProvider.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResource.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceIterator.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResource.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProvider.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderEntry.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/starresource/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/starresource/StarResource.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/scripting/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/scripting/JcrObjectsBindingsValuesProvider.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/OSGI-INF/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/OSGI-INF/metatype/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/OSGI-INF/metatype/metatype.properties sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/folder.cnd sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/mapping.cnd sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/redirect.cnd sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/resource.cnd sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/resources/SLING-INF/nodetypes/vanitypath.cnd sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/resource/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/resource/internal/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrModifiablePropertyMapTest.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrPropertyMapTest.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceListenerTest.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverTest.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/resource/internal/SynchronousJcrResourceListener.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/JcrNodeResourceIteratorTest.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/MapEntryTest.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/RedirectResourceTest.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/ResourcePathIteratorTest.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntryTest.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResourceTestBase.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceTest.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResourceTest.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/MockResourceResolver.java sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/starresource/ sling/whiteboard/resourceresolverfactory/jcr-resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/starresource/StarResourceTest.java Added: sling/whiteboard/resourceresolverfactory/jcr-resource/README.txt URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/README.txt?rev=1239587&view=auto ============================================================================== --- sling/whiteboard/resourceresolverfactory/jcr-resource/README.txt (added) +++ sling/whiteboard/resourceresolverfactory/jcr-resource/README.txt Thu Feb 2 12:46:58 2012 @@ -0,0 +1,27 @@ +Apache Sling Resource Resolver + +This bundle provides the JCR based Resource Resolver. + +Getting Started +=============== + +This component uses a Maven 2 (http://maven.apache.org/) build +environment. It requires a Java 5 JDK (or higher) and Maven (http://maven.apache.org/) +2.0.7 or later. We recommend to use the latest Maven version. + +If you have Maven 2 installed, you can compile and +package the jar using the following command: + + mvn package + +See the Maven 2 documentation for other build features. + +The latest source code for this component is available in the +Subversion (http://subversion.tigris.org/) source repository of +the Apache Software Foundation. If you have Subversion installed, +you can checkout the latest source using the following command: + + svn checkout http://svn.apache.org/repos/asf/sling/trunk/jcr/resource + +See the Subversion documentation for other source control features. + Added: sling/whiteboard/resourceresolverfactory/jcr-resource/pom.xml URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/pom.xml?rev=1239587&view=auto ============================================================================== --- sling/whiteboard/resourceresolverfactory/jcr-resource/pom.xml (added) +++ sling/whiteboard/resourceresolverfactory/jcr-resource/pom.xml Thu Feb 2 12:46:58 2012 @@ -0,0 +1,258 @@ + + + + 4.0.0 + + org.apache.sling + sling + 12 + ../../../parent/pom.xml + + + org.apache.sling.jcr.resource + 2.0.11-SNAPSHOT + bundle + + Apache Sling JCR Resource Resolver + + This bundle provides the JCR based ResourceResolver. + + + + + scm:svn:http://svn.apache.org/repos/asf/sling/trunk/bundles/jcr/resource + + + scm:svn:https://svn.apache.org/repos/asf/sling/trunk/bundles/jcr/resource + + + http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource + + + + + 12314286 + **.internal.** + + + + + + org.apache.felix + maven-scr-plugin + + + org.apache.sling + maven-sling-plugin + 2.1.0 + + + generate-adapter-metadata + process-classes + + generate-adapter-metadata + + + + + + org.apache.felix + maven-bundle-plugin + true + + + + javax.script.*; + javax.annotation;resolution:=optional, + org.apache.sling.scripting.api.*;resolution:=optional, + org.apache.sling.api.resource;version="[$(version;==;$(@)),$(version;=+;$(@)))", + org.apache.sling.commons.osgi;version="$(@)", + * + + + org.apache.jackrabbit.api.observation + + + org.apache.sling.jcr.resource;version=2.1 + + + org.apache.sling.jcr.resource.internal.* + + + + + jackrabbit-classloader;inline="org/apache/jackrabbit/net/**|org/apache/jackrabbit/classloader/Util.*", + jackrabbit-jcr-commons;inline="org/apache/jackrabbit/util/ISO9075.*|org/apache/jackrabbit/name/QName.*|org/apache/jackrabbit/util/XMLChar.*|org/apache/jackrabbit/util/Text.*", + guava;inline="com/google/common/collect/Maps*.*|com/google/common/base/Preconditions.*|com/google/common/primitives/Ints.*" + + + + sling=http://sling.apache.org/jcr/sling/1.0 + + + + SLING-INF/nodetypes/folder.cnd, + SLING-INF/nodetypes/resource.cnd, + SLING-INF/nodetypes/vanitypath.cnd, + SLING-INF/nodetypes/redirect.cnd, + SLING-INF/nodetypes/mapping.cnd + + + + + + + + + + org.apache.jackrabbit + jackrabbit-api + 2.0.0 + provided + + + org.apache.felix + org.apache.felix.scr.annotations + + + javax.jcr + jcr + 2.0 + + + org.osgi + org.osgi.core + + + org.osgi + org.osgi.compendium + + + org.apache.sling + org.apache.sling.api + 2.1.0 + provided + + + org.apache.sling + org.apache.sling.scripting.api + 2.1.0 + provided + + + org.apache.sling + org.apache.sling.jcr.api + 2.0.6 + provided + + + org.apache.sling + org.apache.sling.adapter + 2.0.4 + provided + + + org.slf4j + slf4j-api + + + org.apache.sling + org.apache.sling.commons.osgi + 2.0.6 + provided + + + org.apache.sling + org.apache.sling.auth.core + 1.0.0 + provided + + + org.apache.sling + org.apache.sling.commons.classloader + 1.0.0 + provided + + + commons-collections + commons-collections + 3.2.1 + provided + + + com.google.guava + guava + r09 + provided + + + org.apache.sling + adapter-annotations + 1.0.0 + provided + + + + + javax.servlet + servlet-api + + + + + org.apache.jackrabbit + jackrabbit-classloader + 1.5.0 + provided + + + org.apache.jackrabbit + jackrabbit-jcr-commons + 2.0.0 + provided + + + + + org.apache.sling + org.apache.sling.commons.testing + 2.0.6 + test + + + org.mockito + mockito-all + 1.8.2 + test + + + junit-addons + junit-addons + 1.4 + test + + + org.apache.sling + org.apache.sling.jcr.base + 2.1.0 + test + + + Added: sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrModifiablePropertyMap.java URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrModifiablePropertyMap.java?rev=1239587&view=auto ============================================================================== --- sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrModifiablePropertyMap.java (added) +++ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrModifiablePropertyMap.java Thu Feb 2 12:46:58 2012 @@ -0,0 +1,220 @@ +/* + * 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; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import javax.jcr.nodetype.NodeType; + +import org.apache.jackrabbit.util.ISO9075; +import org.apache.sling.api.resource.PersistableValueMap; +import org.apache.sling.api.resource.PersistenceException; +import org.apache.sling.jcr.resource.internal.helper.JcrPropertyMapCacheEntry; + +/** + * This implementation of the value map allows to change + * the properies and save them later on. + */ +public final class JcrModifiablePropertyMap + extends JcrPropertyMap + implements PersistableValueMap { + + /** Set of removed and changed properties. */ + private Set changedProperties; + + /** + * Constructor + * @param node The underlying node. + */ + public JcrModifiablePropertyMap(final Node node) { + super(node); + } + + /** + * Constructor + * @param node The underlying node. + * @param dynamicCL Dynamic class loader for loading serialized objects. + * @since 2.0.6 + */ + public JcrModifiablePropertyMap(final Node node, final ClassLoader dynamicCL) { + super(node, dynamicCL); + } + + // ---------- Map + /** + * @see java.util.Map#clear() + */ + public void clear() { + // we have to read all properties first + this.readFully(); + if ( this.changedProperties == null ) { + this.changedProperties = new HashSet(); + } + this.changedProperties.addAll(this.cache.keySet()); + this.cache.clear(); + this.valueCache.clear(); + } + + /** + * @see java.util.Map#put(java.lang.Object, java.lang.Object) + */ + public Object put(String aKey, Object value) { + final String key = checkKey(aKey); + if ( key.indexOf('/') != -1 ) { + throw new IllegalArgumentException("Invalid key: " + key); + } + if ( value == null ) { + throw new NullPointerException("Value should not be null (key = " + key + ")"); + } + readFully(); + final Object oldValue = this.get(key); + try { + this.cache.put(key, new JcrPropertyMapCacheEntry(value, getNode().getSession())); + } catch (RepositoryException re) { + throw new IllegalArgumentException("Value for key " + key + " can't be put into node: " + value, re); + } + this.valueCache.put(key, value); + if ( this.changedProperties == null ) { + this.changedProperties = new HashSet(); + } + this.changedProperties.add(key); + return oldValue; + } + + /** + * @see java.util.Map#putAll(java.util.Map) + */ + public void putAll(Map t) { + readFully(); + if ( t != null ) { + final Iterator i = t.entrySet().iterator(); + while (i.hasNext() ) { + @SuppressWarnings("unchecked") + final Map.Entry entry = (Map.Entry) i.next(); + put(entry.getKey(), entry.getValue()); + } + } + } + + /** + * @see java.util.Map#remove(java.lang.Object) + */ + public Object remove(Object aKey) { + final String key = checkKey(aKey.toString()); + readFully(); + final Object oldValue = this.cache.remove(key); + this.valueCache.remove(key); + if ( this.changedProperties == null ) { + this.changedProperties = new HashSet(); + } + this.changedProperties.add(key.toString()); + return oldValue; + } + + /** + * @see org.apache.sling.api.resource.PersistableValueMap#reset() + */ + public void reset() { + if ( this.changedProperties != null ) { + this.changedProperties = null; + } + this.cache.clear(); + this.valueCache.clear(); + this.fullyRead = false; + } + + /** Property for the mixin node types. */ + private static final String MIXIN_TYPES = "jcr:mixinTypes"; + + /** + * Update the mixin node types + */ + private void handleMixinTypes(final Node node, final Value[] mixinTypes) throws RepositoryException { + final Set newTypes = new HashSet(); + if ( mixinTypes != null ) { + for(final Value value : mixinTypes ) { + newTypes.add(value.getString()); + } + } + final Set oldTypes = new HashSet(); + for(final NodeType mixinType : node.getMixinNodeTypes()) { + oldTypes.add(mixinType.getName()); + } + for(final String name : oldTypes) { + if ( !newTypes.contains(name) ) { + node.removeMixin(name); + } else { + newTypes.remove(name); + } + } + for(final String name : newTypes) { + node.addMixin(name); + } + } + + /** + * @see org.apache.sling.api.resource.PersistableValueMap#save() + */ + public void save() throws PersistenceException { + if ( this.changedProperties == null || this.changedProperties.size() == 0 ) { + // nothing has changed + return; + } + try { + final Node node = getNode(); + // check for mixin types + final String mixinTypesKey = ISO9075.decode(MIXIN_TYPES); + if ( this.changedProperties.contains(mixinTypesKey) ) { + if ( cache.containsKey(mixinTypesKey) ) { + final JcrPropertyMapCacheEntry entry = cache.get(mixinTypesKey); + handleMixinTypes(node, entry.values); + } else { + // remove all mixin types! + handleMixinTypes(node, null); + } + } + + for(final String key : this.changedProperties) { + final String name = ISO9075.encodePath(key); + if ( !MIXIN_TYPES.equals(name) ) { + if ( cache.containsKey(key) ) { + final JcrPropertyMapCacheEntry entry = cache.get(key); + if ( entry.isMulti ) { + node.setProperty(name, entry.values); + } else { + node.setProperty(name, entry.values[0]); + } + } else { + node.setProperty(name, (String)null); + } + } + } + node.getSession().save(); + } catch (RepositoryException re) { + throw new PersistenceException("Unable to persist changes.", re); + } + this.reset(); + } +} Added: sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrPropertyMap.java URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrPropertyMap.java?rev=1239587&view=auto ============================================================================== --- sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrPropertyMap.java (added) +++ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrPropertyMap.java Thu Feb 2 12:46:58 2012 @@ -0,0 +1,515 @@ +/* + * 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; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.PropertyIterator; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import javax.jcr.ValueFormatException; + +import org.apache.jackrabbit.util.ISO9075; +import org.apache.sling.api.resource.ValueMap; +import org.apache.sling.jcr.resource.internal.helper.JcrPropertyMapCacheEntry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.Maps; + +/** + * An implementation of the value map based on a JCR node. + * @see JcrModifiablePropertyMap + */ +public class JcrPropertyMap + implements ValueMap { + + /** default logger */ + private static Logger LOGGER = LoggerFactory.getLogger(JcrPropertyMap.class); + + /** The underlying node. */ + private final Node node; + + /** A cache for the properties. */ + final Map cache; + + /** A cache for the values. */ + final Map valueCache; + + /** Has the node been read completly? */ + boolean fullyRead; + + private final ClassLoader dynamicClassLoader; + + /** + * Constructor + * @param node The underlying node. + */ + public JcrPropertyMap(final Node node) { + this(node, null); + } + + /** + * Constructor + * @param node The underlying node. + * @param dynamicCL Dynamic class loader for loading serialized objects. + * @since 2.0.8 + */ + public JcrPropertyMap(final Node node, final ClassLoader dynamicCL) { + this.node = node; + this.cache = new LinkedHashMap(); + this.valueCache = new LinkedHashMap(); + this.fullyRead = false; + this.dynamicClassLoader = dynamicCL; + } + + /** + * Get the node. + */ + Node getNode() { + return node; + } + + // ---------- ValueMap + + String checkKey(final String key) { + if ( key == null ) { + throw new NullPointerException("Key must not be null."); + } + if ( key.startsWith("./") ) { + return key.substring(2); + } + return key; + } + + /** + * @see org.apache.sling.api.resource.ValueMap#get(java.lang.String, java.lang.Class) + */ + @SuppressWarnings("unchecked") + public T get(final String aKey, final Class type) { + final String key = checkKey(aKey); + if (type == null) { + return (T) get(key); + } + + JcrPropertyMapCacheEntry entry = cache.get(key); + if (entry == null) { + entry = read(key); + } + if ( entry == null ) { + return null; + } + return convertToType(entry, type); + } + + /** + * @see org.apache.sling.api.resource.ValueMap#get(java.lang.String, java.lang.Object) + */ + @SuppressWarnings("unchecked") + public T get(final String aKey,final T defaultValue) { + final String key = checkKey(aKey); + if (defaultValue == null) { + return (T) get(key); + } + + // special handling in case the default value implements one + // of the interface types supported by the convertToType method + Class type = (Class) normalizeClass(defaultValue.getClass()); + + T value = get(key, type); + if (value == null) { + value = defaultValue; + } + + return value; + } + + // ---------- Map + + /** + * @see java.util.Map#get(java.lang.Object) + */ + public Object get(final Object aKey) { + final String key = checkKey(aKey.toString()); + JcrPropertyMapCacheEntry entry = cache.get(key); + if (entry == null) { + entry = read(key); + } + final Object value = (entry == null ? null : entry.getDefaultValueOrNull()); + return value; + } + + /** + * @see java.util.Map#containsKey(java.lang.Object) + */ + public boolean containsKey(Object key) { + return get(key) != null; + } + + /** + * @see java.util.Map#containsValue(java.lang.Object) + */ + public boolean containsValue(Object value) { + readFully(); + return valueCache.containsValue(value); + } + + /** + * @see java.util.Map#isEmpty() + */ + public boolean isEmpty() { + return size() == 0; + } + + /** + * @see java.util.Map#size() + */ + public int size() { + readFully(); + return cache.size(); + } + + /** + * @see java.util.Map#entrySet() + */ + public Set> entrySet() { + readFully(); + final Map sourceMap; + if (cache.size() == valueCache.size()) { + sourceMap = valueCache; + } else { + sourceMap = Maps.transformEntries(cache, entryTransformer); + } + return Collections.unmodifiableSet(sourceMap.entrySet()); + } + + /** + * @see java.util.Map#keySet() + */ + public Set keySet() { + readFully(); + return cache.keySet(); + } + + /** + * @see java.util.Map#values() + */ + public Collection values() { + readFully(); + final Map sourceMap; + if (cache.size() == valueCache.size()) { + sourceMap = valueCache; + } else { + sourceMap = Maps.transformEntries(cache, entryTransformer); + } + return Collections.unmodifiableCollection(sourceMap.values()); + } + + /** + * Return the path of the current node. + * + * @throws IllegalStateException If a repository exception occurs + * @deprecated + */ + @Deprecated + public String getPath() { + try { + return node.getPath(); + } catch (RepositoryException e) { + throw new IllegalStateException(e); + } + } + + // ---------- Helpers to access the node's property ------------------------ + + JcrPropertyMapCacheEntry read(final String key) { + + // if the node has been completely read, we need not check + // again if the key does not point to a sub node + if (fullyRead && key.indexOf('/') == -1 ) { + // except if the key contains + return null; + } + + final String name = ISO9075.encodePath(key); + try { + if (node.hasProperty(name)) { + final Property prop = node.getProperty(name); + final JcrPropertyMapCacheEntry entry = new JcrPropertyMapCacheEntry(prop); + cache.put(key, entry); + Object defaultValue = entry.getDefaultValue(); + if (defaultValue != null) { + valueCache.put(key, entry.getDefaultValue()); + } + return entry; + } + } catch (RepositoryException re) { + // TODO: log !! + } + + // property not found or some error accessing it + return null; + } + + void readFully() { + if (!fullyRead) { + try { + PropertyIterator pi = node.getProperties(); + while (pi.hasNext()) { + Property prop = pi.nextProperty(); + final String name = prop.getName(); + final String key = ISO9075.decode(name); + if (!cache.containsKey(key)) { + final JcrPropertyMapCacheEntry entry = new JcrPropertyMapCacheEntry(prop); + cache.put(key, entry); + Object defaultValue = entry.getDefaultValue(); + if (defaultValue != null) { + valueCache.put(key, entry.getDefaultValue()); + } + } + } + fullyRead = true; + } catch (RepositoryException re) { + // TODO: log !! + } + } + } + + // ---------- Unsupported Modification methods + + public void clear() { + throw new UnsupportedOperationException(); + } + + public Object put(String key, Object value) { + throw new UnsupportedOperationException(); + } + + public void putAll(Map t) { + throw new UnsupportedOperationException(); + } + + public Object remove(Object key) { + throw new UnsupportedOperationException(); + } + + // ---------- Implementation helper + + @SuppressWarnings("unchecked") + private T convertToType(final JcrPropertyMapCacheEntry entry, Class type) { + T result = null; + + try { + final boolean array = type.isArray(); + + if (entry.isMulti) { + + if (array) { + + result = (T) convertToArray(entry, + type.getComponentType()); + + } else if (entry.values.length > 0) { + + result = convertToType(entry, -1, entry.values[0], type); + + } + + } else { + + if (array) { + + result = (T) convertToArray(entry, + type.getComponentType()); + + } else { + + result = convertToType(entry, -1, entry.values[0], type); + + } + } + + } catch (ValueFormatException vfe) { + LOGGER.info("converToType: Cannot convert value of " + entry.getDefaultValueOrNull() + + " to " + type, vfe); + } catch (RepositoryException re) { + LOGGER.info("converToType: Cannot get value of " + entry.getDefaultValueOrNull(), re); + } + + // fall back to nothing + return result; + } + + private T[] convertToArray(final JcrPropertyMapCacheEntry entry, Class type) + throws ValueFormatException, RepositoryException { + List values = new ArrayList(); + for (int i = 0; i < entry.values.length; i++) { + T value = convertToType(entry, i, entry.values[i], type); + if (value != null) { + values.add(value); + } + } + + @SuppressWarnings("unchecked") + T[] result = (T[]) Array.newInstance(type, values.size()); + + return values.toArray(result); + } + + @SuppressWarnings("unchecked") + private T convertToType(final JcrPropertyMapCacheEntry entry, + final int index, + final Value jcrValue, + final Class type) + throws ValueFormatException, RepositoryException { + Object defaultValue = entry.getDefaultValue(); + if ( type.isInstance(defaultValue) ) { + return (T) defaultValue; + } + + if (String.class == type) { + return (T) jcrValue.getString(); + + } else if (Byte.class == type) { + return (T) Byte.valueOf((byte) jcrValue.getLong()); + + } else if (Short.class == type) { + return (T) Short.valueOf((short) jcrValue.getLong()); + + } else if (Integer.class == type) { + return (T) Integer.valueOf((int) jcrValue.getLong()); + + } else if (Long.class == type) { + if (jcrValue.getType() == PropertyType.BINARY) { + if (index == -1) { + return (T) Long.valueOf(entry.property.getLength()); + } + return (T) Long.valueOf(entry.property.getLengths()[index]); + } + return (T) Long.valueOf(jcrValue.getLong()); + + } else if (Float.class == type) { + return (T) Float.valueOf((float) jcrValue.getDouble()); + + } else if (Double.class == type) { + return (T) Double.valueOf(jcrValue.getDouble()); + + } else if (Boolean.class == type) { + return (T) Boolean.valueOf(jcrValue.getBoolean()); + + } else if (Date.class == type) { + return (T) jcrValue.getDate().getTime(); + + } else if (Calendar.class == type) { + return (T) jcrValue.getDate(); + + } else if (Value.class == type) { + return (T) jcrValue; + + } else if (Property.class == type) { + return (T) entry.property; + + } else if (Serializable.class.isAssignableFrom(type) + && jcrValue.getType() == PropertyType.BINARY) { + ObjectInputStream ois = null; + try { + ois = new ObjectInputStream(jcrValue.getStream(), this.dynamicClassLoader); + final Object obj = ois.readObject(); + if ( type.isInstance(obj) ) { + return (T)obj; + } + } catch (ClassNotFoundException cnfe) { + // ignore and use fallback + } catch (IOException ioe) { + // ignore and use fallback + } finally { + if ( ois != null ) { + try { + ois.close(); + } catch (IOException ignore) { + // ignore + } + } + } + } + + // fallback in case of unsupported type + return null; + } + + private Class normalizeClass(Class type) { + if (Calendar.class.isAssignableFrom(type)) { + type = Calendar.class; + } else if (Date.class.isAssignableFrom(type)) { + type = Date.class; + } else if (Value.class.isAssignableFrom(type)) { + type = Value.class; + } else if (Property.class.isAssignableFrom(type)) { + type = Property.class; + } + return type; + } + + private static Maps.EntryTransformer entryTransformer = new Maps.EntryTransformer() { + + public Object transformEntry(String key, JcrPropertyMapCacheEntry value) { + return value.getDefaultValueOrNull(); + } + }; + + /** + * This is an extended version of the object input stream which uses the + * thread context class loader. + */ + private static class ObjectInputStream extends java.io.ObjectInputStream { + + private ClassLoader classloader; + + public ObjectInputStream(final InputStream in, final ClassLoader classLoader) throws IOException { + super(in); + this.classloader = classLoader; + } + + /** + * @see java.io.ObjectInputStream#resolveClass(java.io.ObjectStreamClass) + */ + @Override + protected Class resolveClass(java.io.ObjectStreamClass classDesc) throws IOException, ClassNotFoundException { + if ( this.classloader != null ) { + return this.classloader.loadClass(classDesc.getName()); + } + return super.resolveClass(classDesc); + } + } +} Added: sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceConstants.java URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceConstants.java?rev=1239587&view=auto ============================================================================== --- sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceConstants.java (added) +++ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceConstants.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; + +import org.apache.sling.api.SlingConstants; + +/** + * The JcrResourceConstants interface provides constant values. + */ +public class JcrResourceConstants { + + /** + * The namespace URI used by Sling JCR for items and node types used by + * Sling (value is "http://sling.apache.org/jcr/sling/1.0"). This URI is + * ensured to be mapped to the Sling namespace prefix sling for any + * session used by the JCR Resource bundle through the + * Sling-Namespaces bundle manifest header. + */ + public static final String SLING_NAMESPACE_URI = SlingConstants.NAMESPACE_URI_ROOT + + "jcr/sling/1.0"; + + /** + * The name of the JCR Property that defines the resource type of this node + * (value is "sling:resourceType"). The resource manager implementation of + * this bundle uses this property to defined the resource type of a loaded + * resource. If this property does not exist the primary node type is used + * as the resource type. + */ + public static final String SLING_RESOURCE_TYPE_PROPERTY = "sling:resourceType"; + + /** + * The name of the JCR Property that defines the resource super type (value + * is "sling:resourceSuperType"). The resource manager implementation of + * this bundle uses this property to defined the resource type of a loaded + * resource. If this property does not exist any non-mixin base type of the + * the primary node type is used as the resource super type. + */ + public static final String SLING_RESOURCE_SUPER_TYPE_PROPERTY = "sling:resourceSuperType"; + + /** + * The name of the property providing the JCR credentials to be used by the + * resource resolver factory method instead of the user.name + * and user.password properties. If this propery is provided + * and set to an object of type javax.jcr.Credentials the + * user.name property is ignored. + *

+ * This property is ignored by the + * {@link org.apache.sling.api.resource.ResourceResolverFactory#getAdministrativeResourceResolver(java.util.Map)} + * method or if the authentication info has a + * {@link #AUTHENTICATION_INFO_SESSION} property set to a + * javax.jcr.Session object. + *

+ * The type of this property, if present, is + * javax.jcr.Credentials. + * + * @since 2.1 + * @see org.apache.sling.api.resource.ResourceResolverFactory#getResourceResolver(java.util.Map) + */ + public static final String AUTHENTICATION_INFO_CREDENTIALS = "user.jcr.credentials"; + + /** + * The name of the authentication info property containing the workspace + * name to which the JCR based resource resolver should provide access. + *

+ * The type of this property, if present, is String. + * + * @since 2.1 + */ + public static final String AUTHENTICATION_INFO_WORKSPACE = "user.jcr.workspace"; + + /** + * The name of the authentication info property containing a JCR Session to + * which a JCR based resource resolver should provide access. If this + * property is set in the authentication info map, all other properties are + * ignored for the creation of the resource resolver with the exception of + * the user.impersonation which is still respected. + *

+ * The session provided by as this property and used as the basis of newly + * created resource resolver must not be logged out before the resource + * resolver is closed. On the other closing the resource resolver not logout + * this session. + *

+ * This property is ignored by the + * {@link org.apache.sling.api.resource.ResourceResolverFactory#getAdministrativeResourceResolver(java.util.Map)} + * method. + *

+ * The type of this property, if present, is javax.jcr.Session. + * + * @since 2.1 + */ + public static final String AUTHENTICATION_INFO_SESSION = "user.jcr.session"; + +} Added: sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceResolverFactory.java URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceResolverFactory.java?rev=1239587&view=auto ============================================================================== --- sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceResolverFactory.java (added) +++ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceResolverFactory.java Thu Feb 2 12:46:58 2012 @@ -0,0 +1,71 @@ +/* + * 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; + +import javax.jcr.Session; + +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.api.resource.ResourceResolverFactory; + +/** + * The JcrResourceResolverFactory interface defines the service + * interface to have JCR-based ResourceResolver instances created + * for JCR sessions. + *

+ * This interface is not intended to be implemented by client applications. It + * is implemented by this bundle and the implementation registered as a service + * for use by client applications. + * + * This interface is deprecated. You should use + * {@link org.apache.sling.api.resource.ResourceResolverFactory} + * instead. If you need a resource resolver based on an existing session + * you can create an authentication map just containing this session + * (using the key {@link JcrResourceConstants#AUTHENTICATION_INFO_SESSION}) + * and then call {@link org.apache.sling.api.resource.ResourceResolverFactory#getResourceResolver(java.util.Map)} + * with exactly this map. + * + * @deprecated Since 2.1. Use the + * {@link org.apache.sling.api.resource.ResourceResolverFactory} + */ +@Deprecated +public interface JcrResourceResolverFactory extends ResourceResolverFactory { + + /** + * Returns a ResourceResolver for the given session. Calling + * this method repeatedly returns a new instance on each call. + *

+ * This method is equivalent to: + * + *

+     * Map<String, Object> authInfo = new HashMap<String, Object>();
+     * authInfo.put(SESSION, session);
+     * return getResourceResolver(authInfo);
+     * 
+ *

+ * Note: Closing the ResourceResolver returned by this + * method will not close the provided Session ! Likewise + * the provided Session should not be logged out before closing + * the returned ResourceResolver. + * + * @param session The JCR Session used by the created resource + * manager to access the repository. + */ + ResourceResolver getResourceResolver(Session session); + +} Added: sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceUtil.java URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceUtil.java?rev=1239587&view=auto ============================================================================== --- sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceUtil.java (added) +++ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceUtil.java Thu Feb 2 12:46:58 2012 @@ -0,0 +1,329 @@ +/* + * 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; + +import java.io.InputStream; +import java.util.Calendar; +import java.util.StringTokenizer; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.Value; +import javax.jcr.ValueFactory; +import javax.jcr.query.Query; +import javax.jcr.query.QueryManager; +import javax.jcr.query.QueryResult; + +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.api.resource.ResourceUtil; +import org.apache.sling.jcr.resource.internal.helper.LazyInputStream; + +/** + * The JcrResourceUtil class provides helper methods used + * throughout this bundle. + */ +public class JcrResourceUtil { + + /** Helper method to execute a JCR query */ + public static QueryResult query(Session session, String query, + String language) throws RepositoryException { + QueryManager qManager = session.getWorkspace().getQueryManager(); + Query q = qManager.createQuery(query, language); + return q.execute(); + } + + /** Converts a JCR Value to a corresponding Java Object */ + public static Object toJavaObject(Value value) throws RepositoryException { + switch (value.getType()) { + case PropertyType.BINARY: + return new LazyInputStream(value); + case PropertyType.BOOLEAN: + return value.getBoolean(); + case PropertyType.DATE: + return value.getDate(); + case PropertyType.DOUBLE: + return value.getDouble(); + case PropertyType.LONG: + return value.getLong(); + case PropertyType.NAME: // fall through + case PropertyType.PATH: // fall through + case PropertyType.REFERENCE: // fall through + case PropertyType.STRING: // fall through + case PropertyType.UNDEFINED: // not actually expected + default: // not actually expected + return value.getString(); + } + } + + /** + * Converts the value(s) of a JCR Property to a corresponding Java Object. + * If the property has multiple values the result is an array of Java + * Objects representing the converted values of the property. + */ + public static Object toJavaObject(Property property) + throws RepositoryException { + // multi-value property: return an array of values + if (property.getDefinition().isMultiple()) { + Value[] values = property.getValues(); + Object[] result = new Object[values.length]; + for (int i = 0; i < values.length; i++) { + Value value = values[i]; + if (value != null) { + result[i] = toJavaObject(value); + } + } + return result; + } + + // single value property + return toJavaObject(property.getValue()); + } + + /** + * Creates a {@link javax.jcr.Value JCR Value} for the given object with + * the given Session. + * Selects the the {@link javax.jcr.PropertyType PropertyType} according + * the instance of the object's Class + * + * @param value object + * @param session to create value for + * @return the value or null if not convertible to a valid PropertyType + * @throws RepositoryException in case of error, accessing the Repository + */ + public static Value createValue(Object value, Session session) + throws RepositoryException { + Value val; + ValueFactory fac = session.getValueFactory(); + if(value instanceof Calendar) { + val = fac.createValue((Calendar)value); + } else if (value instanceof InputStream) { + val = fac.createValue((InputStream)value); + } else if (value instanceof Node) { + val = fac.createValue((Node)value); + } else if (value instanceof Long) { + val = fac.createValue((Long)value); + } else if (value instanceof Number) { + val = fac.createValue(((Number)value).doubleValue()); + } else if (value instanceof Boolean) { + val = fac.createValue((Boolean) value); + } else if ( value instanceof String ){ + val = fac.createValue((String)value); + } else { + val = null; + } + return val; + } + + /** + * Sets the value of the property. + * Selects the {@link javax.jcr.PropertyType PropertyType} according + * to the instance of the object's class. + * @param node The node where the property will be set on. + * @param propertyName The name of the property. + * @param propertyValue The value for the property. + */ + public static void setProperty(final Node node, + final String propertyName, + final Object propertyValue) + throws RepositoryException { + if ( propertyValue == null ) { + node.setProperty(propertyName, (String)null); + } else if ( propertyValue.getClass().isArray() ) { + final Object[] values = (Object[])propertyValue; + final Value[] setValues = new Value[values.length]; + for(int i=0; iResource addressed by the resourceType to a + * string. If no such child resource exists or if the resource does not + * adapt to a string, this method returns null. + * + * @param resourceResolver The ResourceResolver used to + * access the resource whose path (relative or absolute) is given + * by the resourceType parameter. + * @param resourceType The resource type whose super type is to be returned. + * This type is turned into a path by calling the + * {@link #resourceTypeToPath(String)} method before trying to + * get the resource through the resourceResolver. + * @return the super type of the resourceType or + * null if the resource type does not have a child + * resource + * {@link JcrResourceConstants#SLING_RESOURCE_SUPER_TYPE_PROPERTY} + * adapting to a string. + * @deprecated Use {@link ResourceUtil#getResourceSuperType(ResourceResolver, String)} + */ + @Deprecated + public static String getResourceSuperType( + ResourceResolver resourceResolver, String resourceType) { + return ResourceUtil.getResourceSuperType(resourceResolver, resourceType); + } + + /** + * Returns the resource super type of the given resource. This is either the + * child resource + * {@link JcrResourceConstants#SLING_RESOURCE_SUPER_TYPE_PROPERTY} if the + * given resource adapted to a string or the result of + * calling the {@link #getResourceSuperType(ResourceResolver, String)} + * method on the resource type of the resource. + *

+ * This mechanism allows to specifically set the resource super type on a + * per-resource level overwriting any resource super type hierarchy + * pre-defined by the actual resource type of the resource. + * + * @param resource The Resource whose resource super type is + * requested. + * @return The resource super type or null if the algorithm + * described above does not yield a resource super type. + * @deprecated Call {@link ResourceUtil#findResourceSuperType(Resource)} + */ + @Deprecated + public static String getResourceSuperType(Resource resource) { + String resourceSuperType = resource.getResourceSuperType(); + if ( resourceSuperType == null ) { + final ResourceResolver resolver = resource.getResourceResolver(); + + // try explicit resourceSuperType resource + final String resourceType = resource.getResourceType(); + resourceSuperType = ResourceUtil.getResourceSuperType(resolver, resourceType); + } + + return resourceSuperType; + } + + /** + * Creates or gets the {@link javax.jcr.Node Node} at the given Path. + * In case it has to create the Node all non-existent intermediate path-elements + * will be create with the given intermediate node type and the returned node + * will be created with the given nodeType + * + * @param path to create + * @param intermediateNodeType to use for creation of intermediate nodes (or null) + * @param nodeType to use for creation of the final node (or null) + * @param session to use + * @param autoSave Should save be called when a new node is created? + * @return the Node at path + * @throws RepositoryException in case of exception accessing the Repository + */ + public static Node createPath(String path, + String intermediateNodeType, + String nodeType, + Session session, + boolean autoSave) + throws RepositoryException { + if (path == null || path.length() == 0 || "/".equals(path)) { + return session.getRootNode(); + } else if (!session.itemExists(path)) { + return createPath(session.getRootNode(), + path.substring(1), + intermediateNodeType, + nodeType, + autoSave); + } else { + return (Node) session.getItem(path); + } + } + + /** + * Creates or gets the {@link javax.jcr.Node Node} at the given Path. + * In case it has to create the Node all non-existent intermediate path-elements + * will be create with the given intermediate node type and the returned node + * will be created with the given nodeType + * + * @param parentNode starting node + * @param relativePath to create + * @param intermediateNodeType to use for creation of intermediate nodes (or null) + * @param nodeType to use for creation of the final node (or null) + * @param autoSave Should save be called when a new node is created? + * @return the Node at path + * @throws RepositoryException in case of exception accessing the Repository + */ + public static Node createPath(Node parentNode, + String relativePath, + String intermediateNodeType, + String nodeType, + boolean autoSave) + throws RepositoryException { + if (relativePath == null || relativePath.length() == 0 || "/".equals(relativePath)) { + return parentNode; + } else if (!parentNode.hasNode(relativePath)) { + Node node = parentNode; + int pos = relativePath.lastIndexOf('/'); + if ( pos != -1 ) { + final StringTokenizer st = new StringTokenizer(relativePath.substring(0, pos), "/"); + while ( st.hasMoreTokens() ) { + final String token = st.nextToken(); + if ( !node.hasNode(token) ) { + try { + if ( intermediateNodeType != null ) { + node.addNode(token, intermediateNodeType); + } else { + node.addNode(token); + } + if ( autoSave ) node.getSession().save(); + } catch (RepositoryException re) { + // we ignore this as this folder might be created from a different task + node.refresh(false); + } + } + node = node.getNode(token); + } + relativePath = relativePath.substring(pos + 1); + } + if ( !node.hasNode(relativePath) ) { + if ( nodeType != null ) { + node.addNode(relativePath, nodeType); + } else { + node.addNode(relativePath); + } + if ( autoSave ) node.getSession().save(); + } + return node.getNode(relativePath); + } else { + return parentNode.getNode(relativePath); + } + } +} Added: sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrItemAdapterFactory.java URL: http://svn.apache.org/viewvc/sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrItemAdapterFactory.java?rev=1239587&view=auto ============================================================================== --- sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrItemAdapterFactory.java (added) +++ sling/whiteboard/resourceresolverfactory/jcr-resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrItemAdapterFactory.java Thu Feb 2 12:46:58 2012 @@ -0,0 +1,91 @@ +/* + * 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.util.Dictionary; +import java.util.Hashtable; +import java.util.Map; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.RepositoryException; + +import org.apache.sling.api.adapter.AdapterFactory; +import org.apache.sling.api.resource.PersistableValueMap; +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ValueMap; +import org.apache.sling.jcr.resource.internal.helper.jcr.JcrNodeResource; +import org.apache.sling.jcr.resource.internal.helper.jcr.JcrPropertyResource; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.ServiceRegistration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * AdapterFactory which adapts JCR Nodes and Properties into Resources. + */ +class JcrItemAdapterFactory implements AdapterFactory { + + private final Logger logger = LoggerFactory.getLogger(JcrItemAdapterFactory.class); + + private final JcrResourceResolverFactoryImpl resourceResolverFactory; + + private ServiceRegistration serviceRegsitration; + + public JcrItemAdapterFactory(BundleContext ctx, JcrResourceResolverFactoryImpl resourceResolverFactory) { + this.resourceResolverFactory = resourceResolverFactory; + Dictionary properties = new Hashtable(); + properties.put(ADAPTABLE_CLASSES, new String[] { Node.class.getName(), Property.class.getName() }); + properties.put(ADAPTER_CLASSES, + new String[] { Resource.class.getName(), Map.class.getName(), ValueMap.class.getName(), + PersistableValueMap.class.getName() }); + properties.put(Constants.SERVICE_DESCRIPTION, "JCR Item Adapter Factory"); + properties.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation"); + this.serviceRegsitration = ctx.registerService(AdapterFactory.class.getName(), this, properties); + } + + public void dispose() { + if (this.serviceRegsitration != null) { + this.serviceRegsitration.unregister(); + this.serviceRegsitration = null; + } + } + + @SuppressWarnings("unchecked") + public AdapterType getAdapter(Object adaptable, Class type) { + if (type == Resource.class) { + try { + if (adaptable instanceof Node) { + Node node = (Node) adaptable; + return (AdapterType) new JcrNodeResource(resourceResolverFactory.getResourceResolver(node + .getSession()), node, resourceResolverFactory.getDynamicClassLoader()); + } else if (adaptable instanceof Property) { + Property property = (Property) adaptable; + return (AdapterType) new JcrPropertyResource(resourceResolverFactory.getResourceResolver(property + .getSession()), property); + } + } catch (RepositoryException e) { + logger.error("Unable to adapt JCR Item to a Resource", e); + } + return null; + } else { + return getAdapter(adaptable, Resource.class).adaptTo(type); + } + } + +}