Return-Path: Delivered-To: apmail-incubator-sling-commits-archive@locus.apache.org Received: (qmail 75906 invoked from network); 13 Aug 2008 06:10:40 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 13 Aug 2008 06:10:40 -0000 Received: (qmail 36325 invoked by uid 500); 13 Aug 2008 06:10:40 -0000 Delivered-To: apmail-incubator-sling-commits-archive@incubator.apache.org Received: (qmail 36312 invoked by uid 500); 13 Aug 2008 06:10:39 -0000 Mailing-List: contact sling-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: sling-dev@incubator.apache.org Delivered-To: mailing list sling-commits@incubator.apache.org Received: (qmail 36303 invoked by uid 99); 13 Aug 2008 06:10:39 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 12 Aug 2008 23:10:39 -0700 X-ASF-Spam-Status: No, hits=-1998.0 required=10.0 tests=ALL_TRUSTED,URIBL_BLACK 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; Wed, 13 Aug 2008 06:09:44 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 851B5238898F; Tue, 12 Aug 2008 23:09:42 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r685455 - in /incubator/sling/trunk: api/src/main/java/org/apache/sling/api/resource/ jcr/resource/src/main/java/org/apache/sling/jcr/resource/ jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/ Date: Wed, 13 Aug 2008 06:09:41 -0000 To: sling-commits@incubator.apache.org From: cziegeler@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20080813060942.851B5238898F@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: cziegeler Date: Tue Aug 12 23:09:40 2008 New Revision: 685455 URL: http://svn.apache.org/viewvc?rev=685455&view=rev Log: SLING-609 : Add persistable map for persisting changes and implement it for the jcr resources. Added: incubator/sling/trunk/api/src/main/java/org/apache/sling/api/resource/PersistableValueMap.java (with props) incubator/sling/trunk/api/src/main/java/org/apache/sling/api/resource/PersistenceException.java (with props) incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrModifiablePropertyMap.java (with props) Modified: incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrPropertyMap.java incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceUtil.java incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java Added: incubator/sling/trunk/api/src/main/java/org/apache/sling/api/resource/PersistableValueMap.java URL: http://svn.apache.org/viewvc/incubator/sling/trunk/api/src/main/java/org/apache/sling/api/resource/PersistableValueMap.java?rev=685455&view=auto ============================================================================== --- incubator/sling/trunk/api/src/main/java/org/apache/sling/api/resource/PersistableValueMap.java (added) +++ incubator/sling/trunk/api/src/main/java/org/apache/sling/api/resource/PersistableValueMap.java Tue Aug 12 23:09:40 2008 @@ -0,0 +1,44 @@ +/* + * 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.api.resource; + + + +/** + * The PersistableValueMap is an extension + * of the {@link ValueMap} which allows to modify and + * persist the properties. + * + * Note, that each time you call {@link Resource#adaptTo(Class)} + * you get a new map instance which does not share modified + * properties with other representations. + */ +public interface PersistableValueMap extends ValueMap { + + /** + * Persists the changes. + * @throws PersistenceException If the changes can't be persisted. + */ + void save() throws PersistenceException; + + /** + * Reset the changes. + */ + void reset(); +} Propchange: incubator/sling/trunk/api/src/main/java/org/apache/sling/api/resource/PersistableValueMap.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: incubator/sling/trunk/api/src/main/java/org/apache/sling/api/resource/PersistableValueMap.java ------------------------------------------------------------------------------ svn:keywords = author date id revision rev url Propchange: incubator/sling/trunk/api/src/main/java/org/apache/sling/api/resource/PersistableValueMap.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: incubator/sling/trunk/api/src/main/java/org/apache/sling/api/resource/PersistenceException.java URL: http://svn.apache.org/viewvc/incubator/sling/trunk/api/src/main/java/org/apache/sling/api/resource/PersistenceException.java?rev=685455&view=auto ============================================================================== --- incubator/sling/trunk/api/src/main/java/org/apache/sling/api/resource/PersistenceException.java (added) +++ incubator/sling/trunk/api/src/main/java/org/apache/sling/api/resource/PersistenceException.java Tue Aug 12 23:09:40 2008 @@ -0,0 +1,41 @@ +/* + * 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.api.resource; + +import java.io.IOException; + +/** + * This exception will be thrown during the try to persists + * changes to a {@link PersistableValueMap}. + */ +public class PersistenceException extends IOException { + + public PersistenceException() { + super(); + } + + public PersistenceException(String s) { + super(s); + } + + public PersistenceException(String s, Throwable t) { + super(s); + initCause(t); + } +} Propchange: incubator/sling/trunk/api/src/main/java/org/apache/sling/api/resource/PersistenceException.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: incubator/sling/trunk/api/src/main/java/org/apache/sling/api/resource/PersistenceException.java ------------------------------------------------------------------------------ svn:keywords = author date id revision rev url Propchange: incubator/sling/trunk/api/src/main/java/org/apache/sling/api/resource/PersistenceException.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrModifiablePropertyMap.java URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrModifiablePropertyMap.java?rev=685455&view=auto ============================================================================== --- incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrModifiablePropertyMap.java (added) +++ incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrModifiablePropertyMap.java Tue Aug 12 23:09:40 2008 @@ -0,0 +1,147 @@ +/* + * 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 org.apache.sling.api.resource.PersistenceException; + +/** + * This implementation of the value map allows to change + * the properies and save them later on. + */ +public class JcrModifiablePropertyMap extends JcrPropertyMap { + + /** Set of removed and changed properties. */ + private Set changedProperties; + + public JcrModifiablePropertyMap(Node node) { + super(node); + } + + // ---------- Map + + /** + * @see java.util.Map#get(java.lang.Object) + */ + public Object get(Object key) { + Object value = cache.get(key); + if (value == null && !this.fullyRead ) { + value = read((String) key); + } + + return value; + } + + /** + * @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(); + } + + /** + * @see java.util.Map#put(java.lang.Object, java.lang.Object) + */ + public Object put(String key, Object value) { + readFully(); + final Object oldValue = this.get(key); + if ( this.changedProperties == null ) { + this.changedProperties = new HashSet(); + } + this.changedProperties.add(key); + this.cache.put(key, value); + 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 Entry entry = (Entry) i.next(); + put(entry.getKey(), entry.getValue()); + } + } + } + + /** + * @see java.util.Map#remove(java.lang.Object) + */ + public Object remove(Object key) { + readFully(); + final Object oldValue = this.get(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.fullyRead = false; + } + + /** + * @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(); + for(final String key : this.changedProperties) { + if ( cache.containsKey(key) ) { + JcrResourceUtil.setProperty(node, key, this.cache.get(key)); + } else { + node.setProperty(key, (String)null); + } + } + node.save(); + } catch (RepositoryException re) { + throw new PersistenceException("Unable to persist changes.", re); + } + this.reset(); + } +} Propchange: incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrModifiablePropertyMap.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrModifiablePropertyMap.java ------------------------------------------------------------------------------ svn:keywords = author date id revision rev url Propchange: incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrModifiablePropertyMap.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrPropertyMap.java URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrPropertyMap.java?rev=685455&r1=685454&r2=685455&view=diff ============================================================================== --- incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrPropertyMap.java (original) +++ incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrPropertyMap.java Tue Aug 12 23:09:40 2008 @@ -41,13 +41,13 @@ public class JcrPropertyMap implements ValueMap { /** default log */ - private final Logger log = LoggerFactory.getLogger(getClass()); + private Logger logger = LoggerFactory.getLogger(JcrPropertyMap.class); private final Node node; - private final Map cache; + protected final Map cache; - private boolean fullyRead; + protected boolean fullyRead; public JcrPropertyMap(Node node) { this.node = node; @@ -55,6 +55,10 @@ this.fullyRead = false; } + protected Node getNode() { + return node; + } + // ---------- ValueMap @SuppressWarnings("unchecked") @@ -100,56 +104,76 @@ 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 cache.containsValue(value); } + /** + * @see java.util.Map#isEmpty() + */ public boolean isEmpty() { - // only start reading if there is nothing in the cache yet - if (cache.isEmpty()) { - readFully(); - } - - return cache.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(); return cache.entrySet(); } + /** + * @see java.util.Map#keySet() + */ public Set keySet() { readFully(); return cache.keySet(); } + /** + * @see java.util.Map#values() + */ public Collection values() { readFully(); return cache.values(); } + /** + * Return the path of the current node. + * @throws IllegalStateException If a repository exception occurs + */ public String getPath() { try { return node.getPath(); } catch (RepositoryException e) { - // TODO - return ""; + throw new IllegalStateException(e); } } + // ---------- Helpers to access the node's property ------------------------ - private Object read(String key) { + protected Object read(String key) { // if the node has been completely read, we need not check // again, as we certainly will not find the key @@ -172,7 +196,7 @@ return null; } - private void readFully() { + protected void readFully() { if (!fullyRead) { try { PropertyIterator pi = node.getProperties(); @@ -228,10 +252,10 @@ } } catch (ValueFormatException vfe) { - log.info("converToType: Cannot convert value of " + name + " to " + logger.info("converToType: Cannot convert value of " + name + " to " + type, vfe); } catch (RepositoryException re) { - log.info("converToType: Cannot get value of " + name, re); + logger.info("converToType: Cannot get value of " + name, re); } // fall back to nothing Modified: incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceUtil.java URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceUtil.java?rev=685455&r1=685454&r2=685455&view=diff ============================================================================== --- incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceUtil.java (original) +++ incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceUtil.java Tue Aug 12 23:09:40 2008 @@ -18,11 +18,16 @@ */ package org.apache.sling.jcr.resource; +import java.io.InputStream; +import java.util.Calendar; + +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; @@ -93,10 +98,69 @@ } /** + * 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.getClass().isAssignableFrom(Calendar.class)) { + val = fac.createValue((Calendar)value); + } else if (value.getClass().isAssignableFrom(InputStream.class)) { + val = fac.createValue((InputStream)value); + } else if (value.getClass().isAssignableFrom(Node.class)) { + val = fac.createValue((Node)value); + } else if (value.getClass().isAssignableFrom(Long.class)) { + val = fac.createValue((Long)value); + } else if (value.getClass().isAssignableFrom(Number.class)) { + val = fac.createValue(((Number)value).doubleValue()); + } else if (value.getClass().isAssignableFrom(Boolean.class)) { + val = fac.createValue((Boolean) value); + } else { + val = fac.createValue((String)value); + } + 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. @@ -151,7 +215,7 @@ * 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 Modified: incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java?rev=685455&r1=685454&r2=685455&view=diff ============================================================================== --- incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java (original) +++ incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java Tue Aug 12 23:09:40 2008 @@ -37,10 +37,12 @@ import javax.jcr.RepositoryException; import org.apache.jackrabbit.net.URLFactory; +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.JcrResourceTypeProvider; import org.slf4j.Logger; @@ -81,6 +83,15 @@ return (Type) getURL(); // unchecked cast } else if (type == Map.class || type == ValueMap.class) { return (Type) new JcrPropertyMap(getNode()); // unchecked cast + } else if (type == PersistableValueMap.class ) { + // check write + try { + getNode().getSession().checkPermission(getNode().getPath(), "set_property"); + return (Type) new JcrModifiablePropertyMap(getNode()); + } catch (RepositoryException e) { + // either the user has no write permission or a more + // sever exception occured - in both cases we don't return the map + } } // fall back to default implementation