You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by fm...@apache.org on 2008/01/04 17:37:25 UTC

svn commit: r608910 [1/2] - in /incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/sling/ src/main/java/org/apache/sling/jcr/ src/main/java/org/ap...

Author: fmeschbe
Date: Fri Jan  4 08:37:23 2008
New Revision: 608910

URL: http://svn.apache.org/viewvc?rev=608910&view=rev
Log:
First steps towards a Prototype of "Everything is a Resource"

Added:
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/   (with props)
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/pom.xml
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/AbstractMappedObject.java
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/DefaultMappedObject.java
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/OcmConstants.java
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/BundleMapper.java
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/ClassDescriptorReader.java
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/ObjectContentManagerFactory.java
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/ObservingObjectCache.java
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/OcmAdapterFactory.java
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/SlingAtomicTypeConverterProvider.java
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/ValueTypeConverterImpl.java
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/classloader/
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/classloader/BundleLoader.java
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/classloader/ClassLoaderLoader.java
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/classloader/Loader.java
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/classloader/LoaderDelegate.java
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/classloader/MapperClassLoader.java
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/resources/
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/resources/META-INF/
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/resources/META-INF/LICENSE
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/resources/META-INF/LICENSE.kxml2
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/resources/META-INF/NOTICE
    incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/resources/graffito-jcr-mapping.dtd
      - copied unchanged from r607540, incubator/sling/whiteboard/fmeschbe/resource/jcr/resource/src/main/resources/graffito-jcr-mapping.dtd

Propchange: incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Fri Jan  4 08:37:23 2008
@@ -0,0 +1,3 @@
+target
+.classpath
+.project

Added: incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/pom.xml
URL: http://svn.apache.org/viewvc/incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/pom.xml?rev=608910&view=auto
==============================================================================
--- incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/pom.xml (added)
+++ incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/pom.xml Fri Jan  4 08:37:23 2008
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+    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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.sling</groupId>
+        <artifactId>sling</artifactId>
+        <version>1-incubator-SNAPSHOT</version>
+        <relativePath>../../parent/pom.xml</relativePath>
+    </parent>
+
+    <artifactId>org.apache.sling.jcr.ocm</artifactId>
+    <version>2.0.0-incubator-SNAPSHOT</version>
+    <packaging>bundle</packaging>
+
+    <name>Sling - Object Content Mapping</name>
+    <description>
+        This bundle provides Object Content Mapping support for
+        resources loaded from a JCR repositories. This support is
+        implemented as an AdapterFactory for Resource objects.
+    </description>
+
+    <scm>
+        <connection>
+            scm:svn:http://svn.apache.org/repos/asf/incubator/sling/trunk/jcr/ocm
+        </connection>
+        <developerConnection>
+            scm:svn:https://svn.apache.org/repos/asf/incubator/sling/trunk/jcr/ocm
+        </developerConnection>
+        <url>
+            http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/ocm
+        </url>
+    </scm>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-scr-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.sling</groupId>
+                <artifactId>maven-jcrocm-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.apache.sling.jcr.ocm;version=${pom.version},
+                            org.apache.jackrabbit.ocm.exception;
+                            org.apache.jackrabbit.ocm.mapper;
+                            org.apache.jackrabbit.ocm.manager;
+                            org.apache.jackrabbit.ocm.manager.atomictypeconverter;
+                            org.apache.jackrabbit.ocm.manager.collectionconverter;
+                            org.apache.jackrabbit.ocm.manager.collectionconverter.impl;
+                            org.apache.jackrabbit.ocm.query;
+                            org.apache.jackrabbit.ocm.version;version=1.4
+                        </Export-Package>
+                        <Private-Package>
+                            org.apache.sling.jcr.ocm.impl.*,
+                            org.apache.jackrabbit.ocm.lock,
+                            org.apache.jackrabbit.ocm.manager.atomictypeconverter.impl,
+                            org.apache.jackrabbit.ocm.manager.beanconverter,
+                            org.apache.jackrabbit.ocm.manager.beanconverter.impl,
+                            org.apache.jackrabbit.ocm.manager.cache,
+                            org.apache.jackrabbit.ocm.manager.cache.impl,
+                            org.apache.jackrabbit.ocm.manager.impl,
+                            org.apache.jackrabbit.ocm.manager.objectconverter,
+                            org.apache.jackrabbit.ocm.manager.objectconverter.impl,
+                            org.apache.jackrabbit.ocm.mapper.impl,
+                            org.apache.jackrabbit.ocm.mapper.impl.annotation,
+                            org.apache.jackrabbit.ocm.mapper.model,
+                            org.apache.jackrabbit.ocm.query.impl,
+                            org.apache.jackrabbit.ocm.reflection,
+                            org.apache.jackrabbit.ocm.repository,
+                            org.kxml2.io, org.xmlpull.v1
+                        </Private-Package>
+                        <Import-Package>
+                            !org.apache.jackrabbit.ocm.mapper.impl.digester,
+                            *
+                        </Import-Package>
+
+                        <Sling-Namespaces>
+                            ocm=http://jackrabbit.apache.org/ocm
+                        </Sling-Namespaces>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi_R4_core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi_R4_compendium</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.api</artifactId>
+            <version>2.0.0-incubator-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.jcr.resource</artifactId>
+            <version>2.0.0-incubator-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.osgi.commons</artifactId>
+            <version>2.0.0-incubator-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.jcr.api</artifactId>
+            <version>2.0.0-incubator-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>jackrabbit-ocm</artifactId>
+        </dependency>
+
+       <dependency>
+            <groupId>net.sf.kxml</groupId>
+            <artifactId>kxml2</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>jackrabbit-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>

Added: incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/AbstractMappedObject.java
URL: http://svn.apache.org/viewvc/incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/AbstractMappedObject.java?rev=608910&view=auto
==============================================================================
--- incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/AbstractMappedObject.java (added)
+++ incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/AbstractMappedObject.java Fri Jan  4 08:37:23 2008
@@ -0,0 +1,52 @@
+/*
+ * 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.ocm;
+
+/**
+ * The <code>AbstractMappedObject</code> is a simple helper class which may be
+ * extended to off-load handling of the path of mapped objects. It simply maps
+ * a single field <em>path</em> to have the path of the mapped object.
+ *
+ * @ocm.mapped discriminator="false"
+ */
+public abstract class AbstractMappedObject {
+
+    /**
+     * The path of the mapped object. This is not an actual JCR node property
+     * mapping but a special field taking the path of the mapped node.
+     * @ocm.field path="true"
+     */
+    private String path;
+
+    protected AbstractMappedObject() {
+    }
+
+    protected AbstractMappedObject(String path) {
+        this.path = path;
+    }
+
+    public void setPath(String path) {
+        this.path = path;
+    }
+
+    public String getPath() {
+        return path;
+    }
+
+}

