You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2006/08/15 09:09:08 UTC
svn commit: r431546 - in /jackrabbit/trunk/jcr-server:
server/src/java/org/apache/jackrabbit/server/io/
server/src/java/org/apache/jackrabbit/webdav/simple/
webapp/src/webapp/WEB-INF/
Author: angela
Date: Tue Aug 15 00:09:07 2006
New Revision: 431546
URL: http://svn.apache.org/viewvc?rev=431546&view=rev
Log:
Webdav Simple: Delegate PROPPATCH to (extended) IOHandlers
Added:
jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyExportContext.java (with props)
jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyHandler.java (with props)
jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyImportContext.java (with props)
jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyManager.java (with props)
jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyManagerImpl.java (with props)
Modified:
jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/DefaultHandler.java
jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/DirListingExportHandler.java
jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java
jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/ResourceConfig.java
jackrabbit/trunk/jcr-server/webapp/src/webapp/WEB-INF/config.xml
Modified: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/DefaultHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/DefaultHandler.java?rev=431546&r1=431545&r2=431546&view=diff
==============================================================================
--- jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/DefaultHandler.java (original)
+++ jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/DefaultHandler.java Tue Aug 15 00:09:07 2006
@@ -17,7 +17,12 @@
package org.apache.jackrabbit.server.io;
import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.util.ISO9075;
+import org.apache.jackrabbit.util.Text;
import org.apache.jackrabbit.webdav.DavResource;
+import org.apache.jackrabbit.webdav.xml.Namespace;
+import org.apache.jackrabbit.webdav.property.DavPropertyName;
+import org.apache.jackrabbit.webdav.property.DavProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -26,10 +31,19 @@
import javax.jcr.NodeIterator;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
+import javax.jcr.PropertyIterator;
+import javax.jcr.Session;
+import javax.jcr.NamespaceException;
+import javax.jcr.NamespaceRegistry;
+import javax.jcr.nodetype.PropertyDefinition;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Date;
+import java.util.Map;
+import java.util.List;
+import java.util.HashMap;
+import java.util.Iterator;
/**
* <code>DefaultHandler</code> implements a simple IOHandler that creates 'file'
@@ -53,13 +67,15 @@
* Subclasses therefore should provide their own {@link #importData(ImportContext, boolean, Node)
* importData} method, that handles the data according their needs.
*/
-public class DefaultHandler implements IOHandler {
+public class DefaultHandler implements IOHandler, PropertyHandler {
private static Logger log = LoggerFactory.getLogger(DefaultHandler.class);
private String collectionNodetype = JcrConstants.NT_FOLDER;
private String defaultNodetype = JcrConstants.NT_FILE;
- private String contentNodetype = JcrConstants.NT_RESOURCE;
+ /* IMPORTANT NOTE: for webDAV compliancy the default nodetype of the content
+ node has been changed from nt:resource to nt:unstructured. */
+ private String contentNodetype = JcrConstants.NT_UNSTRUCTURED;
private IOManager ioManager;
@@ -97,7 +113,7 @@
*/
public DefaultHandler(IOManager ioManager, String collectionNodetype, String defaultNodetype, String contentNodetype) {
this.ioManager = ioManager;
-
+
this.collectionNodetype = collectionNodetype;
this.defaultNodetype = defaultNodetype;
this.contentNodetype = contentNodetype;
@@ -406,7 +422,8 @@
try {
// only non-collections: 'jcr:created' is present on the parent 'fileNode' only
if (!isCollection && contentNode.getDepth() > 0 && contentNode.getParent().hasProperty(JcrConstants.JCR_CREATED)) {
- context.setCreationTime(contentNode.getParent().getProperty(JcrConstants.JCR_CREATED).getValue().getLong());
+ long cTime = contentNode.getParent().getProperty(JcrConstants.JCR_CREATED).getValue().getLong();
+ context.setCreationTime(cTime);
}
long length = IOUtil.UNDEFINED_LENGTH;
@@ -444,6 +461,7 @@
}
} catch (RepositoryException e) {
// should never occur
+ log.error("Unexpected error {0} while exporting properties: {1}", e.getClass().getName(), e.getMessage());
throw new IOException(e.getMessage());
}
}
@@ -494,5 +512,194 @@
*/
protected String getContentNodeType() {
return contentNodetype;
+ }
+
+ //----------------------------------------------------< PropertyHandler >---
+
+ public boolean canExport(PropertyExportContext context, boolean isCollection) {
+ return canExport((ExportContext) context, isCollection);
+ }
+
+ public boolean exportProperties(PropertyExportContext exportContext, boolean isCollection) throws RepositoryException {
+ if (!canExport(exportContext, isCollection)) {
+ throw new RepositoryException("PropertyHandler " + getName() + " failed to export properties.");
+ }
+
+ Node cn = getContentNode(exportContext, isCollection);
+ try {
+ // export the properties common with normal IO handling
+ exportProperties(exportContext, isCollection, cn);
+
+ // export all other properties as well
+ PropertyIterator it = cn.getProperties();
+ while (it.hasNext()) {
+ Property p = it.nextProperty();
+ String name = p.getName();
+ PropertyDefinition def = p.getDefinition();
+ if (def.isMultiple()) {
+ log.debug("Multivalued property '" + name + "' not added to webdav property set.");
+ continue;
+ }
+ if (JcrConstants.JCR_DATA.equals(name)
+ || JcrConstants.JCR_MIMETYPE.equals(name)
+ || JcrConstants.JCR_ENCODING.equals(name)
+ || JcrConstants.JCR_LASTMODIFIED.equals(name)) {
+ continue;
+ }
+
+ DavPropertyName davName = getDavName(name, p.getSession());
+ exportContext.setProperty(davName, p.getValue().getString());
+ }
+ return true;
+ } catch (IOException e) {
+ // should not occur (log output see 'exportProperties')
+ return false;
+ }
+ }
+
+ public boolean canImport(PropertyImportContext context, boolean isCollection) {
+ if (context == null || context.isCompleted()) {
+ return false;
+ }
+ Item contextItem = context.getImportRoot();
+ try {
+ return contextItem != null && contextItem.isNode() && (!isCollection || ((Node)contextItem).hasNode(JcrConstants.JCR_CONTENT));
+ } catch (RepositoryException e) {
+ log.error("Unexpected error: " + e.getMessage());
+ return false;
+ }
+ }
+
+ public Map importProperties(PropertyImportContext importContext, boolean isCollection) throws RepositoryException {
+ if (!canImport(importContext, isCollection)) {
+ throw new RepositoryException("PropertyHandler " + getName() + " failed import properties");
+ }
+
+ // loop over List and remember all properties and propertyNames
+ // that failed to be imported (set or remove).
+ Map failures = new HashMap();
+ List changeList = importContext.getChangeList();
+
+ // for collections the import-root is the target node where properties
+ // are altered. in contrast 'non-collections' are with the handler
+ // represented by 'file' nodes, that must have a jcr:content child
+ // node, which holds all properties except jcr:created.
+ // -> see canImport for the corresponding assertions
+ Node cn = (Node) importContext.getImportRoot();
+ if (!isCollection && cn.hasNode(JcrConstants.JCR_CONTENT)) {
+ cn = cn.getNode(JcrConstants.JCR_CONTENT);
+ }
+
+ if (changeList != null) {
+ Iterator it = changeList.iterator();
+ while (it.hasNext()) {
+ Object propEntry = it.next();
+ try {
+ if (propEntry instanceof DavPropertyName) {
+ // remove
+ DavPropertyName propName = (DavPropertyName)propEntry;
+ removeJcrProperty(propName, cn);
+ } else if (propEntry instanceof DavProperty) {
+ // add or modify property
+ DavProperty prop = (DavProperty)propEntry;
+ setJcrProperty(prop, cn);
+ } else {
+ // ignore any other entry in the change list
+ log.error("unknown object in change list: " + propEntry.getClass().getName());
+ }
+ } catch (RepositoryException e) {
+ failures.put(propEntry, e);
+ }
+ }
+ }
+ return failures;
+ }
+
+ //------------------------------------------------------------< private >---
+ /**
+ * Builds a webdav property name from the given jcrName. In case the jcrName
+ * contains a namespace prefix that would conflict with any of the predefined
+ * webdav namespaces a new prefix is assigned.<br>
+ * Please note, that the local part of the jcrName is checked for XML
+ * compatibility by calling {@link ISO9075#encode(String)}
+ *
+ * @param jcrName
+ * @param session
+ * @return a <code>DavPropertyName</code> for the given jcr name.
+ */
+ private DavPropertyName getDavName(String jcrName, Session session) throws RepositoryException {
+ // make sure the local name is xml compliant
+ String localName = ISO9075.encode(Text.getLocalName(jcrName));
+ String prefix = Text.getNamespacePrefix(jcrName);
+ String uri = session.getNamespaceURI(prefix);
+ Namespace namespace = Namespace.getNamespace(prefix, uri);
+ DavPropertyName name = DavPropertyName.create(localName, namespace);
+ return name;
+ }
+
+ /**
+ * Build jcr property name from dav property name. If the property name
+ * defines a namespace uri, that has not been registered yet, an attempt
+ * is made to register the uri with the prefix defined. Note, that no
+ * extra effort is made to generated a unique prefix.
+ *
+ * @param propName
+ * @return jcr name
+ * @throws RepositoryException
+ */
+ private String getJcrName(DavPropertyName propName, Session session) throws RepositoryException {
+ // remove any encoding necessary for xml compliance
+ String pName = ISO9075.decode(propName.getName());
+ Namespace propNamespace = propName.getNamespace();
+ if (!Namespace.EMPTY_NAMESPACE.equals(propNamespace)) {
+ String prefix;
+ String emptyPrefix = Namespace.EMPTY_NAMESPACE.getPrefix();
+ try {
+ // lookup 'prefix' in the session-ns-mappings / namespace-registry
+ prefix = session.getNamespacePrefix(propNamespace.getURI());
+ } catch (NamespaceException e) {
+ // namespace uri has not been registered yet
+ NamespaceRegistry nsReg = session.getWorkspace().getNamespaceRegistry();
+ prefix = propNamespace.getPrefix();
+ // avoid trouble with default namespace
+ if (emptyPrefix.equals(prefix)) {
+ prefix = "_pre" + nsReg.getPrefixes().length + 1;
+ }
+ // NOTE: will fail if prefix is already in use in the namespace registry
+ nsReg.registerNamespace(prefix, propNamespace.getURI());
+ }
+ if (prefix != null && !emptyPrefix.equals(prefix)) {
+ pName = prefix + ":" + pName;
+ }
+ }
+ return pName;
+ }
+
+
+ /**
+ * @param property
+ * @throws RepositoryException
+ */
+ private void setJcrProperty(DavProperty property, Node contentNode) throws RepositoryException {
+ // Retrieve the property value. Note, that a 'null' value is replaced
+ // by empty string, since setting a jcr property value to 'null'
+ // would be equivalent to its removal.
+ String value = "";
+ if (property.getValue() != null) {
+ value = property.getValue().toString();
+ }
+ contentNode.setProperty(getJcrName(property.getName(), contentNode.getSession()), value);
+ }
+
+ /**
+ * @param propertyName
+ * @throws RepositoryException
+ */
+ private void removeJcrProperty(DavPropertyName propertyName, Node contentNode) throws RepositoryException {
+ String jcrName = getJcrName(propertyName, contentNode.getSession());
+ if (contentNode.hasProperty(jcrName)) {
+ contentNode.getProperty(jcrName).remove();
+ }
+ // removal of non existing property succeeds
}
}
Modified: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/DirListingExportHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/DirListingExportHandler.java?rev=431546&r1=431545&r2=431546&view=diff
==============================================================================
--- jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/DirListingExportHandler.java (original)
+++ jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/DirListingExportHandler.java Tue Aug 15 00:09:07 2006
@@ -31,6 +31,7 @@
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Date;
+import java.util.Map;
/**
* <code>DirListingExportHandler</code> represents a simple export for collections:
@@ -38,7 +39,7 @@
* Note: If {@link #exportContent(ExportContext, boolean)} is called the view list
* child nodes only, without respecting their representation as <code>DavResource</code>s.
*/
-public class DirListingExportHandler implements IOHandler {
+public class DirListingExportHandler implements IOHandler, PropertyHandler {
private static Logger log = LoggerFactory.getLogger(DirListingExportHandler.class);
@@ -46,6 +47,12 @@
/**
* Creates a new <code>DirListingExportHandler</code>
+ */
+ public DirListingExportHandler() {
+ }
+
+ /**
+ * Creates a new <code>DirListingExportHandler</code>
*
* @param ioManager
*/
@@ -251,11 +258,42 @@
public void setIOManager(IOManager ioManager) {
this.ioManager = ioManager;
}
-
+
/**
* @see IOHandler#getName()
*/
public String getName() {
return "DirListing Export";
+ }
+
+ //----------------------------------------------------< PropertyHandler >---
+
+ public boolean canExport(PropertyExportContext context, boolean isCollection) {
+ return canExport((ExportContext)context, isCollection);
+ }
+
+ /**
+ * @see PropertyHandler#exportProperties(PropertyExportContext, boolean)
+ */
+ public boolean exportProperties(PropertyExportContext exportContext, boolean isCollection) throws RepositoryException {
+ if (!canExport(exportContext, isCollection)) {
+ throw new RepositoryException(getName() + ": Cannot export properties for context " + exportContext);
+ }
+ exportContext.setModificationTime(new Date().getTime());
+ exportContext.setContentType("text/html", "UTF-8");
+ exportContext.setETag("");
+ return true;
+ }
+
+ public boolean canImport(PropertyImportContext context, boolean isCollection) {
+ return false;
+ }
+
+ /**
+ * @see PropertyHandler#importProperties(PropertyImportContext, boolean)
+ */
+ public Map importProperties(PropertyImportContext importContext, boolean isCollection) throws RepositoryException {
+ // export facilities only -> throw
+ throw new RepositoryException(getName() + ": Cannot import properties.");
}
}
Added: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyExportContext.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyExportContext.java?rev=431546&view=auto
==============================================================================
--- jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyExportContext.java (added)
+++ jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyExportContext.java Tue Aug 15 00:09:07 2006
@@ -0,0 +1,26 @@
+/*
+ * 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.jackrabbit.server.io;
+
+/**
+ * <code>PropertyExportContext</code> represents a marker interface to distinguish
+ * the ExportContext (which is mainly used to export data and some fundamental
+ * properties) from a context that is used to export properties only.
+ */
+public interface PropertyExportContext extends ExportContext {
+
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyExportContext.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyExportContext.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyHandler.java?rev=431546&view=auto
==============================================================================
--- jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyHandler.java (added)
+++ jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyHandler.java Tue Aug 15 00:09:07 2006
@@ -0,0 +1,82 @@
+/*
+ * 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.jackrabbit.server.io;
+
+import javax.jcr.RepositoryException;
+import java.util.Map;
+
+/**
+ * <code>PropertyHandler</code> interface defines methods for importing and
+ * exporting resource properties.
+ */
+public interface PropertyHandler {
+
+ /**
+ * Returns true, if this handler can run a successful export based on the
+ * specified context.
+ *
+ * @param context
+ * @param isCollection
+ * @return true if this <code>PropertyHandler</code> is export properties
+ * given the specified parameters.
+ */
+ public boolean canExport(PropertyExportContext context, boolean isCollection);
+
+ /**
+ * Exports properties to the given context. Note that the export must
+ * be consistent with properties that might be exposed by content export
+ * such as defined by {@link IOHandler#exportContent(ExportContext, boolean)}.
+ *
+ * @param exportContext
+ * @param isCollection
+ * @return true if the export succeeded.
+ * @throws RepositoryException If an attempt is made to export properties
+ * even if {@link #canExport{PropertyExportContext, boolean)} returns false or if
+ * some other unrecoverable error occurs. Note, that
+ */
+ public boolean exportProperties(PropertyExportContext exportContext, boolean isCollection) throws RepositoryException;
+
+ /**
+ * Returns true, if this handler can run a property import based on the
+ * specified context.
+ *
+ * @param context
+ * @param isCollection
+ * @return true if this <code>PropertyHandler</code> can import properties
+ * given the specified parameters.
+ */
+ public boolean canImport(PropertyImportContext context, boolean isCollection);
+
+ /**
+ * Imports, modifies or removes properties according the the
+ * {@link PropertyImportContext#getChangeList() change list} available from
+ * the import context. Note, that according to JSR 170 setting a property
+ * value to <code>null</code> is equivalent to its removal.<p/>
+ * The return value of this method must be used to provided detailed
+ * information about any kind of failures.
+ *
+ * @param importContext
+ * @param isCollection
+ * @return Map listing those properties that failed to be updated. An empty
+ * map indicates a successful import for all properties listed in the context.
+ * @throws RepositoryException If {@link #canImport(PropertyImportContext, boolean)}
+ * returns false for the given parameters or if some other unrecoverable
+ * error occured. Note, that normal failure of a property update must be
+ * reported with the return value and should not result in an exception.
+ */
+ public Map importProperties(PropertyImportContext importContext, boolean isCollection) throws RepositoryException;
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyHandler.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyHandler.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyImportContext.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyImportContext.java?rev=431546&view=auto
==============================================================================
--- jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyImportContext.java (added)
+++ jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyImportContext.java Tue Aug 15 00:09:07 2006
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.server.io;
+
+import javax.jcr.Item;
+import java.util.List;
+
+/**
+ * <code>PropertyImportContext</code>...
+ */
+public interface PropertyImportContext extends IOContext {
+
+ /**
+ * Returns the import root for the properties to be altered. Note, that
+ * a particular implementation may still apply the modifications to
+ * child items at any depth as long as property import is consistent with
+ * the corresponding export.
+ *
+ * @return the import root of the resource to import.
+ */
+ public Item getImportRoot();
+
+ /**
+ * Returns a list of properties to be modified by a call to
+ * {@link PropertyHandler#importProperties(PropertyImportContext, boolean)}.
+ *
+ * @return list of properties to be modified
+ */
+ public List getChangeList();
+}
Propchange: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyImportContext.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyImportContext.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyManager.java?rev=431546&view=auto
==============================================================================
--- jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyManager.java (added)
+++ jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyManager.java Tue Aug 15 00:09:07 2006
@@ -0,0 +1,56 @@
+/*
+ * 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.jackrabbit.server.io;
+
+import javax.jcr.RepositoryException;
+import java.util.Map;
+
+/**
+ * <code>PropertyManager</code>...
+ */
+public interface PropertyManager {
+
+ /**
+ *
+ * @param exportContext
+ * @param isCollection
+ * @return
+ * @throws RepositoryException
+ */
+ public boolean exportProperties(PropertyExportContext exportContext, boolean isCollection) throws RepositoryException;
+
+ /**
+ *
+ * @param importContext
+ * @param isCollection
+ * @return
+ * @throws RepositoryException
+ */
+ public Map alterProperties(PropertyImportContext importContext, boolean isCollection) throws RepositoryException;
+
+ /**
+ *
+ * @param propertyHandler
+ */
+ public void addPropertyHandler(PropertyHandler propertyHandler);
+
+ /**
+ *
+ * @return
+ */
+ public PropertyHandler[] getPropertyHandlers();
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyManager.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyManagerImpl.java?rev=431546&view=auto
==============================================================================
--- jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyManagerImpl.java (added)
+++ jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyManagerImpl.java Tue Aug 15 00:09:07 2006
@@ -0,0 +1,116 @@
+/*
+ * 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.jackrabbit.server.io;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.RepositoryException;
+import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * <code>PropertyManagerImpl</code>...
+ */
+public class PropertyManagerImpl implements PropertyManager {
+
+ private static Logger log = LoggerFactory.getLogger(PropertyManagerImpl.class);
+
+ private static PropertyManager DEFAULT_MANAGER;
+
+ private final List propertyHandlers = new ArrayList();
+
+ /**
+ * Create a new <code>PropertyManagerImpl</code>.
+ * Note, that this manager does not define any <code>PropertyHandler</code>s by
+ * default. Use {@link #addPropertyHandler(PropertyHandler)} in order to populate the
+ * internal list of handlers that are called for <code>importProperties</code> and
+ * <code>exportProperties</code> respectively. See {@link #getDefaultManager()}
+ * for an instance of this class populated with default handlers.
+ */
+ public PropertyManagerImpl() {
+ }
+
+ /**
+ * @see PropertyManager#exportProperties(PropertyExportContext, boolean)
+ */
+ public boolean exportProperties(PropertyExportContext context, boolean isCollection) throws RepositoryException {
+ boolean success = false;
+ PropertyHandler[] propertyHandlers = getPropertyHandlers();
+ for (int i = 0; i < propertyHandlers.length && !success; i++) {
+ PropertyHandler ph = propertyHandlers[i];
+ if (ph.canExport(context, isCollection)) {
+ success = ph.exportProperties(context, isCollection);
+ }
+ }
+ context.informCompleted(success);
+ return success;
+ }
+
+ /**
+ * @see PropertyManager#alterProperties(PropertyImportContext, boolean)
+ */
+ public Map alterProperties(PropertyImportContext context, boolean isCollection) throws RepositoryException {
+ boolean foundHandler = false;
+ Map failures = new HashMap(0);
+ PropertyHandler[] propertyHandlers = getPropertyHandlers();
+ for (int i = 0; i < propertyHandlers.length && !foundHandler; i++) {
+ PropertyHandler ph = propertyHandlers[i];
+ if ((foundHandler = ph.canImport(context, isCollection))) {
+ failures = ph.importProperties(context, isCollection);
+ }
+ }
+ if (!foundHandler) {
+ throw new RepositoryException("Unable to alter properties: No matching handler found.");
+ }
+ context.informCompleted(failures.isEmpty());
+ return failures;
+ }
+
+ /**
+ * @see PropertyManager#addPropertyHandler(PropertyHandler)
+ */
+ public void addPropertyHandler(PropertyHandler propertyHandler) {
+ if (propertyHandler == null) {
+ throw new IllegalArgumentException("'null' is not a valid IOHandler.");
+ }
+ propertyHandlers.add(propertyHandler);
+ }
+
+ /**
+ * @see PropertyManager#getPropertyHandlers()
+ */
+ public PropertyHandler[] getPropertyHandlers() {
+ return (PropertyHandler[]) propertyHandlers.toArray(new PropertyHandler[propertyHandlers.size()]);
+ }
+
+ /**
+ * @return an instance of PropertyManager populated with default handlers.
+ */
+ public static PropertyManager getDefaultManager() {
+ if (DEFAULT_MANAGER == null) {
+ DEFAULT_MANAGER = new PropertyManagerImpl();
+ DEFAULT_MANAGER.addPropertyHandler(new ZipHandler());
+ DEFAULT_MANAGER.addPropertyHandler(new XmlHandler());
+ DEFAULT_MANAGER.addPropertyHandler(new DirListingExportHandler());
+ DEFAULT_MANAGER.addPropertyHandler(new DefaultHandler());
+ }
+ return DEFAULT_MANAGER;
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyManagerImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/server/io/PropertyManagerImpl.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Modified: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java?rev=431546&r1=431545&r2=431546&view=diff
==============================================================================
--- jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java (original)
+++ jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java Tue Aug 15 00:09:07 2006
@@ -17,14 +17,18 @@
package org.apache.jackrabbit.webdav.simple;
import org.apache.jackrabbit.JcrConstants;
-import org.apache.jackrabbit.server.io.AbstractExportContext;
import org.apache.jackrabbit.server.io.ExportContext;
import org.apache.jackrabbit.server.io.ExportContextImpl;
import org.apache.jackrabbit.server.io.IOManager;
import org.apache.jackrabbit.server.io.IOUtil;
import org.apache.jackrabbit.server.io.ImportContext;
import org.apache.jackrabbit.server.io.ImportContextImpl;
-import org.apache.jackrabbit.util.ISO9075;
+import org.apache.jackrabbit.server.io.PropertyManager;
+import org.apache.jackrabbit.server.io.PropertyImportContext;
+import org.apache.jackrabbit.server.io.IOListener;
+import org.apache.jackrabbit.server.io.PropertyExportContext;
+import org.apache.jackrabbit.server.io.AbstractExportContext;
+import org.apache.jackrabbit.server.io.DefaultIOListener;
import org.apache.jackrabbit.util.Text;
import org.apache.jackrabbit.webdav.DavConstants;
import org.apache.jackrabbit.webdav.DavException;
@@ -57,22 +61,16 @@
import org.apache.jackrabbit.webdav.property.DefaultDavProperty;
import org.apache.jackrabbit.webdav.property.ResourceType;
import org.apache.jackrabbit.webdav.property.DavPropertyNameIterator;
-import org.apache.jackrabbit.webdav.xml.Namespace;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jcr.Item;
-import javax.jcr.NamespaceException;
-import javax.jcr.NamespaceRegistry;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
-import javax.jcr.Property;
-import javax.jcr.PropertyIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.lock.Lock;
-import javax.jcr.nodetype.PropertyDefinition;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
@@ -80,6 +78,8 @@
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.Collections;
/**
* DavResourceImpl implements a DavResource.
@@ -110,6 +110,7 @@
private ItemFilter filter;
private IOManager ioManager;
+ private PropertyManager propManager;
private long modificationTime = IOUtil.UNDEFINED_TIME;
@@ -128,6 +129,7 @@
this.locator = locator;
this.filter = config.getItemFilter();
this.ioManager = config.getIOManager();
+ this.propManager = config.getPropertyManager();
if (locator != null && locator.getResourcePath() != null) {
try {
@@ -286,11 +288,12 @@
}
try {
- ioManager.exportContent(new PropertyExportCtx(), this);
- } catch (IOException e) {
- // should not occure....
+ propManager.exportProperties(getPropertyExportContext(), isCollection());
+ } catch (RepositoryException e) {
+ log.warn("Error while accessing resource properties", e);
}
+ // set (or reset) fundamental properties
if (getDisplayName() != null) {
properties.add(new DefaultDavProperty(DavPropertyName.DISPLAYNAME, getDisplayName()));
}
@@ -313,24 +316,6 @@
supportedLock.addEntry(Type.WRITE, Scope.EXCLUSIVE);
properties.add(supportedLock);
- // non-protected JCR properties defined on the underlying jcr node
- try {
- PropertyIterator it = node.getProperties();
- while (it.hasNext()) {
- Property p = it.nextProperty();
- String pName = p.getName();
- PropertyDefinition def = p.getDefinition();
- if (def.isMultiple() || isFilteredItem(p)) {
- log.debug("Property '" + pName + "' not added to webdav property set (either multivalue or filtered).");
- continue;
- }
- DavPropertyName name = getDavName(pName, node.getSession());
- String value = p.getValue().getString();
- properties.add(new DefaultDavProperty(name, value, def.isProtected()));
- }
- } catch (RepositoryException e) {
- log.error("Unexpected error while retrieving properties: " + e.getMessage());
- }
inited = true;
}
@@ -340,25 +325,7 @@
* @see DavResource#setProperty(org.apache.jackrabbit.webdav.property.DavProperty)
*/
public void setProperty(DavProperty property) throws DavException {
- if (isLocked(this)) {
- throw new DavException(DavServletResponse.SC_LOCKED);
- }
- if (!exists()) {
- throw new DavException(DavServletResponse.SC_NOT_FOUND);
- }
- try {
- setJcrProperty(property);
- node.save();
- } catch (RepositoryException e) {
- // revert any changes made so far an throw exception
- JcrDavException je = new JcrDavException(e);
- try {
- node.refresh(false);
- } catch (RepositoryException re) {
- // should not happen...
- }
- throw je;
- }
+ alterProperty(property);
}
/**
@@ -367,6 +334,10 @@
* @see DavResource#removeProperty(org.apache.jackrabbit.webdav.property.DavPropertyName)
*/
public void removeProperty(DavPropertyName propertyName) throws DavException {
+ alterProperty(propertyName);
+ }
+
+ private void alterProperty(Object prop) throws DavException {
if (isLocked(this)) {
throw new DavException(DavServletResponse.SC_LOCKED);
}
@@ -374,9 +345,19 @@
throw new DavException(DavServletResponse.SC_NOT_FOUND);
}
try {
- removeJcrProperty(propertyName);
- node.save();
+ List l = new ArrayList(1);
+ l.add(prop);
+ alterProperties(l);
+ Map failure = propManager.alterProperties(getPropertyImportContext(l), isCollection());
+ if (failure.isEmpty()) {
+ node.save();
+ } else {
+ node.refresh(false);
+ // TODO: retrieve specific error from failure-map
+ throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR);
+ }
} catch (RepositoryException e) {
+ // revert any changes made so far
JcrDavException je = new JcrDavException(e);
try {
node.refresh(false);
@@ -406,7 +387,6 @@
changeList.add(it.next());
}
}
-
return alterProperties(changeList);
}
@@ -418,39 +398,9 @@
throw new DavException(DavServletResponse.SC_NOT_FOUND);
}
MultiStatusResponse msr = new MultiStatusResponse(getHref(), null);
- boolean success = true;
-
- // loop over List and remember all properties and propertyNames
- // that have successfully been altered
- List successList = new ArrayList();
- Iterator it = changeList.iterator();
- while (it.hasNext()) {
- Object propEntry = it.next();
- if (propEntry instanceof DavPropertyName) {
- DavPropertyName propName = (DavPropertyName)propEntry;
- try {
- removeJcrProperty(propName);
- successList.add(propName);
- } catch (RepositoryException e) {
- msr.add(propName, new JcrDavException(e).getErrorCode());
- success = false;
- }
- } else if (propEntry instanceof DavProperty) {
- DavProperty prop = (DavProperty)propEntry;
- try {
- setJcrProperty(prop);
- successList.add(prop);
- } catch (RepositoryException e) {
- msr.add(prop.getName(), new JcrDavException(e).getErrorCode());
- success = false;
- }
- } else {
- throw new IllegalArgumentException("unknown object in change list: " + propEntry.getClass().getName());
- }
- }
-
try {
- if (success) {
+ Map failures = propManager.alterProperties(getPropertyImportContext(changeList), isCollection());
+ if (failures.isEmpty()) {
// save all changes together (reverted in case this fails)
node.save();
} else {
@@ -462,14 +412,22 @@
complete action. in case of failure set the status to 'failed-dependency'
in order to indicate, that altering those names/properties would
have succeeded, if no other error occured.*/
- it = successList.iterator();
+ Iterator it = changeList.iterator();
while (it.hasNext()) {
Object o = it.next();
- int status = (success) ? DavServletResponse.SC_OK : DavServletResponse.SC_FAILED_DEPENDENCY;
+ int statusCode;
+ if (failures.containsKey(o)) {
+ Object error = failures.get(o);
+ statusCode = (error instanceof RepositoryException)
+ ? new JcrDavException((RepositoryException)o).getErrorCode()
+ : DavServletResponse.SC_INTERNAL_SERVER_ERROR;
+ } else {
+ statusCode = (failures.isEmpty()) ? DavServletResponse.SC_OK : DavServletResponse.SC_FAILED_DEPENDENCY;
+ }
if (o instanceof DavProperty) {
- msr.add(((DavProperty) o).getName(), status);
+ msr.add(((DavProperty) o).getName(), statusCode);
} else {
- msr.add((DavPropertyName) o, status);
+ msr.add((DavPropertyName) o, statusCode);
}
}
return msr;
@@ -840,6 +798,25 @@
}
/**
+ * Returns a new <code>PropertyImportContext</code>.
+ *
+ * @param changeList
+ * @return
+ */
+ protected PropertyImportContext getPropertyImportContext(List changeList) {
+ return new ProperyImportCtx(changeList);
+ }
+
+ /**
+ * Returns a new <code>PropertyExportContext</code>.
+ *
+ * @return
+ */
+ protected PropertyExportContext getPropertyExportContext() {
+ return new PropertyExportCtx();
+ }
+
+ /**
* Returns true, if the underlying node is nodetype jcr:lockable,
* without checking its current lock status. If the node is not jcr-lockable
* an attempt is made to add the mix:lockable mixin type.
@@ -885,97 +862,6 @@
}
}
- /**
- * Builds a webdav property name from the given jcrName. In case the jcrName
- * contains a namespace prefix that would conflict with any of the predefined
- * webdav namespaces a new prefix is assigned.<br>
- * Please note, that the local part of the jcrName is checked for XML
- * compatibility by calling {@link ISO9075#encode(String)}
- *
- * @param jcrName
- * @param session
- * @return a <code>DavPropertyName</code> for the given jcr name.
- */
- private DavPropertyName getDavName(String jcrName, Session session) throws RepositoryException {
- // make sure the local name is xml compliant
- String localName = ISO9075.encode(Text.getLocalName(jcrName));
- String prefix = Text.getNamespacePrefix(jcrName);
- String uri = session.getNamespaceURI(prefix);
- // check for conflicts with reserved webdav-namespaces
- if (reservedNamespaces.containsKey(prefix) && !reservedNamespaces.get(prefix).equals(uri)) {
- prefix = prefix + "0";
- }
- Namespace namespace = Namespace.getNamespace(prefix, uri);
- DavPropertyName name = DavPropertyName.create(localName, namespace);
- return name;
- }
-
- /**
- * Build jcr property name from dav property name. If the property name
- * defines a namespace uri, that has not been registered yet, an attempt
- * is made to register the uri with the prefix defined. Note, that no
- * extra effort is made to generated a unique prefix.
- *
- * @param propName
- * @return jcr name
- * @throws RepositoryException
- */
- private String getJcrName(DavPropertyName propName) throws RepositoryException {
- // remove any encoding necessary for xml compliance
- String pName = ISO9075.decode(propName.getName());
- Namespace propNamespace = propName.getNamespace();
- if (!Namespace.EMPTY_NAMESPACE.equals(propNamespace)) {
- Session s = getJcrSession();
- String prefix;
- String emptyPrefix = Namespace.EMPTY_NAMESPACE.getPrefix();
- try {
- // lookup 'prefix' in the session-ns-mappings / namespace-registry
- prefix = s.getNamespacePrefix(propNamespace.getURI());
- } catch (NamespaceException e) {
- // namespace uri has not been registered yet
- NamespaceRegistry nsReg = s.getWorkspace().getNamespaceRegistry();
- prefix = propNamespace.getPrefix();
- // avoid trouble with default namespace
- if (emptyPrefix.equals(prefix)) {
- prefix = "_pre" + nsReg.getPrefixes().length + 1;
- }
- // NOTE: will fail if prefix is already in use in the namespace registry
- nsReg.registerNamespace(prefix, propNamespace.getURI());
- }
- if (prefix != null && !emptyPrefix.equals(prefix)) {
- pName = prefix + ":" + pName;
- }
- }
- return pName;
- }
-
- /**
- * @param property
- * @throws RepositoryException
- */
- private void setJcrProperty(DavProperty property) throws RepositoryException {
- // Retrieve the property value. Note, that a 'null' value is replaced
- // by empty string, since setting a jcr property value to 'null'
- // would be equivalent to its removal.
- String value = "";
- if (property.getValue() != null) {
- value = property.getValue().toString();
- }
- node.setProperty(getJcrName(property.getName()), value);
- }
-
- /**
- * @param propertyName
- * @throws RepositoryException
- */
- private void removeJcrProperty(DavPropertyName propertyName) throws RepositoryException {
- String jcrName = getJcrName(propertyName);
- if (node.hasProperty(jcrName)) {
- node.getProperty(jcrName).remove();
- }
- // removal of non existing property succeeds
- }
-
private Session getJcrSession() {
return session.getRepositorySession();
}
@@ -994,7 +880,7 @@
* ExportContext that writes the properties of this <code>DavResource</code>
* and provides not stream.
*/
- private class PropertyExportCtx extends AbstractExportContext {
+ private class PropertyExportCtx extends AbstractExportContext implements PropertyExportContext {
private PropertyExportCtx() {
super(node, false, null);
@@ -1048,9 +934,81 @@
}
public void setProperty(Object propertyName, Object propertyValue) {
- if (propertyName instanceof DavPropertyName) {
- DavPropertyName pName = (DavPropertyName)propertyName;
+ if (propertyValue == null) {
+ log.warn("Ignore 'setProperty' for " + propertyName + "with null value.");
+ return;
+ }
+
+ if (propertyValue instanceof DavProperty) {
+ properties.add((DavProperty)propertyValue);
+ } else {
+ DavPropertyName pName;
+ if (propertyName instanceof DavPropertyName) {
+ pName = (DavPropertyName)propertyName;
+ } else {
+ // create property name with default DAV: namespace
+ pName = DavPropertyName.create(propertyName.toString());
+ }
properties.add(new DefaultDavProperty(pName, propertyValue));
+ }
+ }
+ }
+
+ private class ProperyImportCtx implements PropertyImportContext {
+
+ private final IOListener ioListener = new DefaultIOListener(log);
+ private final List changeList;
+ private boolean completed;
+
+ private ProperyImportCtx(List changeList) {
+ this.changeList = changeList;
+ }
+
+ /**
+ * @see PropertyImportContext#getImportRoot()
+ */
+ public Item getImportRoot() {
+ return node;
+ }
+
+ /**
+ * @see PropertyImportContext#getChangeList()
+ */
+ public List getChangeList() {
+ return Collections.unmodifiableList(changeList);
+ }
+
+ public IOListener getIOListener() {
+ return ioListener;
+ }
+
+ public boolean hasStream() {
+ return false;
+ }
+
+ /**
+ * @see PropertyImportContext#informCompleted(boolean)
+ */
+ public void informCompleted(boolean success) {
+ checkCompleted();
+ completed = true;
+ }
+
+ /**
+ * @see PropertyImportContext#isCompleted()
+ */
+ public boolean isCompleted() {
+ return completed;
+ }
+
+ /**
+ * @throws IllegalStateException if the context is already completed.
+ * @see #isCompleted()
+ * @see #informCompleted(boolean)
+ */
+ private void checkCompleted() {
+ if (completed) {
+ throw new IllegalStateException("PropertyImportContext has already been consumed.");
}
}
}
Modified: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/ResourceConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/ResourceConfig.java?rev=431546&r1=431545&r2=431546&view=diff
==============================================================================
--- jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/ResourceConfig.java (original)
+++ jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/ResourceConfig.java Tue Aug 15 00:09:07 2006
@@ -19,6 +19,9 @@
import org.apache.jackrabbit.server.io.IOManager;
import org.apache.jackrabbit.server.io.DefaultIOManager;
import org.apache.jackrabbit.server.io.IOHandler;
+import org.apache.jackrabbit.server.io.PropertyManager;
+import org.apache.jackrabbit.server.io.PropertyHandler;
+import org.apache.jackrabbit.server.io.PropertyManagerImpl;
import org.apache.jackrabbit.webdav.xml.ElementIterator;
import org.apache.jackrabbit.webdav.xml.DomUtil;
import org.slf4j.Logger;
@@ -47,6 +50,7 @@
private ItemFilter itemFilter;
private IOManager ioManager;
+ private PropertyManager propManager;
private String[] nodetypeNames = new String[0];
private boolean collectionNames = false;
@@ -54,9 +58,11 @@
* Tries to parse the given xml configuration file.
* The xml must match the following structure:<br>
* <pre>
- * <!ELEMENT config (iomanager, (collection | noncollection)?, filter?) >
+ * <!ELEMENT config (iomanager, propertymanager, (collection | noncollection)?, filter?) >
* <!ELEMENT iomanager (class, iohandler*) >
* <!ELEMENT iohandler (class) >
+ * <!ELEMENT propertymanager (class, propertyhandler*) >
+ * <!ELEMENT propertyhandler (class) >
* <!ELEMENT collection (nodetypes) >
* <!ELEMENT noncollection (nodetypes) >
* <!ELEMENT filter (class, namespaces?, nodetypes?) >
@@ -81,7 +87,7 @@
Element config = document.getDocumentElement();
if (config == null) {
- log.error("Resource configuration: mandatory 'iomanager' element is missing.");
+ log.warn("Resource configuration: mandatory 'config' element is missing.");
return;
}
@@ -97,16 +103,40 @@
Element iohEl = iohElements.nextElement();
inst = buildClassFromConfig(iohEl);
if (inst != null && inst instanceof IOHandler) {
- this.ioManager.addIOHandler((IOHandler) inst);
+ ioManager.addIOHandler((IOHandler) inst);
} else {
- log.error("Resource configuration: the handler is not a valid IOHandler.");
+ log.warn("Resource configuration: the handler is not a valid IOHandler.");
}
}
} else {
- log.error("Resource configuration: 'iomanager' does not define a valid IOManager.");
+ log.warn("Resource configuration: 'iomanager' does not define a valid IOManager.");
}
} else {
- log.error("Resource configuration: mandatory 'iomanager' element is missing.");
+ log.warn("Resource configuration: 'iomanager' element is missing.");
+ }
+
+ el = DomUtil.getChildElement(config, "propertymanager", null);
+ if (el != null) {
+ Object inst = buildClassFromConfig(el);
+ if (inst != null && inst instanceof PropertyManager) {
+ propManager = (PropertyManager)inst;
+ // get optional 'iohandler' child elements and populate the
+ // ioManager with the instances
+ ElementIterator iohElements = DomUtil.getChildren(el, "propertyhandler", null);
+ while (iohElements.hasNext()) {
+ Element iohEl = iohElements.nextElement();
+ inst = buildClassFromConfig(iohEl);
+ if (inst != null && inst instanceof PropertyHandler) {
+ propManager.addPropertyHandler((PropertyHandler) inst);
+ } else {
+ log.warn("Resource configuration: the handler is not a valid PropertyHandler.");
+ }
+ }
+ } else {
+ log.warn("Resource configuration: 'propertymanager' does not define a valid PropertyManager.");
+ }
+ } else {
+ log.debug("Resource configuration: 'propertymanager' element is missing.");
}
el = DomUtil.getChildElement(config, "collection", null);
@@ -202,13 +232,28 @@
return ntNames;
}
-
+ /**
+ *
+ * @return
+ */
public IOManager getIOManager() {
if (ioManager == null) {
log.debug("ResourceConfig: missing io-manager > building DefaultIOManager ");
ioManager = new DefaultIOManager();
}
return ioManager;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public PropertyManager getPropertyManager() {
+ if (propManager == null) {
+ log.debug("ResourceConfig: missing property-manager > building default.");
+ propManager = PropertyManagerImpl.getDefaultManager();
+ }
+ return propManager;
}
/**
Modified: jackrabbit/trunk/jcr-server/webapp/src/webapp/WEB-INF/config.xml
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jcr-server/webapp/src/webapp/WEB-INF/config.xml?rev=431546&r1=431545&r2=431546&view=diff
==============================================================================
--- jackrabbit/trunk/jcr-server/webapp/src/webapp/WEB-INF/config.xml (original)
+++ jackrabbit/trunk/jcr-server/webapp/src/webapp/WEB-INF/config.xml Tue Aug 15 00:09:07 2006
@@ -1,11 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
<!DOCTYPE config [
- <!ELEMENT config (iomanager , (collection | noncollection)? , filter?) >
+ <!ELEMENT config (iomanager , propertymanager, (collection | noncollection)? , filter?) >
<!ELEMENT iomanager (class, iohandler*) >
<!ELEMENT iohandler (class) >
+ <!ELEMENT propertymanager (class, propertyhandler*) >
+ <!ELEMENT propertyhandler (class) >
+
<!ELEMENT collection (nodetypes) >
<!ELEMENT noncollection (nodetypes) >
@@ -31,38 +34,57 @@
-->
<iomanager>
<!-- class element defines the manager to be used. The specified class
- must implement the IOManager interface. -->
- <!-- the DefaultIOManager builds a predefined set of handlers. the
- optional 'iohandler' elements are therefore left out. -->
- <class name="org.apache.jackrabbit.server.io.DefaultIOManager" />
-
- </iomanager>
- <!--
- Example config for iomanager that defines the set of handlers to be used.
- Note, that the handlers are being added and called in the order they appear
- in the configuration.
- -->
- <!--
- <iomanager>
+ must implement the IOManager interface.
+ Note, that the handlers are being added and called in the order
+ they appear in the configuration.
+ -->
<class name="org.apache.jackrabbit.server.io.IOManagerImpl" />
<iohandler>
- <class name="org.apache.jackrabbit.server.io.XmlHandler" />
+ <class name="org.apache.jackrabbit.server.io.ZipHandler" />
</iohandler>
<iohandler>
- <class name="org.apache.jackrabbit.server.io.DefaultHandler" />
+ <class name="org.apache.jackrabbit.server.io.XmlHandler" />
+ </iohandler>
+ <iohandler>
+ <class name="org.apache.jackrabbit.server.io.DirListingExportHandler" />
+ </iohandler>
+ <iohandler>
+ <class name="org.apache.jackrabbit.server.io.DefaultHandler" />
</iohandler>
</iomanager>
+ <!--
+ Example config for iomanager that populates its list of handlers with
+ default values. Therefore the 'iohandler' elements are omited.
-->
<!--
- Defines nodetypes, that should always be displayed as 'collection'.
+ <iomanager>
+ <class name="org.apache.jackrabbit.server.io.DefaultIOManager" />
+ </iomanager>
-->
<!--
- <collection>
- <nodetypes>
- <nodetype>nt:folder</nodetype>
- </nodetypes>
- </collection>
+ Defines the PropertyManager implementation that is responsible for export
+ and import of resource properties.
-->
+ <propertymanager>
+ <!-- class element defines the manager to be used. The specified class
+ must implement the PropertyManager interface.
+ Note, that the handlers are being added and called in the order
+ they appear in the configuration.
+ -->
+ <class name="org.apache.jackrabbit.server.io.PropertyManagerImpl" />
+ <propertyhandler>
+ <class name="org.apache.jackrabbit.server.io.ZipHandler" />
+ </propertyhandler>
+ <propertyhandler>
+ <class name="org.apache.jackrabbit.server.io.XmlHandler" />
+ </propertyhandler>
+ <propertyhandler>
+ <class name="org.apache.jackrabbit.server.io.DirListingExportHandler" />
+ </propertyhandler>
+ <propertyhandler>
+ <class name="org.apache.jackrabbit.server.io.DefaultHandler" />
+ </propertyhandler>
+ </propertymanager>
<!--
Define nodetypes, that should never by displayed as 'collection'
-->
@@ -72,6 +94,17 @@
<nodetype>nt:resource</nodetype>
</nodetypes>
</noncollection>
+ <!--
+ Example: Defines nodetypes, that should always be displayed as 'collection'.
+ -->
+ <!--
+ <collection>
+ <nodetypes>
+ <nodetype>nt:folder</nodetype>
+ <nodetype>rep:root</nodetype>
+ </nodetypes>
+ </collection>
+ -->
<!--
Filter that allows to prevent certain items from being displayed.
Please note, that this has an effect on PROPFIND calls only and does not