Author: cziegeler
Date: Tue Dec 22 15:14:44 2009
New Revision: 893197
URL: http://svn.apache.org/viewvc?rev=893197&view=rev
Log:
SLING-1253 : org.apache.sling.jcr.resource.JcrPropertyMap does not expose
ValueMap interface
Removed:
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrModifiablePropertyMap.java
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrPropertyMap.java
Modified:
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrModifiablePropertyMap.java
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrPropertyMap.java
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java
sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrModifiablePropertyMapTest.java
sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrPropertyMapTest.java
Modified:
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrModifiablePropertyMap.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrModifiablePropertyMap.java?rev=893197&r1=893196&r2=893197&view=diff
==============================================================================
---
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrModifiablePropertyMap.java
(original)
+++
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrModifiablePropertyMap.java
Tue Dec 22 15:14:44 2009
@@ -18,14 +18,28 @@
*/
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.jackrabbit.util.ISO9075;
+import org.apache.sling.api.resource.PersistableValueMap;
+import org.apache.sling.api.resource.PersistenceException;
/**
* This implementation of the value map allows to change
* the properies and save them later on.
*/
public final class JcrModifiablePropertyMap
- extends org.apache.sling.jcr.resource.internal.JcrModifiablePropertyMap {
+ extends JcrPropertyMap
+ implements PersistableValueMap {
+
+ /** Set of removed and changed properties. */
+ private Set<String> changedProperties;
/**
* Constructor
@@ -44,4 +58,117 @@
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<String>();
+ }
+ 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 CacheEntry(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<String>();
+ }
+ this.changedProperties.add(key);
+ 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 Map.Entry<? extends String, ? extends Object> entry =
(Map.Entry<? extends String, ? extends Object>) 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<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.valueCache.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) {
+ final String name = ISO9075.encodePath(key);
+ if ( cache.containsKey(key) ) {
+ final CacheEntry 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.save();
+ } catch (RepositoryException re) {
+ throw new PersistenceException("Unable to persist changes.", re);
+ }
+ this.reset();
+ }
}
Modified:
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrPropertyMap.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrPropertyMap.java?rev=893197&r1=893196&r2=893197&view=diff
==============================================================================
---
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrPropertyMap.java
(original)
+++
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrPropertyMap.java
Tue Dec 22 15:14:44 2009
@@ -18,20 +18,546 @@
*/
package org.apache.sling.jcr.resource;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collection;
+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.Session;
+import javax.jcr.Value;
+import javax.jcr.ValueFormatException;
+
+import org.apache.jackrabbit.util.ISO9075;
+import org.apache.sling.api.resource.ValueMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* An implementation of the value map based on a JCR node.
* @see JcrModifiablePropertyMap
*/
-public final class JcrPropertyMap
- extends org.apache.sling.jcr.resource.internal.JcrPropertyMap {
+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<String, CacheEntry> cache;
+
+ /** A cache for the values. */
+ final Map<String, Object> valueCache;
+
+ /** Has the node been read completly? */
+ boolean fullyRead;
+
+ private final ClassLoader dynamicClassLoader;
/**
* Constructor
* @param node The underlying node.
*/
public JcrPropertyMap(final Node node) {
- super(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<String, CacheEntry>();
+ this.valueCache = new LinkedHashMap<String, Object>();
+ 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> T get(final String aKey, final Class<T> type) {
+ final String key = checkKey(aKey);
+ if (type == null) {
+ return (T) get(key);
+ }
+
+ CacheEntry 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> 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<T> type = (Class<T>) 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());
+ CacheEntry entry = cache.get(key);
+ if (entry == null) {
+ entry = read(key);
+ }
+ final Object value = (entry == null ? null : entry.defaultValue);
+ 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<java.util.Map.Entry<String, Object>> entrySet() {
+ readFully();
+ return valueCache.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 valueCache.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
------------------------
+
+ CacheEntry 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 CacheEntry entry = new CacheEntry(prop);
+ cache.put(key, entry);
+ valueCache.put(key, entry.defaultValue);
+ 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 CacheEntry entry = new CacheEntry(prop);
+ cache.put(key, entry);
+ valueCache.put(key, entry.defaultValue);
+ }
+ }
+ 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<? extends String, ? extends Object> t) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object remove(Object key) {
+ throw new UnsupportedOperationException();
+ }
+
+ // ---------- Implementation helper
+
+ @SuppressWarnings("unchecked")
+ private <T> T convertToType(final CacheEntry entry, Class<T> 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.defaultValue
+ + " to " + type, vfe);
+ } catch (RepositoryException re) {
+ LOGGER.info("converToType: Cannot get value of " +
entry.defaultValue, re);
+ }
+
+ // fall back to nothing
+ return result;
+ }
+
+ private <T> T[] convertToArray(final CacheEntry entry, Class<T> type)
+ throws ValueFormatException, RepositoryException {
+ List<T> values = new ArrayList<T>();
+ 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> T convertToType(final CacheEntry entry,
+ final int index,
+ final Value jcrValue,
+ final Class<T> type)
+ throws ValueFormatException, RepositoryException {
+ if ( type.isInstance(entry.defaultValue) ) {
+ return (T) entry.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;
+ }
+
+ static final class CacheEntry {
+ public final Property property;
+ public final boolean isMulti;
+ public final Value[] values;
+
+ public final Object defaultValue;
+
+ /**
+ * Create a value for the object.
+ * If the value type is supported directly through a jcr property type,
+ * the corresponding value is created. If the value is serializable,
+ * it is serialized through an object stream. Otherwise null is
returned.
+ */
+ private Value createValue(final Object obj, final Session session)
+ throws RepositoryException {
+ Value value = JcrResourceUtil.createValue(obj, session);
+ if ( value == null && obj instanceof Serializable ) {
+ try {
+ final ByteArrayOutputStream baos = new
ByteArrayOutputStream();
+ final ObjectOutputStream oos = new
ObjectOutputStream(baos);
+ oos.writeObject(obj);
+ oos.close();
+ final ByteArrayInputStream bais = new
ByteArrayInputStream(baos.toByteArray());
+ value = session.getValueFactory().createValue(bais);
+ } catch (IOException ioe) {
+ // we ignore this here and return null
+ }
+ }
+ return value;
+ }
+
+ /**
+ * Create a new cache entry from a property.
+ */
+ public CacheEntry(final Property prop)
+ throws RepositoryException {
+ this.property = prop;
+ if ( prop.getDefinition().isMultiple() ) {
+ isMulti = true;
+ values = prop.getValues();
+ } else {
+ isMulti = false;
+ values = new Value[] {prop.getValue()};
+ }
+ this.defaultValue = JcrResourceUtil.toJavaObject(prop);
+ }
+
+ /**
+ * Create a new cache entry from a value.
+ */
+ public CacheEntry(final Object value, final Session session)
+ throws RepositoryException {
+ this.property = null;
+ this.defaultValue = value;
+ if ( value.getClass().isArray() ) {
+ this.isMulti = true;
+ final Object[] values = (Object[])value;
+ this.values = new Value[values.length];
+ for(int i=0; i<values.length; i++) {
+ this.values[i] = this.createValue(values[i], session);
+ if ( this.values[i] == null ) {
+ throw new IllegalArgumentException("Value can't be
stored in the repository: " + values[i]);
+ }
+ }
+ } else {
+ this.isMulti = false;
+ this.values = new Value[] {this.createValue(value, session)};
+ if ( this.values[0] == null ) {
+ throw new IllegalArgumentException("Value can't be stored
in the repository: " + value);
+ }
+ }
+ }
+ }
+
+ /**
+ * 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 Class.forName(classDesc.getName(), true,
this.classloader);
+ }
+ return super.resolveClass(classDesc);
+ }
}
}
Modified:
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java?rev=893197&r1=893196&r2=893197&view=diff
==============================================================================
---
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java
(original)
+++
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java
Tue Dec 22 15:14:44 2009
@@ -45,10 +45,10 @@
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.jcr.resource.JcrModifiablePropertyMap;
+import org.apache.sling.jcr.resource.JcrPropertyMap;
import org.apache.sling.jcr.resource.JcrResourceConstants;
import org.apache.sling.jcr.resource.JcrResourceTypeProvider;
-import org.apache.sling.jcr.resource.internal.JcrModifiablePropertyMap;
-import org.apache.sling.jcr.resource.internal.JcrPropertyMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -121,7 +121,7 @@
} else if (type == URL.class) {
return (Type) getURL(); // unchecked cast
} else if (type == Map.class || type == ValueMap.class) {
- return (Type) new JcrPropertyMap(getNode()); // unchecked cast
+ return (Type) new JcrPropertyMap(getNode(),
this.dynamicClassLoader); // unchecked cast
} else if (type == PersistableValueMap.class) {
// check write
try {
Modified:
sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrModifiablePropertyMapTest.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrModifiablePropertyMapTest.java?rev=893197&r1=893196&r2=893197&view=diff
==============================================================================
---
sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrModifiablePropertyMapTest.java
(original)
+++
sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrModifiablePropertyMapTest.java
Tue Dec 22 15:14:44 2009
@@ -29,6 +29,8 @@
import org.apache.sling.api.resource.PersistableValueMap;
import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.jcr.resource.JcrModifiablePropertyMap;
+import org.apache.sling.jcr.resource.JcrPropertyMap;
import org.apache.sling.jcr.resource.JcrResourceUtil;
public class JcrModifiablePropertyMapTest extends JcrPropertyMapTest {
Modified:
sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrPropertyMapTest.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrPropertyMapTest.java?rev=893197&r1=893196&r2=893197&view=diff
==============================================================================
---
sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrPropertyMapTest.java
(original)
+++
sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrPropertyMapTest.java
Tue Dec 22 15:14:44 2009
@@ -31,6 +31,7 @@
import org.apache.jackrabbit.util.ISO9075;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.commons.testing.jcr.RepositoryTestBase;
+import org.apache.sling.jcr.resource.JcrPropertyMap;
public class JcrPropertyMapTest extends RepositoryTestBase {