Added: incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/DefaultMappedObject.java
URL: http://svn.apache.org/viewvc/incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/DefaultMappedObject.java?rev=608910&view=auto
==============================================================================
--- incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/DefaultMappedObject.java (added)
+++ incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/DefaultMappedObject.java Fri Jan  4 08:37:23 2008
@@ -0,0 +1,367 @@
+/*
+ * 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.ocm;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.jackrabbit.ocm.manager.collectionconverter.impl.ManagedHashMap;
+
+/**
+ * The <code>DefaultMappedObject</code> is used by the JCR based resource
+ * manager implemented by this bundle as a default to map JCR nodes. This class
+ * has the following features:
+ * <ul>
+ * <li>This object may be loaded from any existing node.
+ * <li>If inserting a new instance of this class into the repository a node of
+ * type <code>nt:unstructured</code> without any mixin types is created
+ * <li>All non-protected properties are simply read and may be accessed in the
+ * Java standard <code>Map</code> style using the {@link #get(Object)} and
+ * {@link #put(Object, Object)} methods.
+ * <li>Storing the object back to the repository just writes the map contents
+ * into the properties. Care must be taken to obey the node type restrictions if
+ * setting properties, otherwise storing back may fail.
+ * <li>Single-value properties are loaded and stored as scalar instances
+ * according to the mapping below. Multi-value properties are represented by
+ * this object as <code>java.util.List</code> instances.
+ * </ul>
+ * <p>
+ * <b>Reserved Properties</b>
+ * <p>
+ * The following is a list of reserved properties and their meanings. These
+ * properties should not be modified through the getters and setters.
+ * <dl>
+ * <dt><code>path</code>
+ * <dd>The path of the node underlying this instance.
+ * <dt><code>primaryType</code>
+ * <dd>The primary node type of the node underlying this instance. This
+ * property is read-only. Any modifications will not be stored in the node (of
+ * course). For newly created objects, this property is not used to indicate the
+ * desired node type.
+ * <dt><code>mixinTypes</code>
+ * <dd>The list of mixin node types of the node underlying this instance. This
+ * property is read-only. Any modifications will not be stored in the node. For
+ * newly created objects, this property is not used to indicate the desired
+ * mixin node types.
+ * <dt><code>properties</code>
+ * <dd>The map representing the properties of this content object itself.
+ * </dl>
+ * <p>
+ * <b>Mapping JCR Property types</b> <table border="1" cellspacing="0"
+ * cellpadding="3">
+ * <tr>
+ * <th colspan="2">Property type to Java types</th>
+ * </tr>
+ * <tr>
+ * <th>JCR Type</th>
+ * <th>Java Type</th>
+ * </tr>
+ * <tr>
+ * <td>STRING</td>
+ * <td>String</td>
+ * </tr>
+ * <tr>
+ * <td>DATE</td>
+ * <td>String</td>
+ * </tr>
+ * <tr>
+ * <td>BINARY</td>
+ * <td>java.io.InputStream</td>
+ * </tr>
+ * <tr>
+ * <td>DOUBLE</td>
+ * <td>java.lang.Double</td>
+ * </tr>
+ * <tr>
+ * <td>LONG</td>
+ * <td>java.lang.Long</td>
+ * </tr>
+ * <tr>
+ * <td>BOOLEAN</td>
+ * <td>java.lang.Boolean</td>
+ * </tr>
+ * <tr>
+ * <td>NAME</td>
+ * <td>String</td>
+ * </tr>
+ * <tr>
+ * <td>PATH</td>
+ * <td>String</td>
+ * </tr>
+ * <tr>
+ * <td>REFERENCE</td>
+ * <td>String</td>
+ * </tr>
+ * <tr>
+ * <th colspan="2">Java type to Property type</th>
+ * </tr>
+ * <tr>
+ * <th>Java Type</th>
+ * <th>JCR Type</th>
+ * </tr>
+ * <tr>
+ * <td>String</td>
+ * <td>STRING</td>
+ * </tr>
+ * <tr>
+ * <td>java.util.Date</td>
+ * <td>DATE</td>
+ * </tr>
+ * <tr>
+ * <td>java.util.Calendar</td>
+ * <td>DATE</td>
+ * </tr>
+ * <tr>
+ * <td>java.util.GregorianCalendar</td>
+ * <td>DATE</td>
+ * </tr>
+ * <tr>
+ * <td>java.io.InputStream</td>
+ * <td>BINARY</td>
+ * </tr>
+ * <tr>
+ * <td>java.lang.Double</td>
+ * <td>DOUBLE</td>
+ * </tr>
+ * <tr>
+ * <td>java.lang.Long</td>
+ * <td>LONG</td>
+ * </tr>
+ * <tr>
+ * <td>java.lang.Integer</td>
+ * <td>LONG</td>
+ * </tr>
+ * <tr>
+ * <td>java.lang.Boolean</td>
+ * <td>BOOLEAN</td>
+ * </tr>
+ * </table>
+ *
+ * @ocm.mapped discriminator="false" extend=""
+ */
+public class DefaultMappedObject extends HashMap<String, Object> {
+
+    /*
+     * Implementation Note: As this class extends the HashMap class it
+     * implements the Map interface and therefore the Commons Beanutils library
+     * used by the Jackrabbit JCR Mapper will directly access the map getter and
+     * setter methods to get and set properties instead of checking for specific
+     * getter and setter methods. For this reason the get() and put() methods
+     * have been overwritten here and check for the specially mapped property
+     * "properties" to call the respective specific getter and setter methods.
+     * As a consequence of this situation, no client properties of the name
+     * "properties" may currently be used. Also the "properties" property is not
+     * actually stored in the hash map and will not be iterated over. But the
+     * check for existence (containsKey) will also consider the "properties"
+     * property.
+     */
+
+    /**
+     * The name of the <i>path</i> object property.
+     * <p>
+     * See the implementation notes above regarding this property.
+     */
+    private static final String FIELD_PATH = "path";
+
+    /**
+     * The name of the <i>properties</i> object property.
+     * <p>
+     * See the implementation notes above regarding this property.
+     */
+    private static final String FIELD_PROPERTIES = "properties";
+
+    /**
+     * The name of the <i>primaryType</i> object property.
+     * <p>
+     * See the implementation notes above regarding this property.
+     */
+    private static final String FIELD_PRIMARY_TYPE = "primaryType";
+
+    /**
+     * The name of the <i>mixinTypes</i> object property.
+     * <p>
+     * See the implementation notes above regarding this property.
+     */
+    private static final String FIELD_MIXIN_TYPES = "mixinTypes";
+
+    /**
+     * Returns the value of the indexed property.
+     * <p>
+     * For the special property <code>properties</code> the
+     * {@link #getProperties()} method is called to return a copy of this map
+     * instead of looking in the map itself.
+     *
+     * @param key The index of the property to return.
+     * @return the indicated property or <code>null</code> if the map does not
+     *         contain it.
+     */
+    public Object get(String key) {
+        // handle properties as if they were map elements
+        // due to an inconsistency in the BeanUtils 1.5 through 1.7.0
+        // versions. Version 1.7.1 will fix this again, though ...
+        if (FIELD_PROPERTIES.equals(key)) {
+            return getProperties();
+        }
+
+        return super.get(key);
+    }
+
+    /**
+     * Sets the value of the indexed property.
+     * <p>
+     * For the special property <code>properties</code> the
+     * {@link #setProperties(ManagedHashMap)} method is called to insert all
+     * elements of the <code>value</code> which must be a <code>Map</code>
+     * into this map.
+     *
+     * @param key The index of the property to set
+     * @param value The value of the property to set.
+     * @return The former value of the property or <code>null</code> if the
+     *         property is new.
+     * @throws ClassCastException If the type of the <code>value</code> is
+     *             <code>ManagedHashMap</code> for the <code>properties</code>
+     *             property.
+     */
+    public Object put(String key, Object value) {
+        // handle properties as if they were map elements
+        // due to an inconsistency in the BeanUtils 1.5 through 1.7.0
+        // versions. Version 1.7.1 will fix this again, though ...
+        if (FIELD_PROPERTIES.equals(key)) {
+            Object old = getProperties();
+            setProperties((ManagedHashMap) value);
+            return old;
+        }
+
+        return super.put(key, value);
+    }
+
+    /**
+     * Returns <code>true</code> if this map contains the named property.
+     */
+    public boolean containsKey(String key) {
+        return FIELD_PROPERTIES.equals(key) || super.containsKey(key);
+    }
+
+    // ---------- OCM support -------------------------------------------------
+
+    /**
+     * Sets the path of this mapped object.
+     *
+     * @ocm.field path="true"
+     */
+    public void setPath(String path) {
+        if (path != null) {
+            put(FIELD_PATH, path);
+        }
+    }
+
+    /**
+     * Returns the path of this mapped object.
+     */
+    public String getPath() {
+        return (String) get(FIELD_PATH);
+    }
+
+    /**
+     * Sets the properties of this content object as read from the properties of
+     * the repository node.
+     * <p>
+     * This method copies the properties of the <code>contents</code> map into
+     * this map instance.
+     *
+     * @ocm.collection jcrName="*"
+     *                 collectionConverter="org.apache.jackrabbit.ocm.manager.collectionconverter.impl.ResidualPropertiesCollectionConverterImpl"
+     */
+    @SuppressWarnings("unchecked")
+    public void setProperties(ManagedHashMap contents) {
+        if (contents != null) {
+            putAll(contents); // unchecked cast
+        }
+    }
+
+    /**
+     * Returns the properties of this content to be written to the properties of
+     * the repository node.
+     * <p>
+     * The contents of the returned map replace all non-protected properties of
+     * the repository. That is, existing properties not contained in the map
+     * will be removed.
+     * <p>
+     * This method returns a new instance of a <code>ManagedHashMap</code>
+     * containing a copy of the current properties on each call.
+     */
+    public ManagedHashMap getProperties() {
+        // a copy of this map with the special properties removed
+        ManagedHashMap properties = new ManagedHashMap(this);
+        properties.remove(FIELD_PATH);
+        properties.remove(FIELD_PRIMARY_TYPE);
+        properties.remove(FIELD_MIXIN_TYPES);
+        return properties;
+    }
+
+    /**
+     * Sets the primary node type of the underlying node.
+     * <p>
+     * This method should only be called by the Graffito Mapper to set the type
+     * read from the node.
+     *
+     * @ocm.field jcrName="jcr:primaryType" autoUpdate="false"
+     *            autoInsert="false"
+     */
+    public void setPrimaryType(String type) {
+        put(FIELD_PRIMARY_TYPE, type);
+    }
+
+    /**
+     * Returns the primary node type of the underlying node or <code>null</code>
+     * for new objects.
+     */
+    public String getPrimaryType() {
+        return (String) get(FIELD_PRIMARY_TYPE);
+    }
+
+    /**
+     * Sets the mixin node types of the underlying node.
+     * <p>
+     * This method should only be called by the Graffito Mapper to set the types
+     * read from the node.
+     *
+     * @ocm.collection jcrName="jcr:mixinTypes"
+     *                 elementClassName="java.lang.String"
+     *                 collectionConverter="org.apache.jackrabbit.ocm.manager.collectionconverter.impl.MultiValueCollectionConverterImpl"
+     *                 autoUpdate="false" autoInsert="false"
+     */
+    public void setMixinTypes(ArrayList<String> mixinTypes) {
+        if (mixinTypes != null) {
+            put(FIELD_MIXIN_TYPES, new ArrayList<String>(mixinTypes));
+        }
+    }
+
+    /**
+     * Returns a list of the mixin node typse of the underlying node or
+     * <code>null</code> for new objects or if the node has no mixin node
+     * types.
+     */
+    @SuppressWarnings("unchecked")
+    public ArrayList<String> getMixinTypes() {
+        List<String> types = (List<String>) get(FIELD_MIXIN_TYPES); // unchecked cast
+        return (types != null) ? new ArrayList<String>(types) : null;
+    }
+}

