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;
+ }
+}