You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2008/08/13 08:09:41 UTC
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/
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 <code>PersistableValueMap</code> 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<String> 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<String>();
+ }
+ 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<String>();
+ }
+ this.changedProperties.add(key);
+ this.cache.put(key, value);
+ return oldValue;
+ }
+
+ /**
+ * @see java.util.Map#putAll(java.util.Map)
+ */
+ public void putAll(Map<? extends String, ? extends Object> t) {
+ readFully();
+ if ( t != null ) {
+ final Iterator<?> i = t.entrySet().iterator();
+ while (i.hasNext() ) {
+ @SuppressWarnings("unchecked")
+ final Entry<? extends String, ? extends Object> entry = (Entry<? extends String, ? extends Object>) 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<String>();
+ }
+ 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<String, Object> cache;
+ protected final Map<String, Object> 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<java.util.Map.Entry<String, Object>> entrySet() {
readFully();
return cache.entrySet();
}
+ /**
+ * @see java.util.Map#keySet()
+ */
public Set<String> keySet() {
readFully();
return cache.keySet();
}
+ /**
+ * @see java.util.Map#values()
+ */
public Collection<Object> 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; i<values.length; i++) {
+ setValues[i] = createValue(values[i], node.getSession());
+ }
+ node.setProperty(propertyName, setValues);
+ } else {
+ node.setProperty(propertyName, createValue(propertyValue, node.getSession()));
+ }
+ }
+
+ /**
* Helper method, which returns the given resource type as returned from the
* {@link org.apache.sling.api.resource.Resource#getResourceType()} as a
* relative path.
- *
+ *
* @param type The resource type to be converted into a path
* @return The resource type as a path.
*/
@@ -111,7 +175,7 @@
* <code>Resource</code> addressed by the <code>resourceType</code> to a
* string. If no such child resource exists or if the resource does not
* adapt to a string, this method returns <code>null</code>.
- *
+ *
* @param resourceResolver The <code>ResourceResolver</code> used to
* access the resource whose path (relative or absolute) is given
* by the <code>resourceType</code> 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 <code>Resource</code> whose resource super type is
* requested.
* @return The resource super type or <code>null</code> 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