Added: incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/OcmConstants.java
URL: http://svn.apache.org/viewvc/incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/OcmConstants.java?rev=608910&view=auto
==============================================================================
--- incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/OcmConstants.java (added)
+++ incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/OcmConstants.java Fri Jan  4 08:37:23 2008
@@ -0,0 +1,104 @@
+/*
+ * 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.ocm;
+
+import org.apache.sling.api.SlingConstants;
+
+/**
+ * The <code>OcmConstants</code> interface provides constant values
+ * for event topics and event properties for events sent from this bundle.
+ */
+public class OcmConstants {
+
+    /**
+     * 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 <em>sling</em> for
+     * any session used by the JCR Resource bundle through the
+     * <code>Sling-Namespaces</code> 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 topic root for events published by this bundle (value is
+     * "org/apache/sling/jcr/resource/ResourceEvent"). Event consumers should
+     * register to "org/apache/sling/jcr/resource/ResourceEvent/*" to receive
+     * all events from this bundle.
+     */
+    public static final String RESOURCE_EVENT = "org/apache/sling/jcr/resource/ResourceEvent";
+
+    /**
+     * The name of the event sent after new Object Mappings have been registered
+     * (value is "org/apache/sling/jcr/resource/ResourceEvent/MAPPED").
+     * <p>
+     * Events of this topics have two additional properties:
+     * {@link #MAPPING_CLASS} and {@link #MAPPING_NODE_TYPE}.
+     */
+    public static final String EVENT_MAPPING_ADDED = RESOURCE_EVENT + "/MAPPED";
+
+    /**
+     * The name of the event sent after Object Mappings have been unregistered
+     * (value is "org/apache/sling/jcr/resource/ResourceEvent/UNMAPPED").
+     * <p>
+     * Events of this topics have two additional properties:
+     * {@link #MAPPING_CLASS} and {@link #MAPPING_NODE_TYPE}.
+     */
+    public static final String EVENT_MAPPING_REMOVED = RESOURCE_EVENT
+        + "/UNMAPPED";
+
+    /**
+     * The name of the event property providing a <code>String[]</code> of
+     * class names mapped at the time the event is sent (value is
+     * "MAPPED_CLASS"). This is the complete list of all classes which are
+     * supported by the content manager for mapping.
+     */
+    public static final String MAPPING_CLASS = "MAPPED_CLASS";
+
+    /**
+     * The name of the event property providing a <code>String[]</code> of
+     * node types mapped at the time the event is sent (value is
+     * "MAPPED_NODE_TYPE"). This is the complete list of all node types which
+     * are supported by the content manager for mapping.
+     */
+    public static final String MAPPING_NODE_TYPE = "MAPPED_NODE_TYPE";
+
+    /**
+     * The name of the bundle manifest header listing the bundle entries
+     * providing Object Content Mapping configurations (value is
+     * "Sling-Mappings").
+     */
+    public static final String MAPPER_BUNDLE_HEADER = "Sling-Mappings";
+
+    /**
+     * The name of the bundle manifest header listing the resource provider root
+     * paths provided by the bundle (value is "Sling-Bundle-Resources").
+     */
+    public static final String BUNDLE_RESOURCE_ROOTS = "Sling-Bundle-Resources";
+
+}

Added: incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/BundleMapper.java
URL: http://svn.apache.org/viewvc/incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/BundleMapper.java?rev=608910&view=auto
==============================================================================
--- incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/BundleMapper.java (added)
+++ incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/BundleMapper.java Fri Jan  4 08:37:23 2008
@@ -0,0 +1,54 @@
+/*
+ * 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.ocm.impl;
+
+import java.util.Map;
+
+import org.apache.jackrabbit.ocm.mapper.Mapper;
+import org.apache.jackrabbit.ocm.mapper.model.ClassDescriptor;
+import org.apache.jackrabbit.ocm.mapper.model.MappingDescriptor;
+
+public class BundleMapper implements Mapper {
+
+    private MappingDescriptor mappingDescriptor;
+
+    BundleMapper(MappingDescriptor mappingDescriptor) {
+        this.mappingDescriptor = mappingDescriptor;
+    }
+
+    public ClassDescriptor getClassDescriptorByClass(Class clazz) {
+        return this.mappingDescriptor.getClassDescriptorByName(clazz.getName());
+    }
+
+    public ClassDescriptor getClassDescriptorByNodeType(String jcrNodeType) {
+        return this.mappingDescriptor.getClassDescriptorByNodeType(jcrNodeType);
+    }
+
+    String[] getMappedClasses() {
+        return this.toStringArray(this.mappingDescriptor.getClassDescriptorsByClassName());
+    }
+
+    String[] getMappedNodeTypes() {
+        return this.toStringArray(this.mappingDescriptor.getClassDescriptorsByNodeType());
+    }
+
+    private String[] toStringArray(Map map) {
+        return (String[]) map.keySet().toArray(new String[map.size()]);
+    }
+}

Added: incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/ClassDescriptorReader.java
URL: http://svn.apache.org/viewvc/incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/ClassDescriptorReader.java?rev=608910&view=auto
==============================================================================
--- incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/ClassDescriptorReader.java (added)
+++ incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/ClassDescriptorReader.java Fri Jan  4 08:37:23 2008
@@ -0,0 +1,546 @@
+/*
+ * 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.ocm.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.jackrabbit.ocm.exception.JcrMappingException;
+import org.apache.jackrabbit.ocm.mapper.model.BeanDescriptor;
+import org.apache.jackrabbit.ocm.mapper.model.ClassDescriptor;
+import org.apache.jackrabbit.ocm.mapper.model.CollectionDescriptor;
+import org.apache.jackrabbit.ocm.mapper.model.FieldDescriptor;
+import org.apache.jackrabbit.ocm.mapper.model.ImplementDescriptor;
+import org.apache.jackrabbit.ocm.mapper.model.MappingDescriptor;
+import org.kxml2.io.KXmlParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+/**
+ * The <code>ClassDescriptorReader</code> TODO
+ *
+ * Use:
+ * 1. Instantiatate
+ * 2. Multiply call {@link #parse(InputStream)}
+ * 3. Call {@link #getMappingDescriptor()} (more than once always returns the same result)
+ * 4. Call {@link #reset()}  and go back to step 2
+ */
+public class ClassDescriptorReader {
+
+    /** default log */
+    private static final Logger log = LoggerFactory.getLogger(ClassDescriptorReader.class);
+
+    private static final int STATE_NULL = 0;
+    private static final int STATE_MAPPING = 2;
+    private static final int STATE_CLASS = 3;
+    private static final int STATE_DESCRIPTOR = 4;
+
+    private KXmlParser parser;
+
+    private int state = STATE_NULL;
+
+    private MappingDescriptor descriptors;
+    boolean verified;
+    private ClassDescriptor currentClassDescriptor;
+
+    public ClassDescriptorReader() {
+        this.parser = new KXmlParser();
+        this.reset();
+    }
+
+    public void reset() {
+        this.descriptors = new MappingDescriptor();
+        this.verified = false;
+    }
+
+    /**
+     * @throws IllegalStateException If no descriptors are available
+     * @throws XmlPullParserException If an error occurrs validating the descriptors
+     * @return The mapping descriptor.
+     */
+    public MappingDescriptor getMappingDescriptor() throws XmlPullParserException {
+        this.verify();
+        return this.descriptors;
+    }
+
+    public void parse(List<URL> urlList) throws IOException, XmlPullParserException {
+        for (URL url : urlList) {
+            InputStream ins = null;
+            try {
+                ins = url.openStream();
+                this.parser.setProperty("http://xmlpull.org/v1/doc/properties.html#location", url);
+                this.parse(ins);
+            } finally {
+                if (ins != null) {
+                    try {
+                        ins.close();
+                    } catch (IOException ignore) {
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     *
+     * @param ins
+     * @throws IOException
+     * @throws XmlPullParserException
+     * @throws IllegalStateException If the {@link #getMappingDescriptor()}
+     *      method has been called but not the {@link #reset()} method before
+     *      calling this method.
+     */
+    public void parse(InputStream ins) throws IOException, XmlPullParserException {
+
+        if (this.verified) {
+            throw new IllegalStateException("Please reset before parsing");
+        }
+
+        // set the parser input, use null encoding to force detection with <?xml?>
+        this.parser.setInput(ins, null);
+        this.state = STATE_NULL;
+
+        int eventType = this.parser.getEventType();
+        while (eventType != XmlPullParser.END_DOCUMENT) {
+            if (eventType == XmlPullParser.START_TAG) {
+                switch (this.state) {
+                    case STATE_NULL:
+                        if ("graffito-jcr".equals(this.parser.getName())) {
+                            // accept for backwards compatibility
+                            // might want to log this situation
+                        } else if (!"jackrabbit-ocm".equals(this.parser.getName())) {
+                            throw this.unexpectedElement();
+                        }
+                        this.descriptors.setPackage(this.getOptionalAttribute("package"));
+                        this.currentClassDescriptor = null;
+                        this.state = STATE_MAPPING;
+                        break;
+
+                    case STATE_MAPPING:
+                        if (!"class-descriptor".equals(this.parser.getName())) {
+                            throw this.unexpectedElement();
+                        }
+                        this.currentClassDescriptor = this.parseClassDescriptor();
+                        this.state = STATE_CLASS;
+                        break;
+
+                    case STATE_CLASS:
+                        if ("implement-descriptor".equals(this.parser.getName())) {
+                            this.currentClassDescriptor.addImplementDescriptor(this.parseImplementDescriptor());
+                        } else if ("field-descriptor".equals(this.parser.getName())) {
+                            this.currentClassDescriptor.addFieldDescriptor(this.parseFieldDescriptor());
+                        } else if ("bean-descriptor".equals(this.parser.getName())) {
+                            this.currentClassDescriptor.addBeanDescriptor(this.parseBeanDescriptor());
+                        } else if ("collection-descriptor".equals(this.parser.getName())) {
+                            this.currentClassDescriptor.addCollectionDescriptor(this.parseCollectionDescriptor());
+                        } else {
+                            throw this.unexpectedElement();
+                        }
+                        this.state = STATE_DESCRIPTOR;
+                        break;
+
+                    case STATE_DESCRIPTOR:
+                        // single descriptors are empty, fail
+                        throw this.unexpectedElement();
+
+                    default:
+                        // don't care
+                }
+
+            } else if (eventType == XmlPullParser.END_TAG) {
+                switch (this.state) {
+                    case STATE_NULL:
+                        // do not expected an end tag in this state...
+                        break;
+
+                    case STATE_MAPPING:
+                        if (!"graffito-jcr".equals(this.parser.getName())
+                            && !"jackrabbit-ocm".equals(this.parser.getName())) {
+                            throw this.unexpectedElement();
+                        }
+
+                        this.state = STATE_NULL;
+                        break;
+
+                    case STATE_CLASS:
+                        if (!"class-descriptor".equals(this.parser.getName())) {
+                            throw this.unexpectedElement();
+                        }
+
+                        this.descriptors.addClassDescriptor(this.currentClassDescriptor);
+
+                        this.state = STATE_MAPPING;
+                        break;
+
+                    case STATE_DESCRIPTOR:
+                        if (!"implement-descriptor".equals(this.parser.getName())
+                                && !"field-descriptor".equals(this.parser.getName())
+                                && !"bean-descriptor".equals(this.parser.getName())
+                                && ! "collection-descriptor".equals(this.parser.getName())) {
+                            throw this.unexpectedElement();
+                        }
+
+                        this.state = STATE_CLASS;
+                        break;
+
+                    default:
+                        // don't care
+                }
+            }
+
+            eventType = this.parser.next();
+        }
+    }
+
+    private ClassDescriptor parseClassDescriptor() throws XmlPullParserException {
+        ClassDescriptor fd = new ClassDescriptor();
+
+        /*
+         * className CDATA #REQUIRED
+         * jcrType CDATA #IMPLIED
+         * jcrSuperTypes CDATA #IMPLIED
+         * jcrMixinTypes CDATA #IMPLIED
+         * extend CDATA #IMPLIED
+         * abstract (true|false) "false"
+         * interface (true|false) "false"
+         * discriminator (true|false) "true"
+         */
+
+        fd.setClassName(this.getRequiredAttribute("className"));
+        fd.setJcrType(this.getOptionalAttribute("jcrType"));
+        fd.setJcrSuperTypes(this.getOptionalAttribute("jcrSuperTypes"));
+        fd.setJcrMixinTypes(this.getOptionalAttribute("jcrMixinTypes", (String[]) null));
+
+        fd.setExtend(this.getOptionalAttribute("extend"));
+
+        fd.setAbstract(this.getOptionalAttribute("abstract", false));
+        fd.setInterface(this.getOptionalAttribute("interface", false));
+        fd.setDiscriminator(this.getOptionalAttribute("discriminator", true));
+
+        return fd;
+    }
+
+    private ImplementDescriptor parseImplementDescriptor() throws XmlPullParserException {
+        ImplementDescriptor fd = new ImplementDescriptor();
+
+        /*
+         * interfaceName CDATA #REQUIRED
+         */
+
+        fd.setInterfaceName(this.getRequiredAttribute("interfaceName"));
+
+        return fd;
+    }
+
+    private FieldDescriptor parseFieldDescriptor() throws XmlPullParserException {
+        FieldDescriptor fd = new FieldDescriptor();
+
+        /*
+         *  fieldName CDATA #REQUIRED
+         *  jcrName CDATA #IMPLIED
+         *  id (true | false) "false"
+         *  path (true | false) "false"
+         *  jcrType (String | Date | Long | Double | Boolean | Binary) #IMPLIED
+         *  jcrAutoCreated (true | false) "false"
+         *  jcrMandatory (true | false) "false"
+         *  jcrOnParentVersion (COPY | VERSION | INITIALIZE | COMPUTE | IGNORE | ABORT) "COPY"
+         *  jcrProtected (true | false) "false"
+         *  jcrMultiple (true | false) "false"
+         */
+
+        fd.setFieldName(this.getRequiredAttribute("fieldName"));
+        fd.setJcrName(this.getOptionalAttribute("jcrName", fd.getFieldName()));
+
+        fd.setId(this.getOptionalAttribute("id", false));
+        fd.setPath(this.getOptionalAttribute("path", false));
+
+        fd.setJcrType(this.getOptionalAttribute("jcrType"));
+        fd.setJcrAutoCreated(this.getOptionalAttribute("jcrAutoCreated", false));
+        fd.setJcrMandatory(this.getOptionalAttribute("jcrMandatory", false));
+        fd.setJcrOnParentVersion(this.getOptionalAttribute("jcrOnParentVersion", "COPY"));
+        fd.setJcrProtected(this.getOptionalAttribute("jcrProtected", false));
+        fd.setJcrMultiple(this.getOptionalAttribute("jcrMultiple", false));
+        fd.setJcrDefaultValue(this.getOptionalAttribute("jcrDefaultValue"));
+
+        return fd;
+    }
+
+    private BeanDescriptor parseBeanDescriptor() throws XmlPullParserException {
+        BeanDescriptor fd = new BeanDescriptor();
+
+        /*
+         * fieldName CDATA #REQUIRED
+         * jcrName CDATA #IMPLIED
+         * proxy (true | false) "false"
+         * autoRetrieve (true|false) "true"
+         * autoUpdate (true|false) "true"
+         * autoInsert (true|false) "true"
+         * converter CDATA #IMPLIED
+         * jcrType CDATA #IMPLIED
+         * jcrAutoCreated (true | false) "false"
+         * jcrMandatory (true | false) "false"
+         * jcrOnParentVersion (COPY | VERSION | INITIALIZE | COMPUTE | IGNORE | ABORT) "COPY"
+         * jcrProtected (true | false) "false"
+         * jcrSameNameSiblings (true | false) "false"
+         */
+
+        fd.setFieldName(this.getRequiredAttribute("fieldName"));
+        fd.setJcrName(this.getOptionalAttribute("jcrName", fd.getFieldName()));
+        fd.setProxy(this.getOptionalAttribute("proxy", false));
+
+        fd.setAutoRetrieve(this.getOptionalAttribute("autoRetrieve", true));
+        fd.setAutoUpdate(this.getOptionalAttribute("autoUpdate", true));
+        fd.setAutoInsert(this.getOptionalAttribute("autoInsert", true));
+
+        fd.setJcrType(this.getOptionalAttribute("jcrType"));
+        fd.setJcrAutoCreated(this.getOptionalAttribute("jcrAutoCreated", false));
+        fd.setJcrMandatory(this.getOptionalAttribute("jcrMandatory", false));
+        fd.setJcrOnParentVersion(this.getOptionalAttribute("jcrOnParentVersion", "COPY"));
+        fd.setJcrProtected(this.getOptionalAttribute("jcrProtected", false));
+        fd.setJcrSameNameSiblings(this.getOptionalAttribute("jcrSameNameSiblings", false));
+
+        fd.setJcrMultiple(this.getOptionalAttribute("jcrMultiple", false));
+
+        return fd;
+    }
+
+    private CollectionDescriptor parseCollectionDescriptor() throws XmlPullParserException {
+        CollectionDescriptor fd = new CollectionDescriptor();
+
+        /*
+         * fieldName CDATA #REQUIRED
+         * jcrName CDATA #IMPLIED
+         * proxy (true | false) "false"
+         * autoRetrieve (true|false) "true"
+         * autoUpdate (true|false) "true"
+         * autoInsert (true|false) "true"
+         * elementClassName CDATA #REQUIRED
+         * collectionClassName CDATA #IMPLIED
+         * collectionConverter CDATA #IMPLIED
+         * jcrType CDATA #IMPLIED
+         * jcrAutoCreated (true | false) "false"
+         * jcrMandatory (true | false) "false"
+         * jcrOnParentVersion (COPY | VERSION | INITIALIZE | COMPUTE | IGNORE | ABORT) "COPY"
+         * jcrProtected (true | false) "false"
+         * jcrSameNameSiblings (true | false) "false"
+         */
+
+        fd.setFieldName(this.getRequiredAttribute("fieldName"));
+        fd.setJcrName(this.getOptionalAttribute("jcrName", fd.getFieldName()));
+        fd.setProxy(this.getOptionalAttribute("proxy", false));
+
+        fd.setAutoRetrieve(this.getOptionalAttribute("autoRetrieve", true));
+        fd.setAutoUpdate(this.getOptionalAttribute("autoUpdate", true));
+        fd.setAutoInsert(this.getOptionalAttribute("autoInsert", true));
+
+        fd.setElementClassName(this.getRequiredAttribute("elementClassName"));
+        fd.setCollectionClassName(this.getOptionalAttribute("collectionClassName"));
+        fd.setCollectionConverter(this.getOptionalAttribute("collectionConverter"));
+
+        fd.setJcrAutoCreated(this.getOptionalAttribute("jcrAutoCreated", false));
+        fd.setJcrMandatory(this.getOptionalAttribute("jcrMandatory", false));
+        fd.setJcrOnParentVersion(this.getOptionalAttribute("jcrOnParentVersion", "COPY"));
+        fd.setJcrProtected(this.getOptionalAttribute("jcrProtected", false));
+        fd.setJcrSameNameSiblings(this.getOptionalAttribute("jcrSameNameSiblings", false));
+
+        fd.setJcrType(this.getOptionalAttribute("jcrType"));
+        fd.setJcrMultiple(this.getOptionalAttribute("jcrMultiple", false));
+
+        return fd;
+    }
+
+    //---------- Attribute access helper --------------------------------------
+
+    private String getRequiredAttribute(String attrName) throws XmlPullParserException {
+        String attrVal = this.parser.getAttributeValue(null, attrName);
+        if (attrVal != null) {
+            return attrVal;
+        }
+
+        // fail if value is missing
+        throw this.missingAttribute(attrName);
+    }
+
+    private String getOptionalAttribute(String attrName) {
+        return this.getOptionalAttribute(attrName, (String) null);
+    }
+
+    private String getOptionalAttribute(String attrName, String defaultValue) {
+        String attrVal = this.parser.getAttributeValue(null, attrName);
+        return (attrVal != null) ? attrVal : defaultValue;
+    }
+
+    private String[] getOptionalAttribute(String attrName, String[] defaultValue) {
+        String attrVal = this.parser.getAttributeValue(null, attrName);
+        return (attrVal != null) ? attrVal.split(",") : defaultValue;
+    }
+
+    private boolean getOptionalAttribute(String attrName, boolean defaultValue) {
+        String attrVal = this.parser.getAttributeValue(null, attrName);
+        return (attrVal != null) ? "true".equalsIgnoreCase(attrVal) : defaultValue;
+    }
+
+    //---------- Error Handling support ---------------------------------------
+
+    private XmlPullParserException missingAttribute(String attrName) {
+        String message = "Missing Attribute " + attrName + " in element " + this.parser.getName();
+        return new XmlPullParserException(message, this.parser, null);
+    }
+
+    private XmlPullParserException unexpectedElement() {
+        String message = "Illegal Element " + this.parser.getName();
+        return new XmlPullParserException(message, this.parser, null);
+    }
+
+    //---------- Verification of the mapping descriptors ----------------------
+
+    private void verify() throws XmlPullParserException {
+        // nothing to do anymore
+        if (this.verified) {
+            return;
+        }
+
+        if (this.descriptors == null) {
+            throw new IllegalStateException("Nothing has been read yet");
+        }
+
+        List<String> errors = new ArrayList<String>();
+        List<ClassDescriptor> rootClassDescriptors = new ArrayList<ClassDescriptor>();
+        errors = this.solveReferences(errors, rootClassDescriptors);
+        errors = this.validateDescriptors(errors, rootClassDescriptors);
+
+        if (!errors.isEmpty()) {
+            throw new XmlPullParserException("Mapping files contain errors."
+                + this.getErrorMessage(errors));
+        }
+    }
+
+    private List<String> solveReferences(List<String> errors, List<ClassDescriptor> rootClassDescriptors) {
+        Set<ClassDescriptor> toRemove = new HashSet<ClassDescriptor>();
+        for( ClassDescriptor cd : (Collection<ClassDescriptor>)this.descriptors.getClassDescriptorsByClassName().values() ) {
+
+            if (null != cd.getExtend() && !"".equals(cd.getExtend())) {
+                ClassDescriptor superClassDescriptor = this.descriptors.getClassDescriptorByName(cd.getExtend());
+
+                if (superClassDescriptor == null) {
+                    log.warn("Dropping class {}: Base class {} not registered", cd.getClassName(), cd.getExtend());
+                    toRemove.add(cd);
+//                    errors.add("Cannot find mapping for class "
+//                        + cd.getExtend() + " referenced as extends from "
+//                        + cd.getClassName());
+                } else {
+                    log.debug("Class {} extends {}", cd.getClassName(), cd.getExtend());
+                    cd.setSuperClassDescriptor(superClassDescriptor);
+                }
+            } else {
+                log.debug("Class {} is a root class", cd.getClassName());
+                rootClassDescriptors.add(cd);
+            }
+
+            @SuppressWarnings("unchecked")
+            Collection<String> interfaces = cd.getImplements();
+            for (String interfaceName : interfaces) {
+                ClassDescriptor interfaceClassDescriptor = this.descriptors.getClassDescriptorByName(interfaceName);
+
+                if (interfaceClassDescriptor == null) {
+                    log.warn("Dropping class {}: Interface class {} not registered", cd.getClassName(), interfaceName);
+                    toRemove.add(cd);
+//                        errors.add("Cannot find mapping for interface "
+//                            + interfaceName + " referenced as implements from "
+//                            + cd.getClassName());
+                } else {
+                    log.debug("Class " + cd.getClassName() + " implements "
+                        + interfaceName);
+                    //cd.setSuperClassDescriptor(interfaceClassDescriptor);
+                    interfaceClassDescriptor.addDescendantClassDescriptor(cd);
+                }
+
+            }
+
+        }
+
+        if (!toRemove.isEmpty()) {
+            log.info("Removing dropped classes from map");
+            for (ClassDescriptor cd : toRemove) {
+                this.dropClassDescriptor(cd);
+            }
+        }
+        return errors;
+    }
+
+    private void dropClassDescriptor(ClassDescriptor cd) {
+        // remove descriptor
+        this.descriptors.getClassDescriptorsByClassName().remove(cd.getClassName());
+        this.descriptors.getClassDescriptorsByNodeType().remove(cd.getJcrType());
+
+        if (cd.hasDescendants()) {
+            for( ClassDescriptor desc : (Collection<ClassDescriptor>)cd.getDescendantClassDescriptors()) {
+                log.warn("Dropping class {}: Depends on non-resolvable class {}", desc.getClassName(), cd.getClassName());
+                this.dropClassDescriptor(desc);
+            }
+        }
+    }
+
+    /**
+     * Validate all class descriptors.
+     * This method validates the toplevel ancestors and after the descendants.
+     * Otherwise, we can have invalid settings in the class descriptors
+     * @param errors all errors found during the validation process
+     * @param classDescriptors the ancestor classdescriptors
+     * @return
+     */
+    private List<String> validateDescriptors(List<String> errors, Collection<ClassDescriptor> classDescriptors) {
+        for (ClassDescriptor classDescriptor : classDescriptors) {
+            try {
+                classDescriptor.afterPropertiesSet();
+                if (classDescriptor.hasDescendants()) {
+                    errors = this.validateDescriptors(errors,
+                        classDescriptor.getDescendantClassDescriptors());
+                }
+            } catch (JcrMappingException jme) {
+                // TODO: consider dropping the descriptor due to errors ...
+                log.warn("Mapping of class " + classDescriptor.getClassName()
+                    + " is invalid", jme);
+                errors.add(jme.getMessage());
+            }
+        }
+        return errors;
+    }
+
+
+    private String getErrorMessage(List<String> errors) {
+        final String lineSep = System.getProperty("line.separator");
+        StringBuffer buf = new StringBuffer();
+        for(String msg : errors) {
+            buf.append(lineSep).append(msg);
+        }
+
+        return buf.toString();
+    }
+
+
+}

Added: incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/ObjectContentManagerFactory.java
URL: http://svn.apache.org/viewvc/incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/ObjectContentManagerFactory.java?rev=608910&view=auto
==============================================================================
--- incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/ObjectContentManagerFactory.java (added)
+++ incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/ObjectContentManagerFactory.java Fri Jan  4 08:37:23 2008
@@ -0,0 +1,363 @@
+/*
+ * 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.ocm.impl;
+
+import static org.apache.sling.jcr.ocm.OcmConstants.EVENT_MAPPING_ADDED;
+import static org.apache.sling.jcr.ocm.OcmConstants.EVENT_MAPPING_REMOVED;
+import static org.apache.sling.jcr.ocm.OcmConstants.MAPPER_BUNDLE_HEADER;
+import static org.apache.sling.jcr.ocm.OcmConstants.MAPPING_CLASS;
+import static org.apache.sling.jcr.ocm.OcmConstants.MAPPING_NODE_TYPE;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.ValueFactory;
+
+import org.apache.jackrabbit.ocm.manager.ObjectContentManager;
+import org.apache.jackrabbit.ocm.manager.atomictypeconverter.AtomicTypeConverterProvider;
+import org.apache.jackrabbit.ocm.manager.cache.ObjectCache;
+import org.apache.jackrabbit.ocm.manager.impl.ObjectContentManagerImpl;
+import org.apache.jackrabbit.ocm.manager.objectconverter.ObjectConverter;
+import org.apache.jackrabbit.ocm.manager.objectconverter.impl.ObjectConverterImpl;
+import org.apache.jackrabbit.ocm.manager.objectconverter.impl.ProxyManagerImpl;
+import org.apache.jackrabbit.ocm.mapper.model.MappingDescriptor;
+import org.apache.jackrabbit.ocm.query.QueryManager;
+import org.apache.jackrabbit.ocm.query.impl.QueryManagerImpl;
+import org.apache.jackrabbit.ocm.reflection.ReflectionUtils;
+import org.apache.jackrabbit.value.ValueFactoryImpl;
+import org.apache.sling.jcr.ocm.impl.classloader.MapperClassLoader;
+import org.apache.sling.osgi.commons.OsgiUtil;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.SynchronousBundleListener;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xmlpull.v1.XmlPullParserException;
+
+/**
+ * The <code>ObjectContentManagerFactory</code> TODO
+ * 
+ * @scr.component metadata="no"
+ * @scr.property name="service.description"
+ *               value="Sling Object Content Manager Factory"
+ * @scr.property name="service.vendor" value="The Apache Software Foundation"
+ */
+public class ObjectContentManagerFactory implements SynchronousBundleListener {
+
+    /** default log */
+    private static final Logger log = LoggerFactory.getLogger(ObjectContentManagerFactory.class);
+
+    /** scr.reference cardinality="0..1" policy="dynamic" */
+    private EventAdmin eventAdmin;
+    
+    /**
+     * The class loader used by the Jackrabbit OCM ReflectionUtils class to load
+     * classes for mapping. The class loader is set on the ReflectionUtils
+     * before the new mappings are loaded.
+     *
+     * @see #loadMappings()
+     */
+    private MapperClassLoader mapperClassLoader;
+
+    private BundleMapper mapper;
+
+    private ClassDescriptorReader descriptorReader;
+
+    private AtomicTypeConverterProvider converterProvider;
+    
+    private OcmAdapterFactory adapterFactory;
+
+    public ObjectContentManagerFactory() {
+
+        // prepare the data converters and query manager
+        this.converterProvider = new SlingAtomicTypeConverterProvider();
+    }
+
+    public ObjectContentManager getObjectContentManager(Session session) {
+
+        ValueFactory valueFactory;
+        try {
+            valueFactory = session.getValueFactory();
+        } catch (RepositoryException re) {
+            log.info(
+                "getObjectContentManager: Cannot get ValueFactory from Session ("
+                    + session.getUserID() + "), using default factory", re);
+            valueFactory = ValueFactoryImpl.getInstance();
+        }
+
+        ObjectCache objectCache = new ObservingObjectCache(session);
+        
+        QueryManager queryManager = new QueryManagerImpl(mapper,
+            converterProvider.getAtomicTypeConverters(), valueFactory);
+        
+        ObjectConverter objectConverter = new ObjectConverterImpl(mapper,
+            converterProvider, new ProxyManagerImpl(), objectCache);
+
+        return new ObjectContentManagerImpl(mapper, objectConverter,
+            queryManager, objectCache, session);
+    }
+
+    private ClassDescriptorReader getDescriptorReader() {
+        if (descriptorReader == null) {
+            ClassDescriptorReader ddr = new ClassDescriptorReader();
+            // ddr.setResolver(null /* TODO resolve URL :
+            // graffito-jcr-mapping.dtd */);
+            // ddr.setValidating(false);
+            descriptorReader = ddr;
+        } else {
+            descriptorReader.reset();
+        }
+
+        return descriptorReader;
+    }
+
+    // TODO: New Implementation --------------------------------------
+
+    private List<Bundle> bundles = new ArrayList<Bundle>();
+
+    /**
+     * Loads the components of the given bundle. If the bundle has no
+     * <i>Service-Component</i> header, this method has no effect. The
+     * fragments of a bundle are not checked for the header (112.4.1).
+     * <p>
+     * This method calls the {@link #getBundleContext(Bundle)} method to find
+     * the <code>BundleContext</code> of the bundle. If the context cannot be
+     * found, this method does not load components for the bundle.
+     */
+    private synchronized void addBundle(Bundle bundle) {
+        // ignore bundle without mappings
+        if (bundle.getHeaders().get(MAPPER_BUNDLE_HEADER) == null) {
+            return;
+        }
+
+        if (bundles.contains(bundle)) {
+            // ignore existing bundle
+            return;
+        }
+
+        bundles.add(bundle);
+
+        loadMappings();
+
+        // fire mapping event
+        fireEvent(bundle, EVENT_MAPPING_ADDED);
+    }
+
+    private synchronized void removeBundle(Bundle bundle) {
+        if (!bundles.remove(bundle)) {
+            // bundle not known
+            return;
+        }
+
+        loadMappings();
+
+        // fire mapping event
+        fireEvent(bundle, EVENT_MAPPING_REMOVED);
+    }
+
+    private void loadMappings() {
+        MapperClassLoader newMapperClassLoader = new MapperClassLoader();
+        ReflectionUtils.setClassLoader(newMapperClassLoader);
+
+        ArrayList<URL> urlList = new ArrayList<URL>();
+        for (Iterator<Bundle> bi = bundles.iterator(); bi.hasNext();) {
+            Bundle bundle = bi.next();
+
+            String mapperHeader = (String) bundle.getHeaders().get(
+                MAPPER_BUNDLE_HEADER);
+            if (mapperHeader == null) {
+                // no components in the bundle, abandon
+                log.debug("registerMapperClient: Bundle {} has no mappings",
+                    bundle.getSymbolicName());
+                continue;
+            }
+
+            newMapperClassLoader.registerBundle(bundle);
+
+            StringTokenizer tokener = new StringTokenizer(mapperHeader, ",");
+            while (tokener.hasMoreTokens()) {
+                String mapping = tokener.nextToken().trim();
+                URL mappingURL = bundle.getResource(mapping);
+                if (mappingURL == null) {
+                    log.warn("Mapping {} not found in bundle {}", mapping,
+                        bundle.getSymbolicName());
+                } else {
+                    urlList.add(mappingURL);
+                }
+            }
+        }
+
+        // nothing to do if there are not streams
+        if (urlList.isEmpty()) {
+            return;
+        }
+
+        MappingDescriptor md;
+        try {
+            ClassDescriptorReader cdr = getDescriptorReader();
+            cdr.parse(urlList);
+            md = cdr.getMappingDescriptor();
+        } catch (XmlPullParserException xppe) {
+            log.error("Failed parsing descriptors", xppe);
+            return;
+        } catch (IOException ioe) {
+            log.error("Failed reading descriptors", ioe);
+            return;
+        }
+
+        BundleMapper newMapper = new BundleMapper(md);
+
+        // dispose off old class loader before using new loader
+        if (mapperClassLoader != null) {
+            // note: the mapperClassLoader is used by the Jackrabbit OCM
+            // ReflectionUtils class. This class has already been reset to
+            // use the new class loader, so we can dispose off the old
+            // class loader here safely
+            mapperClassLoader.dispose();
+        }
+
+        mapperClassLoader = newMapperClassLoader;
+        mapper = newMapper;
+        
+        // update adapters
+        if (adapterFactory != null) {
+            adapterFactory.updateAdapterClasses(mapper.getMappedClasses());
+        }
+    }
+
+    // ---------- BundleListener -----------------------------------------------
+
+    /**
+     * Loads and unloads any components provided by the bundle whose state
+     * changed. If the bundle has been started, the components are loaded. If
+     * the bundle is about to stop, the components are unloaded.
+     *
+     * @param event The <code>BundleEvent</code> representing the bundle state
+     *            change.
+     */
+    public void bundleChanged(BundleEvent event) {
+
+        //
+        // NOTE:
+        // This is synchronous - take care to not block the system !!
+        //
+
+        switch (event.getType()) {
+
+            case BundleEvent.STARTING: // STARTED:
+                // register mappings before the bundle gets activated
+                addBundle(event.getBundle());
+                break;
+
+            case BundleEvent.STOPPED:
+                // remove mappings after the bundle has stopped
+                removeBundle(event.getBundle());
+                break;
+
+        }
+    }
+
+    // ---------- EventAdmin Event Dispatching ---------------------------------
+
+    /**
+     * Fires an OSGi event through the EventAdmin service.
+     *
+     * @param sourceBundle The Bundle from which the event originates. This may
+     *            be <code>null</code> if there is no originating bundle.
+     * @param eventName The name of the event
+     * @param props Event properties. This must not be <code>null</code>.
+     * @throws NullPointerException if eventName or props is <code>null</code>.
+     */
+    public void fireEvent(Bundle sourceBundle, String eventName) {
+        
+        // check event admin service, return if not available
+        EventAdmin ea = eventAdmin;
+        BundleMapper mapper = this.mapper;
+        if (ea == null || mapper == null) {
+            return;
+        }
+
+        // only fire, if there is a (new) mapper
+        Map<String, Object> props = new HashMap<String, Object>();
+        props.put(MAPPING_CLASS, mapper.getMappedClasses());
+        props.put(MAPPING_NODE_TYPE, mapper.getMappedNodeTypes());
+        
+        // create and fire the event
+        Event event = OsgiUtil.createEvent(sourceBundle, null, eventName, props);
+        ea.postEvent(event);
+    }
+
+    // ---------- SCR Integration ---------------------------------------------
+
+    /** Activates this component, called by SCR before registering as a service */
+    protected void activate(ComponentContext componentContext) {
+
+        componentContext.getBundleContext().addBundleListener(this);
+
+        try {
+            Bundle[] bundles = componentContext.getBundleContext().getBundles();
+            for (Bundle bundle : bundles) {
+                if (bundle.getState() == Bundle.ACTIVE) {
+                    // register active bundles with the mapper client
+                    addBundle(bundle);
+                }
+            }
+        } catch (Throwable t) {
+            log.error("activate: Problem while loading initial content and"
+                + " registering mappings for existing bundles", t);
+        }
+
+        // register the OcmAdapterFactory
+        String[] mappedClasses = (mapper != null)
+                ? mapper.getMappedClasses()
+                : new String[0];
+        adapterFactory = new OcmAdapterFactory(
+            componentContext.getBundleContext(), mappedClasses);
+    }
+
+    /** Deativates this component, called by SCR to take out of service */
+    protected void deactivate(ComponentContext componentContext) {
+        if (adapterFactory != null) {
+            adapterFactory.dispose();
+            adapterFactory = null;
+        }
+        
+        componentContext.getBundleContext().removeBundleListener(this);
+
+        synchronized (this) {
+            if (mapperClassLoader != null) {
+                mapperClassLoader.dispose();
+                mapperClassLoader = null;
+            }
+        }
+    }
+
+}

Added: incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/ObservingObjectCache.java
URL: http://svn.apache.org/viewvc/incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/ObservingObjectCache.java?rev=608910&view=auto
==============================================================================
--- incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/ObservingObjectCache.java (added)
+++ incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/ObservingObjectCache.java Fri Jan  4 08:37:23 2008
@@ -0,0 +1,60 @@
+/*
+ * 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.ocm.impl;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
+import javax.jcr.observation.EventListener;
+
+import org.apache.jackrabbit.ocm.manager.cache.impl.RequestObjectCacheImpl;
+
+/**
+ * The <code>ObservingObjectCache</code> TODO
+ */
+public class ObservingObjectCache extends RequestObjectCacheImpl implements
+        EventListener {
+
+    private boolean unregistered;
+
+    ObservingObjectCache(Session session) {
+        try {
+            session.getWorkspace().getObservationManager().addEventListener(
+                this,
+                Event.NODE_ADDED | Event.NODE_REMOVED | Event.PROPERTY_ADDED
+                    | Event.PROPERTY_CHANGED | Event.PROPERTY_REMOVED, "/",
+                true, null, null, false);
+            this.unregistered = false;
+        } catch (RepositoryException re) {
+            // TODO: log
+            this.unregistered = true;
+        }
+    }
+
+    public void onEvent(EventIterator eventiterator) {
+        super.clear();
+    }
+
+    public void clear() {
+        if (this.unregistered) {
+            super.clear();
+        }
+    }
+}

Added: incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/OcmAdapterFactory.java
URL: http://svn.apache.org/viewvc/incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/OcmAdapterFactory.java?rev=608910&view=auto
==============================================================================
--- incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/OcmAdapterFactory.java (added)
+++ incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/OcmAdapterFactory.java Fri Jan  4 08:37:23 2008
@@ -0,0 +1,68 @@
+/*
+ * 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.ocm.impl;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.osgi.commons.AdapterFactory;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+
+class OcmAdapterFactory implements AdapterFactory {
+
+    private Dictionary<String, Object> registrationProperties;
+    
+    private ServiceRegistration registration;
+    
+    OcmAdapterFactory(BundleContext bundleContext, String[] mappedClasses) {
+        
+        registrationProperties = new Hashtable<String, Object>();
+        registrationProperties.put(ADAPTABLE_CLASSES, Resource.class.getName());
+        registrationProperties.put(ADAPTER_CLASSES, mappedClasses);
+        registrationProperties.put(Constants.SERVICE_DESCRIPTION, "Sling OCM Adapter Factory");
+        registrationProperties.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
+        
+        registration = bundleContext.registerService(SERVICE_NAME, this, registrationProperties);
+    }
+    
+    void updateAdapterClasses(String[] mappedClasses) {
+        // set the new set of mapped classes
+        registrationProperties.put(ADAPTER_CLASSES, mappedClasses);
+        
+        // update the registration to have the factory registry updated
+        registration.setProperties(registrationProperties);
+    }
+    
+    void dispose() {
+        if (registration != null) {
+            registration.unregister();
+            registration = null;
+        }
+    }
+    
+    public <AdapterType> AdapterType getAdapter(Object adaptable,
+            Class<AdapterType> type) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+}

Added: incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/SlingAtomicTypeConverterProvider.java
URL: http://svn.apache.org/viewvc/incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/SlingAtomicTypeConverterProvider.java?rev=608910&view=auto
==============================================================================
--- incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/SlingAtomicTypeConverterProvider.java (added)
+++ incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/SlingAtomicTypeConverterProvider.java Fri Jan  4 08:37:23 2008
@@ -0,0 +1,45 @@
+/*
+ * 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.ocm.impl;
+
+import java.util.Map;
+
+import javax.jcr.Value;
+
+import org.apache.jackrabbit.ocm.manager.atomictypeconverter.impl.DefaultAtomicTypeConverterProvider;
+import org.apache.jackrabbit.ocm.manager.atomictypeconverter.impl.UndefinedTypeConverterImpl;
+
+/**
+ * The <code>SlingAtomicTypeConverterProvider</code> TODO
+ */
+public class SlingAtomicTypeConverterProvider extends
+        DefaultAtomicTypeConverterProvider {
+
+    protected Map registerDefaultAtomicTypeConverters() {
+        Map converters = super.registerDefaultAtomicTypeConverters();
+
+        // add undefined type converter for Object class (not entirely correct but ok)
+        converters.put(Object.class, UndefinedTypeConverterImpl.class);
+
+        // Value type converter for JCR Values
+        converters.put(Value.class, ValueTypeConverterImpl.class);
+
+        return converters;
+    }
+}

Added: incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/ValueTypeConverterImpl.java
URL: http://svn.apache.org/viewvc/incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/ValueTypeConverterImpl.java?rev=608910&view=auto
==============================================================================
--- incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/ValueTypeConverterImpl.java (added)
+++ incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/ValueTypeConverterImpl.java Fri Jan  4 08:37:23 2008
@@ -0,0 +1,60 @@
+/*
+ * 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.ocm.impl;
+
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+
+import org.apache.jackrabbit.ocm.manager.atomictypeconverter.AtomicTypeConverter;
+
+/**
+ * JCR Value Type Converter
+ */
+public class ValueTypeConverterImpl implements AtomicTypeConverter
+{
+    /*
+     * (non-Javadoc)
+     * @see org.apache.jackrabbit.ocm.manager.atomictypeconverter.AtomicTypeConverter#getValue(javax.jcr.ValueFactory, java.lang.Object)
+     */
+    public Value getValue(ValueFactory valueFactory, Object propValue)
+    {
+        if (propValue == null)
+        {
+            return null;
+        }
+        return (Value) propValue;
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.jackrabbit.ocm.manager.atomictypeconverter.AtomicTypeConverter#getObject(javax.jcr.Value)
+     */
+    public Object getObject(Value value)
+    {
+        return value;
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.jackrabbit.ocm.manager.atomictypeconverter.AtomicTypeConverter#getXPathQueryValue(javax.jcr.ValueFactory, java.lang.Object)
+     */
+    public String getXPathQueryValue(ValueFactory valueFactory, Object object) {
+        return "'" + object.toString() + "'";
+    }
+}

Added: incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/classloader/BundleLoader.java
URL: http://svn.apache.org/viewvc/incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/classloader/BundleLoader.java?rev=608910&view=auto
==============================================================================
--- incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/classloader/BundleLoader.java (added)
+++ incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/classloader/BundleLoader.java Fri Jan  4 08:37:23 2008
@@ -0,0 +1,61 @@
+/*
+ * 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.ocm.impl.classloader;
+
+import org.osgi.framework.Bundle;
+
+
+/**
+ * The <code>ClassLoaderLoader</code> TODO
+ */
+public class BundleLoader implements Loader {
+
+    private Bundle bundle;
+
+    BundleLoader(Bundle bundle) {
+        this.bundle = bundle;
+    }
+
+    /**
+     * @see org.apache.sling.jcr.resource.internal.mapping.classloader.Loader#loadClass(java.lang.String)
+     */
+    public Class loadClass(String name) throws ClassNotFoundException {
+        try {
+            // to prevent nasty messages, we check for the class resource
+            // before actually accessing the class
+            String resource = name.replace('.', '/') + ".class";
+            if (this.bundle.getResource(resource) != null) {
+                return this.bundle.loadClass(name);
+            }
+
+            // fail if the bundle does not have the resource
+            throw new ClassNotFoundException(name);
+        } catch (IllegalStateException ise) {
+            // TODO: log
+            throw new ClassNotFoundException(name, ise);
+        }
+    }
+
+    /**
+     * @see org.apache.sling.jcr.resource.internal.mapping.classloader.Loader#getLoader()
+     */
+    public Object getLoader() {
+        return this.bundle;
+    }
+}

Added: incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/classloader/ClassLoaderLoader.java
URL: http://svn.apache.org/viewvc/incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/classloader/ClassLoaderLoader.java?rev=608910&view=auto
==============================================================================
--- incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/classloader/ClassLoaderLoader.java (added)
+++ incubator/sling/whiteboard/fmeschbe/resource/jcr/ocm/src/main/java/org/apache/sling/jcr/ocm/impl/classloader/ClassLoaderLoader.java Fri Jan  4 08:37:23 2008
@@ -0,0 +1,45 @@
+/*
+ * 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.ocm.impl.classloader;
+
+/**
+ * The <code>ClassLoaderLoader</code> TODO
+ */
+public class ClassLoaderLoader implements Loader {
+
+    private ClassLoader classLoader;
+
+    ClassLoaderLoader(ClassLoader classLoader) {
+        this.classLoader = classLoader;
+    }
+
+    /**
+     * @see org.apache.sling.jcr.resource.internal.mapping.classloader.Loader#loadClass(java.lang.String)
+     */
+    public Class loadClass(String name) throws ClassNotFoundException {
+        return this.classLoader.loadClass(name);
+    }
+
+    /**
+     * @see org.apache.sling.jcr.resource.internal.mapping.classloader.Loader#getLoader()
+     */
+    public Object getLoader() {
+        return this.classLoader;
+    }
+}