### Eclipse Workspace Patch 1.0
#P trunk
Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/README.txt
===================================================================
--- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/README.txt (nonexistent)
+++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/README.txt (working copy)
@@ -0,0 +1,8 @@
+=======================================================
+Apache Jackrabbit JCR Servlets
+=======================================================
+
+JCR Servlets is a collection of servlets and other classes designed to
+make it easier to use Jackrabbit and other JCR content repositories in
+web applications.
+
Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/README.txt
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/pom.xml
===================================================================
--- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/pom.xml (nonexistent)
+++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/pom.xml (working copy)
@@ -0,0 +1,44 @@
+
+
+
+
+
+ 4.0.0
+
+ org.apache.jackrabbit
+ jackrabbit-jcr-servlet-project
+ 2.21.16-SNAPSHOT
+
+
+ jackrabbit-jcr-servlet
+
+ Jackrabbit JCR Servlets
+
+ Servlets and related classes for easy use of JCR content repositories
+ in web applications.
+
+
+
+
+ javax.servlet
+ javax.servlet-api
+ provided
+
+
+
+
Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/pom.xml
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/AbstractRepositoryServlet.java
===================================================================
--- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/AbstractRepositoryServlet.java (nonexistent)
+++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/AbstractRepositoryServlet.java (working copy)
@@ -0,0 +1,196 @@
+/*
+ * 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.servlet;
+
+import java.io.IOException;
+import java.util.Properties;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.jackrabbit.commons.repository.ProxyRepository;
+
+/**
+ * Abstract base class for servlets that make a repository available in
+ * the servlet context. This class handles the initialization and cleanup
+ * tasks of setting up and clearing the configured repository attribute,
+ * while a subclass only needs to implement the abstract
+ * {@link #getRepository()} method that returns the actual content repository.
+ *
+ * The {@link Repository} instance bound to the servlet context is actually
+ * a {@link ProxyRepository} for late binding of the underlying content repository.
+ *
+ * The default name of the repository attribute is
+ * "javax.jcr.Repository", but it can be changed by specifying
+ * an init parameter with the same name:
+ *
+ * <servlet>
+ * <init-param>
+ * <param-name>javax.jcr.Repository</param-name>
+ * <param-value>my.repository.attribute</param-value>
+ * <description>
+ * This init parameter causes the repository to be looked up from
+ * the "my.repository.attribute" attribute instead of the default
+ * "javax.jcr.Repository".
+ * </description>
+ * </init-param>
+ * </servlet>
+ *
+ *
+ * A repository servlet can also be mapped to the URL space. See the
+ * {@link #doGet(HttpServletRequest, HttpServletResponse)} method for
+ * the details of the default behavior.
+ *
+ * @since 1.4
+ */
+public abstract class AbstractRepositoryServlet extends HttpServlet {
+
+ /**
+ * Binds a {@link ProxyRepository} with the repository returned by
+ * {@link #getRepository()} in the configured servlet context attribute.
+ *
+ * @throws ServletException
+ */
+ public void init() throws ServletException {
+ getServletContext().setAttribute(
+ getAttributeName(),
+ new ProxyRepository() {
+ @Override
+ protected Repository getRepository()
+ throws RepositoryException {
+ return AbstractRepositoryServlet.this.getRepository();
+ }
+ });
+ }
+
+ /**
+ * Removes the repository attribute from the servlet context.
+ */
+ public void destroy() {
+ getServletContext().removeAttribute(getAttributeName());
+ }
+
+ /**
+ * Returns the repository that will be used by the
+ * {@link ProxyRepository} bound to the servlet context.
+ *
+ * @return repository
+ * @throws RepositoryException if the repository could not be created
+ */
+ protected abstract Repository getRepository()
+ throws RepositoryException;
+
+ /**
+ * Returns the name of the repository attribute. The default
+ * implementation returns "javax.jcr.Repository" or
+ * the value of the "javax.jcr.Repository" init parameter.
+ *
+ * A subclass can override this method to customize the attribute name,
+ * but for consistency it is generally better not to do that.
+ *
+ * @return name of the repository attribute
+ */
+ protected String getAttributeName() {
+ String name = Repository.class.getName();
+ return getInitParameter(name, name);
+ }
+
+ /**
+ * Utility method that returns the named init parameter or the given
+ * default value if the parameter does not exist.
+ *
+ * @param name name of the init parameter
+ * @param def default value
+ * @return value of the init parameter, or the default value
+ */
+ protected String getInitParameter(String name, String def) {
+ String value = getInitParameter(name);
+ if (value == null) {
+ value = def;
+ }
+ return value;
+ }
+
+ /**
+ * Outputs the repository descriptors either as a collection of properties
+ * (see {@link Properties#store(java.io.OutputStream, String)} or
+ * individually addressable text/plain resources based on the request URI.
+ *
+ * A typical mapping for a repository servlet would be:
+ *
+ * This mapping would allow clients to retrieve all repository descriptors
+ * from http://server/context/repository/ and to address
+ * individual descriptors by key with URIs like
+ * http://server/context/repository/key.
+ * For example, the name of the repository vendor could be retrieved from
+ * http://server/context/repository/jcr.repository.vendor.
+ * Likewise, a 404 (not found) response from
+ * http://server/context/repository/level.2.supported would
+ * indicate that the repository does not support Level 2 features.
+ *
+ * Note that mapping a repository servlet to the URL space is optional,
+ * as the main purpose of the servlet is to make a repository available
+ * in the servlet context, not to expose repository information to web
+ * clients.
+ *
+ * @param request HTTP request
+ * @param response HTTP response
+ * @throws IOException on IO errors
+ * @throws ServletException on servlet errors
+ */
+ protected void doGet(
+ HttpServletRequest request, HttpServletResponse response)
+ throws IOException, ServletException {
+ Repository repository = new ServletRepository(this);
+
+ String info = request.getPathInfo();
+ if (info == null || info.equals("/")) {
+ Properties descriptors = new Properties();
+ String[] keys = repository.getDescriptorKeys();
+ for (int i = 0; i < keys.length; i++) {
+ descriptors.setProperty(
+ keys[i], repository.getDescriptor(keys[i]));
+ }
+ // TODO: Using UTF-8 instead of ISO-8859-1 would be better, but
+ // would require re-implementing the Properties.store() method
+ response.setContentType("text/plain; charset=ISO-8859-1");
+ descriptors.store(response.getOutputStream(), getAttributeName());
+ } else {
+ String key = info.substring(1); // skip the leading "/"
+ String descriptor = repository.getDescriptor(key);
+ if (descriptor != null) {
+ response.setContentType("text/plain; charset=UTF-8");
+ response.getWriter().write(descriptor);
+ } else {
+ response.sendError(
+ HttpServletResponse.SC_NOT_FOUND,
+ "Repository descriptor " + key + " not found");
+ }
+ }
+ }
+
+}
Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/AbstractRepositoryServlet.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/ContextRepositoryServlet.java
===================================================================
--- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/ContextRepositoryServlet.java (nonexistent)
+++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/ContextRepositoryServlet.java (working copy)
@@ -0,0 +1,106 @@
+/*
+ * 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.servlet;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.servlet.ServletContext;
+
+/**
+ * Servlet that makes a repository from one servlet context attribute
+ * available as another servlet context attribute. The source context
+ * can be different from the context of this servlet.
+ *
+ * The supported initialization parameters of this servlet are:
+ *
+ *
javax.jcr.Repository
+ *
+ * Name of the target servlet context attribute.
+ * The default value is "javax.jcr.Repository".
+ *
+ *
path
+ *
+ * Context path of the source servlet context. The source context
+ * defaults to the context of this servlet if this parameter is not set.
+ *
+ *
name
+ *
+ * Name of the source servlet context attribute. The default value
+ * is "javax.jcr.Repository". The name of the source attribute
+ * can be the same as the name of target attribute only if the source
+ * context is different from the context of this servlet.
+ *
+ *
+ *
+ * This servlet can also be mapped to the URL space. See
+ * {@link AbstractRepositoryServlet} for the details.
+ *
+ * @since 1.4
+ */
+public class ContextRepositoryServlet extends AbstractRepositoryServlet {
+
+ /**
+ * Serial version UID.
+ */
+ private static final long serialVersionUID = 6222606878557491477L;
+
+ /**
+ * Creates and returns the repository in the configured servlet
+ * context attribute.
+ *
+ * @return repository
+ */
+ protected Repository getRepository() throws RepositoryException {
+ String path = getInitParameter("path");
+ String name = getInitParameter("name", Repository.class.getName());
+
+ ServletContext context = getServletContext();
+ if (path != null && context.equals(context.getContext(path))) {
+ path = null;
+ }
+
+ if (path == null && name.equals(getAttributeName())) {
+ throw new RepositoryException(
+ "Invalid configuration: Can not duplicate attribute "
+ + name + " of servlet " + getServletName());
+ }
+
+ ServletContext otherContext = context.getContext(path);
+ if (otherContext == null) {
+ throw new RepositoryException(
+ "Repository not found: Servlet context " + path
+ + " does not exist or is not accessible from context "
+ + context.getServletContextName());
+ }
+
+ Object repository = otherContext.getAttribute(name);
+ if (repository instanceof Repository) {
+ return (Repository) repository;
+ } else if (repository != null) {
+ throw new RepositoryException(
+ "Invalid repository: Attribute " + name
+ + " in servlet context " + otherContext.getServletContextName()
+ + " is an instance of " + repository.getClass().getName());
+ } else {
+ throw new RepositoryException(
+ "Repository not found: Attribute " + name
+ + " does not exist in servlet context "
+ + otherContext.getServletContextName());
+ }
+ }
+
+}
Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/ContextRepositoryServlet.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/FilterRepositoryFactory.java
===================================================================
--- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/FilterRepositoryFactory.java (nonexistent)
+++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/FilterRepositoryFactory.java (working copy)
@@ -0,0 +1,95 @@
+/*
+ * 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.servlet;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+
+import org.apache.jackrabbit.commons.repository.RepositoryFactory;
+
+/**
+ * Factory that looks up a repository from the context of a given filter.
+ *
+ * The default name of the repository attribute is
+ * "javax.jcr.Repository", but it can be changed by specifying
+ * an init parameter with the same name:
+ *
+ * <filter>
+ * <init-param>
+ * <param-name>javax.jcr.Repository</param-name>
+ * <param-value>my.repository.attribute</param-value>
+ * <description>
+ * This init parameter causes the repository to be looked up from
+ * the "my.repository.attribute" attribute instead of the default
+ * "javax.jcr.Repository".
+ * </description>
+ * </init-param>
+ * </filter>
+ *
+ *
+ * @since Apache Jackrabbit 1.6
+ */
+public class FilterRepositoryFactory implements RepositoryFactory {
+
+ /**
+ * Configuration of the filter whose context contains the repository.
+ */
+ private final FilterConfig config;
+
+ /**
+ * Creates a factory for looking up a repository from the context
+ * associated with the given filter configuration.
+ *
+ * @param config filter configuration
+ */
+ public FilterRepositoryFactory(FilterConfig config) {
+ this.config = config;
+ }
+
+ /**
+ * Looks up and returns a repository bound in the servlet context of
+ * the given filter.
+ *
+ * @return repository from servlet context
+ * @throws RepositoryException if the repository is not available
+ */
+ public Repository getRepository() throws RepositoryException {
+ String name = config.getInitParameter(Repository.class.getName());
+ if (name == null) {
+ name = Repository.class.getName();
+ }
+
+ ServletContext context = config.getServletContext();
+ Object repository = context.getAttribute(name);
+ if (repository instanceof Repository) {
+ return (Repository) repository;
+ } else if (repository != null) {
+ throw new RepositoryException(
+ "Invalid repository: Attribute " + name
+ + " in servlet context " + context.getServletContextName()
+ + " is an instance of " + repository.getClass().getName());
+ } else {
+ throw new RepositoryException(
+ "Repository not found: Attribute " + name
+ + " does not exist in servlet context "
+ + context.getServletContextName());
+ }
+ }
+
+}
Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/FilterRepositoryFactory.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/JNDIBindingServlet.java
===================================================================
--- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/JNDIBindingServlet.java (nonexistent)
+++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/JNDIBindingServlet.java (working copy)
@@ -0,0 +1,107 @@
+/*
+ * 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.servlet;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import javax.jcr.Repository;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+
+/**
+ * Servlet that binds a repository from a servlet context attribute in JNDI.
+ *
+ * The initialization parameters of this servlet are:
+ *
+ *
javax.jcr.Repository
+ *
+ * Name of the servlet context attribute that contains the repository.
+ * The default value is "javax.jcr.Repository".
+ *
+ *
location
+ *
+ * Location where to bind the repository in the JNDI directory.
+ * The default value is "javax/jcr/Repository".
+ *
+ *
*
+ *
+ * All other init parameters are used as the JNDI environment when
+ * instantiating {@link InitialContext} for binding up the repository.
+ *
+ *
+ *
+ * @since 1.4
+ */
+public class JNDIBindingServlet extends HttpServlet {
+
+ /**
+ * Serial version UID.
+ */
+ private static final long serialVersionUID = -9033906248473370936L;
+
+ /**
+ * JNDI context to which to bind the repository.
+ */
+ private Context context;
+
+ /**
+ * Location of the repository within the JNDI context.
+ */
+ private String location = Repository.class.getName().replace('.', '/');
+
+ /**
+ * Binds a repository from the servlet context in the configured
+ * JNDI location.
+ *
+ * @throws ServletException if the repository could not be bound in JNDI
+ */
+ public void init() throws ServletException {
+ try {
+ Hashtable environment = new Hashtable();
+ Enumeration names = getInitParameterNames();
+ while (names.hasMoreElements()) {
+ String name = (String) names.nextElement();
+ if (name.equals("location")) {
+ location = getInitParameter(name);
+ } else if (!name.equals(Repository.class.getName())) {
+ environment.put(name, getInitParameter(name));
+ }
+ }
+ context = new InitialContext(environment);
+ context.bind(location, new ServletRepository(this));
+ } catch (NamingException e) {
+ throw new ServletException(
+ "Failed to bind repository to JNDI: " + location, e);
+ }
+ }
+
+ /**
+ * Unbinds the repository from JNDI.
+ */
+ public void destroy() {
+ try {
+ context.unbind(location);
+ } catch (NamingException e) {
+ log("Failed to unbind repository from JNDI: " + location, e);
+ }
+ }
+
+}
Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/JNDIBindingServlet.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/JNDIRepositoryServlet.java
===================================================================
--- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/JNDIRepositoryServlet.java (nonexistent)
+++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/JNDIRepositoryServlet.java (working copy)
@@ -0,0 +1,90 @@
+/*
+ * 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.servlet;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+import org.apache.jackrabbit.commons.repository.JNDIRepositoryFactory;
+
+/**
+ * Servlet that makes a repository from JNDI available as an attribute
+ * in the servlet context.
+ *
+ * The supported initialization parameters of this servlet are:
+ *
+ *
javax.jcr.Repository
+ *
+ * Name of the servlet context attribute to put the repository in.
+ * The default value is "javax.jcr.Repository".
+ *
+ *
location
+ *
+ * Location of the repository in the JNDI directory.
+ * The default value is "javax/jcr/Repository".
+ *
+ *
*
+ *
+ * All other init parameters are used as the JNDI environment when
+ * instantiating {@link InitialContext} for looking up the repository.
+ *
+ *
+ *
+ * This servlet can also be mapped to the URL space. See
+ * {@link AbstractRepositoryServlet} for the details.
+ *
+ * @since 1.4
+ */
+public class JNDIRepositoryServlet extends AbstractRepositoryServlet {
+
+ /**
+ * Serial version UID.
+ */
+ private static final long serialVersionUID = 8952525573562952560L;
+
+ /**
+ * Returns a JNDI repository based on the configured init parameters.
+ *
+ * @return JNDI repository
+ */
+ protected Repository getRepository() throws RepositoryException {
+ try {
+ String location = Repository.class.getName().replace('.', '/');
+ Hashtable environment = new Hashtable();
+ Enumeration names = getInitParameterNames();
+ while (names.hasMoreElements()) {
+ String name = (String) names.nextElement();
+ if (name.equals("location")) {
+ location = getInitParameter(name);
+ } else if (!name.equals(Repository.class.getName())) {
+ environment.put(name, getInitParameter(name));
+ }
+ }
+ return new JNDIRepositoryFactory(
+ new InitialContext(environment), location).getRepository();
+ } catch (NamingException e) {
+ throw new RepositoryException(
+ "Repository not found: Invalid JNDI context", e);
+ }
+ }
+
+}
Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/JNDIRepositoryServlet.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/ServletRepository.java
===================================================================
--- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/ServletRepository.java (nonexistent)
+++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/ServletRepository.java (working copy)
@@ -0,0 +1,98 @@
+/*
+ * 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.servlet;
+
+import javax.servlet.FilterConfig;
+import javax.servlet.GenericServlet;
+
+import org.apache.jackrabbit.commons.repository.ProxyRepository;
+
+/**
+ * Proxy for a repository bound in servlet context. The configured repository
+ * attribute is looked up from the servlet context during each method call.
+ * Thus the repository does not need to exist when this class is instantiated.
+ * The repository can also be replaced with another repository during the
+ * lifetime of an instance of this class.
+ *
+
+ *
+ * @since 1.4
+ * @see ServletRepositoryFactory
+ * @see FilterRepositoryFactory
+ */
+public class ServletRepository extends ProxyRepository {
+
+ /**
+ * Creates a proxy for a repository found in the context of the given
+ * servlet.
+ *
+ * @param servlet servlet
+ */
+ public ServletRepository(GenericServlet servlet) {
+ super(new ServletRepositoryFactory(servlet));
+ }
+
+ /**
+ * Creates a proxy for a repository found in the servlet context
+ * associated with the given filter configuration.
+ *
+ * @since Apache Jackrabbit 1.6
+ * @param config filter configuration
+ */
+ public ServletRepository(FilterConfig config) {
+ super(new FilterRepositoryFactory(config));
+ }
+
+}
Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/ServletRepository.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/ServletRepositoryFactory.java
===================================================================
--- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/ServletRepositoryFactory.java (nonexistent)
+++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/ServletRepositoryFactory.java (working copy)
@@ -0,0 +1,95 @@
+/*
+ * 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.servlet;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.servlet.GenericServlet;
+import javax.servlet.ServletContext;
+
+import org.apache.jackrabbit.commons.repository.RepositoryFactory;
+
+/**
+ * Factory that looks up a repository from the context of a given servlet.
+ *
+ * The default name of the repository attribute is
+ * "javax.jcr.Repository", but it can be changed by specifying
+ * an init parameter with the same name:
+ *
+ * <servlet>
+ * <init-param>
+ * <param-name>javax.jcr.Repository</param-name>
+ * <param-value>my.repository.attribute</param-value>
+ * <description>
+ * This init parameter causes the repository to be looked up from
+ * the "my.repository.attribute" attribute instead of the default
+ * "javax.jcr.Repository".
+ * </description>
+ * </init-param>
+ * </servlet>
+ *
+ *
+ * @since 1.4
+ */
+public class ServletRepositoryFactory implements RepositoryFactory {
+
+ /**
+ * The servlet whose context contains the repository.
+ */
+ private final GenericServlet servlet;
+
+ /**
+ * Creates a factory for looking up a repository from the context of
+ * the given servlet.
+ *
+ * @param servlet servlet whose context contains the repository
+ */
+ public ServletRepositoryFactory(GenericServlet servlet) {
+ this.servlet = servlet;
+ }
+
+ /**
+ * Looks up and returns a repository bound in the configured servlet
+ * context attribute.
+ *
+ * @return repository from servlet context
+ * @throws RepositoryException if the repository is not available
+ */
+ public Repository getRepository() throws RepositoryException {
+ String name = servlet.getInitParameter(Repository.class.getName());
+ if (name == null) {
+ name = Repository.class.getName();
+ }
+
+ ServletContext context = servlet.getServletContext();
+ Object repository = context.getAttribute(name);
+ if (repository instanceof Repository) {
+ return (Repository) repository;
+ } else if (repository != null) {
+ throw new RepositoryException(
+ "Invalid repository: Attribute " + name
+ + " in servlet context " + context.getServletContextName()
+ + " is an instance of " + repository.getClass().getName());
+ } else {
+ throw new RepositoryException(
+ "Repository not found: Attribute " + name
+ + " does not exist in servlet context "
+ + context.getServletContextName());
+ }
+ }
+
+}
Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/ServletRepositoryFactory.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/jackrabbit/JackrabbitRepositoryServlet.java
===================================================================
--- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/jackrabbit/JackrabbitRepositoryServlet.java (nonexistent)
+++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/jackrabbit/JackrabbitRepositoryServlet.java (working copy)
@@ -0,0 +1,172 @@
+/*
+ * 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.servlet.jackrabbit;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.servlet.ServletException;
+
+import org.apache.jackrabbit.core.RepositoryContext;
+import org.apache.jackrabbit.core.RepositoryImpl;
+import org.apache.jackrabbit.core.config.RepositoryConfig;
+import org.apache.jackrabbit.servlet.AbstractRepositoryServlet;
+
+/**
+ * Servlet that makes a Jackrabbit repository available as a servlet context
+ * attribute. The repository is started during servlet initialization and
+ * shut down when the servlet is destroyed.
+ *
+ * The supported initialization parameters of this servlet are:
+ *
+ *
org.apache.jackrabbit.core.RepositoryContext
+ *
+ * Name of the servlet context attribute to put the internal
+ * component context of the repository in. The default value is
+ * "org.apache.jackrabbit.core.RepositoryContext".
+ *
+ *
javax.jcr.Repository
+ *
+ * Name of the servlet context attribute to put the repository in.
+ * The default value is "javax.jcr.Repository".
+ *
+ *
repository.home
+ *
+ * Path of the repository home directory. The default value is
+ * "jackrabbit-repository". The home directory is
+ * automatically created during servlet initialization if it does
+ * not already exist.
+ *
+ *
repository.config
+ *
+ * Path of the repository configuration file. The default value is
+ * "repository.xml" within the configured repository home
+ * directory. A standard configuration file is automatically copied to
+ * the configured location during servlet initialization if the file
+ * does not already exist.
+ *
+ *
+ *
+ * The repository servlet can also be mapped to the URL space. See
+ * {@link AbstractRepositoryServlet} for the details.
+ *
+ * @since 1.4
+ */
+public class JackrabbitRepositoryServlet extends AbstractRepositoryServlet {
+
+ /**
+ * Serial version UID.
+ */
+ private static final long serialVersionUID = 7102770011290708450L;
+
+ /**
+ * Repository instance.
+ */
+ private RepositoryContext context;
+
+ /**
+ * Starts the repository instance and makes it available in the
+ * servlet context.
+ *
+ * @throws ServletException if the repository can not be started
+ */
+ public void init() throws ServletException {
+ try {
+ File home = new File(getInitParameter(
+ "repository.home", "jackrabbit-repository"));
+ if (!home.exists()) {
+ log("Creating repository home directory: " + home);
+ home.mkdirs();
+ }
+
+ File config = new File(getInitParameter(
+ "repository.config",
+ new File(home, "repository.xml").getPath()));
+ if (!config.exists()) {
+ log("Creating default repository configuration: " + config);
+ createDefaultConfiguration(config);
+ }
+
+ context = RepositoryContext.create(RepositoryConfig.create(
+ config.toURI(), home.getPath()));
+
+ String name = RepositoryContext.class.getName();
+ getServletContext().setAttribute(
+ getInitParameter(name, name), context);
+ } catch (RepositoryException e) {
+ throw new ServletException("Failed to start Jackrabbit", e);
+ }
+
+ super.init();
+ }
+
+ /**
+ * Removes the repository from the servlet context and shuts it down.
+ */
+ public void destroy() {
+ super.destroy();
+ context.getRepository().shutdown();
+ }
+
+ /**
+ * Returns the configured repository instance.
+ *
+ * @return repository
+ */
+ @Override
+ protected Repository getRepository() {
+ return context.getRepository();
+ }
+
+ /**
+ * Copies the default repository configuration file to the given location.
+ *
+ * @param config path of the configuration file
+ * @throws ServletException if the configuration file could not be copied
+ */
+ private void createDefaultConfiguration(File config)
+ throws ServletException {
+ try {
+ OutputStream output = new FileOutputStream(config);
+ try {
+ InputStream input =
+ RepositoryImpl.class.getResourceAsStream("repository.xml");
+ try {
+ byte[] buffer = new byte[8192];
+ int n = input.read(buffer);
+ while (n != -1) {
+ output.write(buffer, 0, n);
+ n = input.read(buffer);
+ }
+ } finally {
+ input.close();
+ }
+ } finally {
+ output.close();
+ }
+ } catch (IOException e) {
+ throw new ServletException(
+ "Failed to copy default configuration: " + config, e);
+ }
+ }
+
+}
Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/jackrabbit/JackrabbitRepositoryServlet.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/jackrabbit/StatisticsServlet.java
===================================================================
--- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/jackrabbit/StatisticsServlet.java (nonexistent)
+++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/jackrabbit/StatisticsServlet.java (working copy)
@@ -0,0 +1,108 @@
+/*
+ * 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.servlet.jackrabbit;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.jackrabbit.api.stats.RepositoryStatistics;
+import org.apache.jackrabbit.api.stats.TimeSeries;
+import org.apache.jackrabbit.core.RepositoryContext;
+
+/**
+ * Servlet that makes Jackrabbit repository statistics available as
+ * a JSON object.
+ *
+ * @since Apache Jackrabbit 2.3.1
+ */
+public class StatisticsServlet extends HttpServlet {
+
+ /** Serial version UID */
+ private static final long serialVersionUID = -7494195499389135951L;
+
+ @Override
+ protected void doGet(
+ HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ String klass = RepositoryContext.class.getName();
+ String name = getServletConfig().getInitParameter(klass);
+ if (name == null) {
+ name = klass;
+ }
+
+ RepositoryContext context = (RepositoryContext)
+ getServletContext().getAttribute(name);
+ if (context != null) {
+ RepositoryStatistics statistics = context.getRepositoryStatistics();
+ response.setContentType("application/json");
+ Writer writer = response.getWriter();
+ writer.write('{');
+ write(writer, "read", statistics.getTimeSeries(
+ RepositoryStatistics.Type.SESSION_READ_COUNTER));
+ writer.write(',');
+ write(writer, "write", statistics.getTimeSeries(
+ RepositoryStatistics.Type.SESSION_WRITE_COUNTER));
+ writer.write(',');
+ write(writer, "login", statistics.getTimeSeries(
+ RepositoryStatistics.Type.SESSION_LOGIN_COUNTER));
+ writer.write('}');
+ } else {
+ response.sendError(
+ HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+ "Jackrabbit repository internals are not available");
+ }
+ }
+
+ private void write(Writer writer, String name, TimeSeries series)
+ throws IOException {
+ writer.write('"');
+ writer.write(name);
+ writer.write('"');
+ writer.write(':');
+ writer.write('{');
+ write(writer, "second", series.getValuePerSecond());
+ writer.write(',');
+ write(writer, "minute", series.getValuePerMinute());
+ writer.write(',');
+ write(writer, "hour", series.getValuePerHour());
+ writer.write(',');
+ write(writer, "week", series.getValuePerWeek());
+ writer.write('}');
+ }
+
+ private void write(Writer writer, String name, long[] values)
+ throws IOException {
+ writer.write('"');
+ writer.write(name);
+ writer.write('"');
+ writer.write(':');
+ writer.write('[');
+ for (int i = 0; i < values.length; i++) {
+ if (i > 0) {
+ writer.write(',');
+ }
+ writer.write(String.valueOf(values[i]));
+ }
+ writer.write(']');
+ }
+}
Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/jackrabbit/StatisticsServlet.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/AbstractLoginFilter.java
===================================================================
--- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/AbstractLoginFilter.java (nonexistent)
+++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/AbstractLoginFilter.java (working copy)
@@ -0,0 +1,113 @@
+/*
+ * 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.servlet.login;
+
+import java.io.IOException;
+
+import javax.jcr.AccessDeniedException;
+import javax.jcr.Credentials;
+import javax.jcr.LoginException;
+import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.jackrabbit.servlet.ServletRepository;
+
+/**
+ *
+ * @since Apache Jackrabbit 1.6
+ */
+public abstract class AbstractLoginFilter implements Filter {
+
+ private Repository repository;
+
+ private String workspace;
+
+ private String sessionAttribute;
+
+ private String nodeAttribute;
+
+ public void init(FilterConfig config) {
+ repository = new ServletRepository(config);
+ workspace = config.getInitParameter("workspace");
+
+ sessionAttribute = config.getInitParameter(Session.class.getName());
+ if (sessionAttribute == null) {
+ sessionAttribute = Session.class.getName();
+ }
+
+ nodeAttribute = config.getInitParameter(Node.class.getName());
+ if (nodeAttribute == null) {
+ nodeAttribute = Node.class.getName();
+ }
+ }
+
+ public void destroy() {
+ }
+
+ public void doFilter(
+ ServletRequest request, ServletResponse response,
+ FilterChain chain) throws IOException, ServletException {
+ HttpServletRequest httpRequest = (HttpServletRequest) request;
+ HttpServletResponse httpResponse = (HttpServletResponse) response;
+ try {
+ Credentials credentials = getCredentials(httpRequest);
+ Session session = repository.login(credentials, workspace);
+ try {
+ request.setAttribute(sessionAttribute, session);
+ request.setAttribute(nodeAttribute, session.getRootNode());
+ chain.doFilter(request, response);
+ if (session.hasPendingChanges()) {
+ session.save();
+ }
+ } finally {
+ session.logout();
+ }
+ } catch (ServletException e) {
+ Throwable cause = e.getRootCause();
+ if (cause instanceof AccessDeniedException) {
+ httpResponse.sendError(
+ HttpServletResponse.SC_FORBIDDEN, cause.getMessage());
+ } else {
+ throw e;
+ }
+ } catch (LoginException e) {
+ httpResponse.sendError(
+ HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
+ } catch (NoSuchWorkspaceException e) {
+ throw new ServletException(
+ "Workspace " + workspace
+ + " not found in the content repository", e);
+ } catch (RepositoryException e) {
+ throw new ServletException(
+ "Unable to access the content repository", e);
+ }
+ }
+
+ protected abstract Credentials getCredentials(HttpServletRequest request);
+
+}
Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/AbstractLoginFilter.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/BasicLoginFilter.java
===================================================================
--- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/BasicLoginFilter.java (nonexistent)
+++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/BasicLoginFilter.java (working copy)
@@ -0,0 +1,38 @@
+/*
+ * 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.servlet.login;
+
+import javax.jcr.Credentials;
+import javax.jcr.SimpleCredentials;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ *
+ * @since Apache Jackrabbit 1.6
+ */
+public class BasicLoginFilter extends AbstractLoginFilter {
+
+ protected Credentials getCredentials(HttpServletRequest request) {
+ String authorization = request.getHeader("Authorization");
+ if (authorization != null) {
+ return new SimpleCredentials("TODO", "TODO".toCharArray());
+ } else {
+ return null;
+ }
+ }
+
+}
Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/BasicLoginFilter.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/ContainerLoginFilter.java
===================================================================
--- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/ContainerLoginFilter.java (nonexistent)
+++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/ContainerLoginFilter.java (working copy)
@@ -0,0 +1,64 @@
+/*
+ * 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.servlet.login;
+
+import javax.jcr.Credentials;
+import javax.jcr.SimpleCredentials;
+import javax.servlet.FilterConfig;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Login filter that relies on container authentication to provide the
+ * authenticated username of a request. This username is associated with
+ * a dummy password (empty by default, configurable through the init
+ * parameter "password") in a {@link SimpleCredentials} object that is
+ * used to log in to the underlying content repository. If no authenticated
+ * user is found, then null credentials are used.
+ *
+ * It is expected that the underlying repository is configured to simply
+ * trust the given username. If the same repository is also made available
+ * for direct logins, then a special secret password that allows logins with
+ * any username could be configured just for this filter.
+ *
+ * @since Apache Jackrabbit 1.6
+ */
+public class ContainerLoginFilter extends AbstractLoginFilter {
+
+ /**
+ * The dummy password used for the repository login. Empty by default.
+ */
+ private char[] password = new char[0];
+
+ public void init(FilterConfig config) {
+ super.init(config);
+
+ String password = config.getInitParameter("password");
+ if (password != null) {
+ this.password = password.toCharArray();
+ }
+ }
+
+ protected Credentials getCredentials(HttpServletRequest request) {
+ String user = request.getRemoteUser();
+ if (user != null) {
+ return new SimpleCredentials(user, password);
+ } else {
+ return null;
+ }
+ }
+
+}
Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/ContainerLoginFilter.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/NullLoginFilter.java
===================================================================
--- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/NullLoginFilter.java (nonexistent)
+++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/NullLoginFilter.java (working copy)
@@ -0,0 +1,43 @@
+/*
+ * 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.servlet.login;
+
+import javax.jcr.Credentials;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Login filter that always uses null credentials for logging in
+ * to the content repository. This is useful for example for public web sites
+ * where all repository access is performed using anonymous sessions. Another
+ * use case for this login filter is when login information is made available
+ * to the content repository through JAAS or some other out-of-band mechanism.
+ *
+ * @since Apache Jackrabbit 1.6
+ */
+public class NullLoginFilter extends AbstractLoginFilter {
+
+ /**
+ * Always returns null.
+ *
+ * @param request ignored
+ * @return null credentials
+ */
+ protected Credentials getCredentials(HttpServletRequest request) {
+ return null;
+ }
+
+}
Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/NullLoginFilter.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/JNDIRemoteBindingServlet.java
===================================================================
--- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/JNDIRemoteBindingServlet.java (nonexistent)
+++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/JNDIRemoteBindingServlet.java (working copy)
@@ -0,0 +1,118 @@
+/*
+ * 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.servlet.remote;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import javax.jcr.Repository;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.servlet.ServletException;
+
+import org.apache.jackrabbit.rmi.remote.RemoteRepository;
+import org.apache.jackrabbit.rmi.server.RemoteAdapterFactory;
+
+/**
+ * Servlet that binds a repository from a servlet context attribute to JNDI
+ * as a remote repository reference.
+ *
+ * The initialization parameters of this servlet are:
+ *
+ *
javax.jcr.Repository
+ *
+ * Name of the servlet context attribute that contains the repository.
+ * The default value is "javax.jcr.Repository".
+ *
+ * Name of the remote adapter factory class used to create the remote
+ * repository reference. The configured class should have public
+ * constructor that takes no arguments.
+ *
+ *
location
+ *
+ * Location where to bind the repository in the JNDI directory.
+ * The default value is
+ * "org/apache/jackrabbit/rmi/remote/RemoteRepository".
+ *
+ *
*
+ *
+ * All other init parameters are used as the JNDI environment when
+ * instantiating {@link InitialContext} for binding up the repository.
+ *
+ *
+ *
+ * @since 1.4
+ */
+public class JNDIRemoteBindingServlet extends RemoteBindingServlet {
+
+ /**
+ * Serial version UID.
+ */
+ private static final long serialVersionUID = -7984144838866544543L;
+
+ /**
+ * JNDI context to which to bind the repository.
+ */
+ private Context context;
+
+ /**
+ * Location of the repository within the JNDI context.
+ */
+ private String location =
+ RemoteRepository.class.getName().replace('.', '/');
+
+ /**
+ * Binds a repository from the servlet context in the configured RMI URL.
+ *
+ * @throws ServletException if the repository could not be bound in RMI
+ */
+ public void init() throws ServletException {
+ try {
+ Hashtable environment = new Hashtable();
+ Enumeration names = getInitParameterNames();
+ while (names.hasMoreElements()) {
+ String name = (String) names.nextElement();
+ if (name.equals("location")) {
+ location = getInitParameter(name);
+ } else if (!name.equals(Repository.class.getName())
+ && !name.equals(RemoteAdapterFactory.class.getName())) {
+ environment.put(name, getInitParameter(name));
+ }
+ }
+ context = new InitialContext(environment);
+ context.bind(location, getRemoteRepository());
+ } catch (NamingException e) {
+ throw new ServletException(
+ "Failed to bind remote repository to JNDI: " + location, e);
+ }
+ }
+
+ /**
+ * Unbinds the remote repository from JNDI.
+ */
+ public void destroy() {
+ try {
+ context.unbind(location);
+ } catch (NamingException e) {
+ log("Failed to unbind remote repository from JNDI: " + location, e);
+ }
+ }
+
+}
Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/JNDIRemoteBindingServlet.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/JNDIRemoteRepositoryServlet.java
===================================================================
--- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/JNDIRemoteRepositoryServlet.java (nonexistent)
+++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/JNDIRemoteRepositoryServlet.java (working copy)
@@ -0,0 +1,107 @@
+/*
+ * 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.servlet.remote;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.servlet.ServletException;
+
+import org.apache.jackrabbit.commons.repository.RepositoryFactory;
+import org.apache.jackrabbit.rmi.client.LocalAdapterFactory;
+import org.apache.jackrabbit.rmi.remote.RemoteRepository;
+import org.apache.jackrabbit.rmi.repository.JNDIRemoteRepositoryFactory;
+import org.apache.jackrabbit.servlet.AbstractRepositoryServlet;
+
+/**
+ * Servlet that makes a remote repository from JNDI available as an attribute
+ * in the servlet context.
+ *
+ * The supported initialization parameters of this servlet are:
+ *
+ *
javax.jcr.Repository
+ *
+ * Name of the servlet context attribute to put the repository in.
+ * The default value is "javax.jcr.Repository".
+ *
+ * Name of the local adapter factory class used to create the local
+ * adapter for the remote repository. The configured class should have
+ * public constructor that takes no arguments.
+ *
+ *
location
+ *
+ * Location of the remote repository in the JNDI directory.
+ * The default value is
+ * "org/apache/jackrabbit/rmi/remote/RemoteRepository".
+ *
+ *
*
+ *
+ * All other init parameters are used as the JNDI environment when
+ * instantiating {@link InitialContext} for looking up the repository.
+ *
+ *
+ *
+ * This servlet can also be mapped to the URL space. See
+ * {@link AbstractRepositoryServlet} for the details.
+ *
+ * @since 1.4
+ */
+public class JNDIRemoteRepositoryServlet extends RemoteRepositoryServlet {
+
+ /**
+ * Serial version UID.
+ */
+ private static final long serialVersionUID = 9029928193416404478L;
+
+ /**
+ * Returns the remote repository in the configured JNDI location.
+ *
+ * @return repository
+ * @throws RepositoryException if the repository could not be accessed
+ */
+ @Override
+ protected Repository getRepository() throws RepositoryException {
+ String location =
+ "//localhost/" + RemoteRepository.class.getName().replace('.', '/');
+ try {
+ Hashtable environment = new Hashtable();
+ Enumeration names = getInitParameterNames();
+ while (names.hasMoreElements()) {
+ String name = (String) names.nextElement();
+ if (name.equals("location")) {
+ location = getInitParameter(name);
+ } else if (!name.equals(Repository.class.getName())
+ && !name.equals(LocalAdapterFactory.class.getName())) {
+ environment.put(name, getInitParameter(name));
+ }
+ }
+ return new JNDIRemoteRepositoryFactory(
+ getLocalAdapterFactory(),
+ new InitialContext(environment), location).getRepository();
+ } catch (NamingException e) {
+ throw new RepositoryException(
+ "Repository not found: Invalid JNDI context", e);
+ }
+ }
+
+}
Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/JNDIRemoteRepositoryServlet.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RMIRemoteBindingServlet.java
===================================================================
--- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RMIRemoteBindingServlet.java (nonexistent)
+++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RMIRemoteBindingServlet.java (working copy)
@@ -0,0 +1,97 @@
+/*
+ * 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.servlet.remote;
+
+import java.net.MalformedURLException;
+import java.rmi.Naming;
+import java.rmi.NotBoundException;
+import java.rmi.RemoteException;
+
+import javax.servlet.ServletException;
+
+/**
+ * Servlet that binds a repository from a servlet context attribute in RMI.
+ *
+ * The initialization parameters of this servlet are:
+ *
+ *
javax.jcr.Repository
+ *
+ * Name of the servlet context attribute that contains the repository.
+ * The default value is "javax.jcr.Repository".
+ *
+ * Name of the remote adapter factory class used to create the remote
+ * repository reference. The configured class should have public
+ * constructor that takes no arguments.
+ *
+ *
url
+ *
+ * RMI URL where to bind the repository in. The default value is
+ * "//localhost/javax/jcr/Repository".
+ *
+ *
+ *
+ * @since 1.4
+ */
+public class RMIRemoteBindingServlet extends RemoteBindingServlet {
+
+ /**
+ * Serial version UID.
+ */
+ private static final long serialVersionUID = 1627580747678104906L;
+
+ /**
+ * Location of the repository within the JNDI context.
+ */
+ private String url;
+
+ /**
+ * Binds a repository from the servlet context in the configured RMI URL.
+ *
+ * @throws ServletException if the repository could not be bound in RMI
+ */
+ public void init() throws ServletException {
+ url = getInitParameter("url");
+ if (url == null) {
+ url = "//localhost/javax/jcr/Repository";
+ }
+ try {
+ Naming.rebind(url, getRemoteRepository());
+ } catch (MalformedURLException e) {
+ log("Invalid RMI URL: " + url, e);
+ } catch (RemoteException e) {
+ log("Failed to bind repository to RMI: " + url, e);
+ }
+ }
+
+ /**
+ * Unbinds the repository from RMI.
+ */
+ public void destroy() {
+ try {
+ Naming.unbind(url);
+ } catch (NotBoundException e) {
+ // Ignore, perhaps the reference was already manually removed
+ } catch (MalformedURLException e) {
+ // Ignore, we already logged a warning about this during init()
+ } catch (RemoteException e) {
+ log("Failed to unbind repository from RMI: " + url, e);
+ }
+ }
+
+}
Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RMIRemoteBindingServlet.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RMIRemoteRepositoryServlet.java
===================================================================
--- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RMIRemoteRepositoryServlet.java (nonexistent)
+++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RMIRemoteRepositoryServlet.java (working copy)
@@ -0,0 +1,76 @@
+/*
+ * 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.servlet.remote;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.servlet.ServletException;
+
+import org.apache.jackrabbit.rmi.repository.RMIRemoteRepositoryFactory;
+import org.apache.jackrabbit.servlet.AbstractRepositoryServlet;
+
+/**
+ * Servlet that makes a repository from RMI available as an attribute
+ * in the servlet context.
+ *
+ * The supported initialization parameters of this servlet are:
+ *
+ *
javax.jcr.Repository
+ *
+ * Name of the servlet context attribute to put the repository in.
+ * The default value is "javax.jcr.Repository".
+ *
+ * Name of the local adapter factory class used to create the local
+ * adapter for the remote repository. The configured class should have
+ * public constructor that takes no arguments.
+ *
+ *
url
+ *
+ * RMI URL of the remote repository. The default value is
+ * "//localhost/javax/jcr/Repository".
+ *
+ *
+ *
+ * This servlet can also be mapped to the URL space. See
+ * {@link AbstractRepositoryServlet} for the details.
+ *
+ * @since 1.4
+ */
+public class RMIRemoteRepositoryServlet extends RemoteRepositoryServlet {
+
+ /**
+ * Serial version UID.
+ */
+ private static final long serialVersionUID = 2410543206806054854L;
+
+ /**
+ * Creates and returns an RMI repository factory for the configured RMI URL.
+ *
+ * @return RMI repository factory
+ * @throws RepositoryException if the factory could not be created
+ */
+ @Override
+ protected Repository getRepository() throws RepositoryException {
+ return new RMIRemoteRepositoryFactory(
+ getLocalAdapterFactory(),
+ getInitParameter("url", "//localhost/javax/jcr/Repository")
+ ).getRepository();
+ }
+
+}
Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RMIRemoteRepositoryServlet.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RemoteBindingServlet.java
===================================================================
--- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RemoteBindingServlet.java (nonexistent)
+++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RemoteBindingServlet.java (working copy)
@@ -0,0 +1,139 @@
+/*
+ * 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.servlet.remote;
+
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.rmi.RemoteException;
+import java.rmi.server.RemoteObject;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.jackrabbit.rmi.remote.RemoteRepository;
+import org.apache.jackrabbit.rmi.server.RemoteAdapterFactory;
+import org.apache.jackrabbit.rmi.server.ServerAdapterFactory;
+import org.apache.jackrabbit.servlet.ServletRepository;
+
+/**
+ * Servlet that makes a repository in servlet context available as a remote
+ * repository reference. By default this servlet makes the serialized
+ * reference available through HTTP GET, but subclasses can extend this
+ * behavior to bind the remote reference to various locations like JNDI
+ * or the RMI registry.
+ *
+ * The initialization parameters of this servlet are:
+ *
+ *
javax.jcr.Repository
+ *
+ * Name of the servlet context attribute that contains the repository.
+ * The default value is "javax.jcr.Repository".
+ *
+ * Name of the remote adapter factory class used to create the remote
+ * repository reference. The configured class should have public
+ * constructor that takes no arguments.
+ *
+ *
+ *
+ * @since 1.4
+ */
+public class RemoteBindingServlet extends HttpServlet {
+
+ /**
+ * Serial version UID.
+ */
+ private static final long serialVersionUID = -162482284843619248L;
+
+ /**
+ * Remote repository.
+ */
+ private RemoteRepository remote;
+
+ /**
+ * Returns the configured remote repository reference. The remote
+ * repository is instantiated and memorized during the first call to
+ * this method.
+ *
+ * @return remote repository
+ * @throws ServletException if the repository could not be instantiated
+ */
+ protected RemoteRepository getRemoteRepository() throws ServletException {
+ if (remote == null) {
+ try {
+ RemoteAdapterFactory factory = getRemoteAdapterFactory();
+ remote = factory.getRemoteRepository(new ServletRepository(this));
+ } catch (RemoteException e) {
+ throw new ServletException(
+ "Failed to create the remote repository reference", e);
+ }
+ }
+ return remote;
+ }
+
+ /**
+ * Instantiates and returns the configured remote adapter factory.
+ *
+ * @return remote adapter factory
+ * @throws ServletException if the factory could not be instantiated
+ */
+ private RemoteAdapterFactory getRemoteAdapterFactory()
+ throws ServletException {
+ String name = getInitParameter(RemoteAdapterFactory.class.getName());
+ if (name == null) {
+ return new ServerAdapterFactory();
+ }
+ try {
+ Class factoryClass = Class.forName(name);
+ return (RemoteAdapterFactory) factoryClass.newInstance();
+ } catch (ClassNotFoundException e) {
+ throw new ServletException(
+ "Remote adapter factory class not found: " + name, e);
+ } catch (InstantiationException e) {
+ throw new ServletException(
+ "Failed to instantiate the adapter factory: " + name, e);
+ } catch (IllegalAccessException e) {
+ throw new ServletException(
+ "Adapter factory constructor is not public: " + name, e);
+ } catch (ClassCastException e) {
+ throw new ServletException(
+ "Invalid remote adapter factory class: " + name, e);
+ }
+ }
+
+ /**
+ * Outputs the remote repository reference as a serialized stream.
+ *
+ * @param request HTTP request
+ * @param response HTTP response
+ * @throws ServletException if the remote reference is not available
+ * @throws IOException on IO errors
+ */
+ protected void doGet(
+ HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ response.setContentType("application/octet-stream");
+ ObjectOutputStream output =
+ new ObjectOutputStream(response.getOutputStream());
+ output.writeObject(RemoteObject.toStub(getRemoteRepository()));
+ output.flush();
+ }
+
+}
Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RemoteBindingServlet.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RemoteRepositoryServlet.java
===================================================================
--- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RemoteRepositoryServlet.java (nonexistent)
+++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RemoteRepositoryServlet.java (working copy)
@@ -0,0 +1,81 @@
+/*
+ * 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.servlet.remote;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.rmi.client.ClientAdapterFactory;
+import org.apache.jackrabbit.rmi.client.LocalAdapterFactory;
+import org.apache.jackrabbit.servlet.AbstractRepositoryServlet;
+
+/**
+ * Abstract base class for servlets that make a remote repository available
+ * locally in the servlet context.
+ *
+ * The supported initialization parameters of this servlet are:
+ *
+ *
javax.jcr.Repository
+ *
+ * Name of the servlet context attribute to put the repository in.
+ * The default value is "javax.jcr.Repository".
+ *
+ * Name of the local adapter factory class used to create the local
+ * adapter for the remote repository. The configured class should have
+ * public constructor that takes no arguments.
+ *
+ *
+ *
+ * This servlet can also be mapped to the URL space. See
+ * {@link AbstractRepositoryServlet} for the details.
+ *
+ * @since 1.4
+ */
+public abstract class RemoteRepositoryServlet
+ extends AbstractRepositoryServlet {
+
+ /**
+ * Instantiates and returns the configured local adapter factory.
+ *
+ * @return local adapter factory
+ * @throws RepositoryException if the factory could not be instantiated
+ */
+ protected LocalAdapterFactory getLocalAdapterFactory()
+ throws RepositoryException {
+ String name = getInitParameter(
+ LocalAdapterFactory.class.getName(),
+ ClientAdapterFactory.class.getName());
+ try {
+ Class factoryClass = Class.forName(name);
+ return (LocalAdapterFactory) factoryClass.newInstance();
+ } catch (ClassNotFoundException e) {
+ throw new RepositoryException(
+ "Local adapter factory class not found: " + name, e);
+ } catch (InstantiationException e) {
+ throw new RepositoryException(
+ "Failed to instantiate the adapter factory: " + name, e);
+ } catch (IllegalAccessException e) {
+ throw new RepositoryException(
+ "Adapter factory constructor is not public: " + name, e);
+ } catch (ClassCastException e) {
+ throw new RepositoryException(
+ "Invalid local adapter factory class: " + name, e);
+ }
+ }
+
+}
Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RemoteRepositoryServlet.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/URLRemoteBindingServlet.java
===================================================================
--- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/URLRemoteBindingServlet.java (nonexistent)
+++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/URLRemoteBindingServlet.java (working copy)
@@ -0,0 +1,84 @@
+/*
+ * 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.servlet.remote;
+
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.servlet.ServletException;
+
+/**
+ * Servlet that writes the remote reference of a repository in the servlet
+ * context to the configured URL.
+ *
+ * The initialization parameters of this servlet are:
+ *
+ *
javax.jcr.Repository
+ *
+ * Name of the servlet context attribute that contains the repository.
+ * The default value is "javax.jcr.Repository".
+ *
+ * Name of the remote adapter factory class used to create the remote
+ * repository reference. The configured class should have public
+ * constructor that takes no arguments.
+ *
+ *
url
+ *
+ * URL where to store the remote repository reference.
+ *
+ *
+ *
+ * @since 1.4
+ */
+public class URLRemoteBindingServlet extends RemoteBindingServlet {
+
+ /**
+ * Serial version UID.
+ */
+ private static final long serialVersionUID = 3187755583290121129L;
+
+ /**
+ * Writes the remote reference of a repository in the servlet context
+ * to the configured URL.
+ *
+ * @throws ServletException if the URL could not be written to
+ */
+ public void init() throws ServletException {
+ String url = getInitParameter("url");
+ if (url == null) {
+ throw new ServletException("Missing init parameter: url");
+ }
+ try {
+ ObjectOutputStream output = new ObjectOutputStream(
+ new URL(url).openConnection().getOutputStream());
+ try {
+ output.writeObject(getRemoteRepository());
+ } finally {
+ output.close();
+ }
+ } catch (MalformedURLException e) {
+ throw new ServletException("Malformed URL: " + url, e);
+ } catch (IOException e) {
+ throw new ServletException("Failed to write to URL: " + url, e);
+ }
+ }
+
+}
Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/URLRemoteBindingServlet.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/URLRemoteRepositoryServlet.java
===================================================================
--- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/URLRemoteRepositoryServlet.java (nonexistent)
+++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/URLRemoteRepositoryServlet.java (working copy)
@@ -0,0 +1,84 @@
+/*
+ * 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.servlet.remote;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.rmi.repository.URLRemoteRepositoryFactory;
+import org.apache.jackrabbit.servlet.AbstractRepositoryServlet;
+
+/**
+ * Servlet that makes a remote repository from a ULR available as an attribute
+ * in the servlet context.
+ *
+ * The supported initialization parameters of this servlet are:
+ *
+ *
javax.jcr.Repository
+ *
+ * Name of the servlet context attribute to put the repository in.
+ * The default value is "javax.jcr.Repository".
+ *
+ * Name of the local adapter factory class used to create the local
+ * adapter for the remote repository. The configured class should have
+ * public constructor that takes no arguments.
+ *
+ *
url
+ *
+ * URL of the remote repository.
+ *
+ *
+ *
+ * This servlet can also be mapped to the URL space. See
+ * {@link AbstractRepositoryServlet} for the details.
+ *
+ * @since 1.4
+ */
+public class URLRemoteRepositoryServlet extends RemoteRepositoryServlet {
+
+ /**
+ * Serial version UID.
+ */
+ private static final long serialVersionUID = 6144781813459102448L;
+
+ /**
+ * Returns the remote repository at the given URL.
+ *
+ * @return repository
+ * @throws RepositoryException if the repository could not be accessed
+ */
+ @Override
+ protected Repository getRepository() throws RepositoryException {
+ String url = getInitParameter("url");
+ if (url == null) {
+ throw new RepositoryException("Missing init parameter: url");
+ }
+
+ try {
+ return new URLRemoteRepositoryFactory(
+ getLocalAdapterFactory(), new URL(url)).getRepository();
+ } catch (MalformedURLException e) {
+ throw new RepositoryException("Invalid repository URL: " + url, e);
+ }
+ }
+
+}
Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/URLRemoteRepositoryServlet.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet
===================================================================
--- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet (nonexistent)
+++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet (working copy)
Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,5 ##
+target
+.*
+*.iml
+*.ipr
+*.iws
Index: jackrabbit-jcr-servlet-project/pom.xml
===================================================================
--- jackrabbit-jcr-servlet-project/pom.xml (nonexistent)
+++ jackrabbit-jcr-servlet-project/pom.xml (working copy)
@@ -0,0 +1,39 @@
+
+ 4.0.0
+
+ org.apache.jackrabbit
+ jackrabbit-parent
+ 2.21.16-SNAPSHOT
+ ../jackrabbit-parent/pom.xml
+
+ jackrabbit-jcr-servlet-project
+ pom
+ Jackrabbit WebDAV Project
+
+ jackrabbit-jcr-servlet
+ jackrabbit-jcr-servlet-jakarta
+
+
+
+ javax.jcr
+ jcr
+
+
+ org.apache.jackrabbit
+ jackrabbit-jcr-commons
+ ${project.version}
+
+
+ org.apache.jackrabbit
+ jackrabbit-jcr-rmi
+ ${project.version}
+ true
+
+
+ org.apache.jackrabbit
+ jackrabbit-core
+ ${project.version}
+ true
+
+
+
\ No newline at end of file
Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/pom.xml
===================================================================
--- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/pom.xml (nonexistent)
+++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/pom.xml (working copy)
@@ -0,0 +1,90 @@
+
+ 4.0.0
+
+ org.apache.jackrabbit
+ jackrabbit-webapp-project
+ 2.21.16-SNAPSHOT
+
+ jackrabbit-webapp-jakarta
+
+ 10.1.6
+
+
+
+
+ org.eclipse.transformer
+ transformer-maven-plugin
+ 0.5.0
+ true
+
+
+ true
+
+
+
+
+ default-jar
+
+ jar
+
+
+
+ org.apache.jackrabbit
+ jackrabbit-webapp
+ ${project.version}
+
+
+
+
+
+
+
+
+
+ apache-release
+
+
+
+ org.eclipse.transformer
+ transformer-maven-plugin
+ 0.5.0
+ true
+
+
+ true
+
+
+
+
+ source-jar
+
+ jar
+
+
+
+ org.apache.jackrabbit
+ jackrabbit-webapp
+ ${project.version}
+ sources
+
+
+
+
+
+
+
+
+
+
+
+ org.apache.jackrabbit
+ jackrabbit-jcr-server-jakarta
+ ${project.version}
+
+
+ org.apache.jackrabbit
+ jackrabbit-jcr-servlet-jakarta
+ ${project.version}
+
+
+
\ No newline at end of file
Index: jackrabbit-webdav-project/jackrabbit-webdav/pom.xml
===================================================================
--- jackrabbit-webdav-project/jackrabbit-webdav/pom.xml (nonexistent)
+++ jackrabbit-webdav-project/jackrabbit-webdav/pom.xml (working copy)
@@ -0,0 +1,63 @@
+
+
+
+
+
+ 4.0.0
+
+
+
+
+
+ org.apache.jackrabbit
+ jackrabbit-webdav-project
+ 2.21.16-SNAPSHOT
+
+ jackrabbit-webdav
+ bundle
+ Jackrabbit WebDAV Library
+ Generic WebDAV Library
+
+
+
+
+ org.apache.felix
+ maven-bundle-plugin
+ true
+
+
+ maven-surefire-plugin
+
+
+ **/*TestAll.java
+
+ once
+ ${test.opts}
+
+
+
+
+
+
+
+ javax.servlet
+ javax.servlet-api
+ provided
+
+
+
Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/pom.xml
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/README.txt
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/README.txt (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/README.txt (working copy)
@@ -0,0 +1,93 @@
+================================
+Welcome to Jackrabbit JCR Server
+================================
+
+This is the JCR Server component of the Apache Jackrabbit project.
+This component contains two WebDAV based JCR server implementations:
+
+ 1) WebDAV server ('simple')
+
+ DAV1,2 compliant WebDAV server implementation to access a
+ JSR170 repository.
+
+ Futher information such as configuration as well as the
+ SimpleWebdavServlet itself may be found in the 'webapp' project.
+
+ Packages:
+ - org.apache.jackrabbit.server = server
+ - org.apache.jackrabbit.server.io = import/export
+ - org.apache.jackrabbit.webdav.simple = dav-resource implementation + config.
+
+ Servlet (webapp project):
+ - org.apache.jackrabbit.j2ee.SimpleWebdavServlet.java
+
+
+ 2) 'jcr' server:
+
+ Server used to remove JSR170 calls via WebDAV.
+ No particular effort to be compliant to WebDAV related RFCs.
+
+ The 'client' counterpart of this server is under development and
+ can be found within the /contrib/spi contribution.
+
+ Packages:
+ - org.apache.jackrabbit.server = server
+ - org.apache.jackrabbit.server.jcr = jcr-server specific server part
+ - org.apache.jackrabbit.webdav.jcr = dav-resources, reports, properties
+
+ Servlet (webapp project):
+ - org.apache.jackrabbit.j2ee.JCRServerServlet.java
+
+ Further reading:
+ - http://www.day.com/jsr170/server/JCR_Webdav_Protocol.zip
+
+Things to do
+============
+
+-------------------------------------------------------------------
+TODO 'jcr' server implementation
+-------------------------------------------------------------------
+
+general
+
+- undo incomplete changes in case of exception
+- multistatus fuer lock, copy, move, delete wherever required.
+- DAV:supported-live-property-set
+- timeout: remove expired locks/subscriptions
+- improve definition methods/compliance-class
+- OPTIONS to *-request-uri (according to RFC 2616)
+
+
+lock
+
+- implement session-scoped locks. this includes:
+ > uncommenting supported-locks entry
+ > build caching mechanism for session in case of session-scoped locks.
+ > retrieval of cached sessions (currently not possible from IfHeader).
+ > open issue in JCR: scope of lock cannot be retrieved.
+
+- JCR lock-token currently not checked for compliance with RFC2518. If the
+ token is modified accordingly, setting the lock-token to the subsequent
+ session (currently in the WebdavRequestImpl) must be aware of that change....
+
+- transaction locks
+ - lock returned upon lock-discovery
+ - remove after timeout (>> releasing cached sessions)
+ - define reasonable timeout or make timeout configurable
+ - createLock must respect existing locks in the subtree, for lock is always deep.
+ - repository transactions ('global') are only possible with jackrabbit, where
+ the session represents the XAResource itself.
+ since j2ee explicitely requires any usertransaction to be completed
+ upon the end of the servletes service method.
+ general review necessary....
+
+
+observation
+
+- make sure all expired subscriptions are removed.
+- subscription: reasonable default/max timeout make it configurable...
+
+versioning
+
+- Additional VERSION-CONTROL Semantics with workspace not implemented.
+- BaseLine/Activity not respected yet (see jsr283)
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/README.txt
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/pom.xml
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/pom.xml (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/pom.xml (working copy)
@@ -0,0 +1,203 @@
+
+
+
+
+
+ 4.0.0
+
+
+
+
+
+ org.apache.jackrabbit
+ jackrabbit-jcr-server-project
+ 2.21.16-SNAPSHOT
+
+ jackrabbit-jcr-server
+ Jackrabbit JCR Server
+ WebDAV server implementations for JCR
+ bundle
+
+
+
+
+ maven-surefire-plugin
+
+
+ **/*Test.java
+
+ once
+ ${test.opts}
+
+
+ derby.stream.error.file
+ target/derby.log
+
+
+
+
+
+ org.apache.felix
+ maven-scr-plugin
+ 1.26.4
+
+
+ generate-scr-scrdescriptor
+
+ scr
+
+
+
+ The Apache Software Foundation
+
+
+
+
+
+
+ org.apache.felix
+ maven-bundle-plugin
+ true
+
+
+
+ org.apache.jackrabbit.server
+
+
+
+
+
+ org.apache.rat
+ apache-rat-plugin
+
+
+ src/test/resources/keystore
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ test-jar
+
+
+
+
+
+
+
+
+
+ org.eclipse.m2e
+ lifecycle-mapping
+ 1.0.0
+
+
+
+
+
+ org.apache.felix
+
+ maven-scr-plugin
+
+
+ [1.7.2,)
+
+
+ scr
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ integrationTesting
+
+ litmus
+
+
+
+
+ maven-surefire-plugin
+
+
+
+ jackrabbit.test.integration
+ true
+
+
+ litmus
+ ${litmus}
+
+
+ derby.system.durability
+ test
+
+
+ derby.storage.fileSyncTransactionLog
+ true
+
+
+ derby.stream.error.file
+ target/derby.log
+
+
+ known.issues
+
+
+ org.apache.jackrabbit.webdav.server.RFC4918IfHeaderTest#testPutIfEtag
+
+ org.apache.jackrabbit.webdav.server.RFC4918IfHeaderTest#testPutIfLockToken
+
+
+
+
+
+
+
+
+
+
+
+
+ org.apache.jackrabbit
+ jackrabbit-webdav
+ ${project.version}
+
+
+ javax.servlet
+ javax.servlet-api
+ provided
+
+
+
+
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/pom.xml
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/appended-resources/META-INF/NOTICE
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/appended-resources/META-INF/NOTICE (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/appended-resources/META-INF/NOTICE (working copy)
@@ -0,0 +1,2 @@
+Based on source code originally developed by
+Day Software (http://www.day.com/).
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/appended-resources/META-INF/NOTICE
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/BasicCredentialsProvider.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/BasicCredentialsProvider.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/BasicCredentialsProvider.java (working copy)
@@ -0,0 +1,120 @@
+/*
+ * 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;
+
+import org.apache.jackrabbit.util.Base64;
+import org.apache.jackrabbit.webdav.DavConstants;
+
+import javax.jcr.Credentials;
+import javax.jcr.LoginException;
+import javax.jcr.SimpleCredentials;
+import javax.jcr.GuestCredentials;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * This Class implements a credentials provider that extracts the credentials
+ * from the 'WWW-Authenticate' header and only supports 'Basic' authentication.
+ */
+public class BasicCredentialsProvider implements CredentialsProvider {
+
+ public static final String EMPTY_DEFAULT_HEADER_VALUE = "";
+ public static final String GUEST_DEFAULT_HEADER_VALUE = "guestcredentials";
+
+ private final String defaultHeaderValue;
+
+ /**
+ * Constructs a new BasicCredentialsProvider with the given default
+ * value. See {@link #getCredentials} for details.
+ *
+ * @param defaultHeaderValue
+ */
+ public BasicCredentialsProvider(String defaultHeaderValue) {
+ this.defaultHeaderValue = defaultHeaderValue;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * Build a {@link Credentials} object for the given authorization header.
+ * The creds may be used to login to the repository. If the specified header
+ * string is null the behaviour depends on the
+ * {@link #defaultHeaderValue} field:
+ *
+ *
if this field is null, a LoginException is thrown.
+ * This is suitable for clients (eg. webdav clients) for with
+ * sending a proper authorization header is not possible, if the
+ * server never send a 401.
+ *
if this an empty string, null-credentials are returned, thus
+ * forcing an null login on the repository
+ *
if this field has a 'user:password' value, the respective
+ * simple credentials are generated.
+ *
+ *
+ * If the request header is present but cannot be parsed a
+ * ServletException is thrown.
+ *
+ * @param request the servlet request
+ * @return credentials or null.
+ * @throws ServletException If the Authorization header cannot be decoded.
+ * @throws LoginException if no suitable auth header and missing-auth-mapping
+ * is not present
+ */
+ public Credentials getCredentials(HttpServletRequest request)
+ throws LoginException, ServletException {
+ try {
+ String authHeader = request.getHeader(DavConstants.HEADER_AUTHORIZATION);
+ if (authHeader != null) {
+ String[] authStr = authHeader.split(" ");
+ if (authStr.length >= 2 && authStr[0].equalsIgnoreCase(HttpServletRequest.BASIC_AUTH)) {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ Base64.decode(authStr[1].toCharArray(), out);
+ String decAuthStr = out.toString("ISO-8859-1");
+ int pos = decAuthStr.indexOf(':');
+ String userid = decAuthStr.substring(0, pos);
+ String passwd = decAuthStr.substring(pos + 1);
+ return new SimpleCredentials(userid, passwd.toCharArray());
+ }
+ throw new ServletException("Unable to decode authorization.");
+ } else {
+ // check special handling
+ if (defaultHeaderValue == null) {
+ throw new LoginException();
+ } else if (EMPTY_DEFAULT_HEADER_VALUE.equals(defaultHeaderValue)) {
+ return null;
+ } else if (GUEST_DEFAULT_HEADER_VALUE.equals(defaultHeaderValue)) {
+ return new GuestCredentials();
+ } else {
+ int pos = defaultHeaderValue.indexOf(':');
+ if (pos < 0) {
+ return new SimpleCredentials(defaultHeaderValue, new char[0]);
+ } else {
+ return new SimpleCredentials(
+ defaultHeaderValue.substring(0, pos),
+ defaultHeaderValue.substring(pos+1).toCharArray()
+ );
+ }
+ }
+ }
+ } catch (IOException e) {
+ throw new ServletException("Unable to decode authorization: " + e.toString());
+ }
+ }
+
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/BasicCredentialsProvider.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+author date id revision url
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/CredentialsProvider.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/CredentialsProvider.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/CredentialsProvider.java (working copy)
@@ -0,0 +1,39 @@
+/*
+ * 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;
+
+import javax.jcr.Credentials;
+import javax.jcr.LoginException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * This Interface defines a provider for the credentials.
+ */
+public interface CredentialsProvider {
+
+ /**
+ * Extracts the credentials from the given servlet request.
+ *
+ * @param request
+ * @return the credentials or null
+ * @throws LoginException if the credentials are invalid
+ * @throws ServletException if an error occurs
+ */
+ public Credentials getCredentials(HttpServletRequest request)
+ throws LoginException, ServletException;
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/CredentialsProvider.java
___________________________________________________________________
Added: svn
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/SessionProvider.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/SessionProvider.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/SessionProvider.java (working copy)
@@ -0,0 +1,51 @@
+/*
+ * 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;
+
+import javax.jcr.LoginException;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * This Interface defines a provider for repository sessions
+ */
+public interface SessionProvider {
+
+ /**
+ * Provides the repository session suitable for the given request.
+ *
+ * @param request
+ * @param rep the repository to login
+ * @param workspace the workspace name
+ * @return the session or null
+ * @throws LoginException if the credentials are invalid
+ * @throws ServletException if an error occurs
+ */
+ public Session getSession(HttpServletRequest request, Repository rep, String workspace)
+ throws LoginException, ServletException, RepositoryException;
+
+ /**
+ * Informs this provider that the session acquired by a previous
+ * {@link SessionProvider#getSession} call is no longer needed.
+ *
+ * @param session
+ */
+ public void releaseSession(Session session);
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/SessionProvider.java
___________________________________________________________________
Added: svn
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/SessionProviderImpl.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/SessionProviderImpl.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/SessionProviderImpl.java (working copy)
@@ -0,0 +1,109 @@
+/*
+ * 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;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jcr.Credentials;
+import javax.jcr.LoginException;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * This class implements a default session provider based on a given
+ * {@link CredentialsProvider credentials provider}. Additionally,
+ * since Jackrabbit 2.4, if another session provider is available as
+ * the "org.apache.jackrabbit.server.SessionProvider" request attribute,
+ * then that provider is asked first for a session before the default
+ * credential-based login mechanism is used.
+ */
+public class SessionProviderImpl implements SessionProvider {
+
+ /**
+ * the credentials provider
+ */
+ private CredentialsProvider cp;
+
+ /**
+ * Map of sessions acquired from custom session providers looked up
+ * from request attributes. We need to keep track of such providers
+ * so we can route the {@link #releaseSession(Session)} call to the
+ * correct provider.
+ */
+ private final Map externalSessions =
+ Collections.synchronizedMap(new HashMap());
+
+ /**
+ * Creates a new SessionProvider
+ *
+ * @param cp
+ */
+ public SessionProviderImpl(CredentialsProvider cp) {
+ this.cp = cp;
+ }
+
+ /**
+ * {@inheritDoc }
+ */
+ public Session getSession(HttpServletRequest request,
+ Repository repository, String workspace) throws LoginException,
+ RepositoryException, ServletException {
+ Session s = null;
+
+ // JCR-3222: Check if a custom session provider is available as a
+ // request attribute. If one is available, ask it first for a session.
+ Object object = request.getAttribute(SessionProvider.class.getName());
+ if (object instanceof SessionProvider) {
+ SessionProvider provider = (SessionProvider) object;
+ s = provider.getSession(request, repository, workspace);
+ if (s != null) {
+ externalSessions.put(s, provider);
+ }
+ }
+
+ if (s == null) {
+ Credentials creds = cp.getCredentials(request);
+ if (creds == null) {
+ s = repository.login(workspace);
+ } else {
+ s = repository.login(creds, workspace);
+ }
+ }
+
+ return s;
+ }
+
+ /**
+ * {@inheritDoc }
+ */
+ public void releaseSession(Session session) {
+ // JCR-3222: If the session was acquired from a custom session
+ // provider, we need to ask that provider to release the session.
+ SessionProvider provider = externalSessions.remove(session);
+ if (provider != null) {
+ provider.releaseSession(session);
+ } else {
+ session.logout();
+ }
+ }
+
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/SessionProviderImpl.java
___________________________________________________________________
Added: svn
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/AbstractExportContext.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/AbstractExportContext.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/AbstractExportContext.java (working copy)
@@ -0,0 +1,70 @@
+/*
+ * 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.Item;
+
+/**
+ * AbstractExportContext covers methods common to most ExportContext
+ * implementations.
+ */
+public abstract class AbstractExportContext implements ExportContext {
+
+ private static Logger log = LoggerFactory.getLogger(AbstractExportContext.class);
+
+ private final IOListener ioListener;
+ private final Item exportRoot;
+ private final boolean hasStream;
+
+ protected boolean completed;
+
+ public AbstractExportContext(
+ Item exportRoot, boolean hasStream, IOListener ioListener) {
+ this.exportRoot = exportRoot;
+ this.hasStream = hasStream;
+ this.ioListener = (ioListener != null) ? ioListener : new DefaultIOListener(log);
+ }
+
+ public IOListener getIOListener() {
+ return ioListener;
+ }
+
+ public Item getExportRoot() {
+ return exportRoot;
+ }
+
+ public boolean hasStream() {
+ return hasStream;
+ }
+
+ public void informCompleted(boolean success) {
+ completed = true;
+ }
+
+ public boolean isCompleted() {
+ return completed;
+ }
+
+ protected void checkCompleted() {
+ if (completed) {
+ throw new IllegalStateException("ExportContext has already been finalized.");
+ }
+ }
+}
\ No newline at end of file
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/AbstractExportContext.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+author date id revision url
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/BoundedInputStream.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/BoundedInputStream.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/BoundedInputStream.java (working copy)
@@ -0,0 +1,183 @@
+/*
+ * 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 java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * This is a stream that will only supply bytes up to a certain length - if its
+ * position goes above that, it will stop.
+ *
+ * This is useful to wrap ServletInputStreams. The ServletInputStream will block
+ * if you try to read content from it that isn't there, because it doesn't know
+ * whether the content hasn't arrived yet or whether the content has finished.
+ * So, one of these, initialized with the Content-length sent in the
+ * ServletInputStream's header, will stop it blocking, providing it's been sent
+ * with a correct content length.
+ *
+ * @author InigoSurguy
+ */
+public class BoundedInputStream extends InputStream {
+
+ /** the wrapped input stream */
+ private final InputStream in;
+
+ /** the max length to provide */
+ private final int max;
+
+ /** the number of bytes already returned */
+ private int pos = 0;
+
+ /** the marked position */
+ private int mark = -1;
+
+ /** flag if close should be propagated */
+ private boolean propagateClose = true;
+
+ /**
+ * Creates a new BoundedInputStream that wraps the given input
+ * stream and limits it to a certain size.
+ *
+ * @param in The wrapped input stream
+ * @param size The maximum number of bytes to return
+ */
+ public BoundedInputStream(InputStream in, long size) {
+ // Some badly designed methods - eg the servlet API - overload length
+ // such that "-1" means stream finished
+ this.max = (int) size;
+ this.in = in;
+ }
+
+ public BoundedInputStream(InputStream in) {
+ this(in, -1);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int read() throws IOException {
+ if (max>=0 && pos==max) {
+ return -1;
+ }
+ int result = in.read();
+ pos++;
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int read(byte[] b) throws IOException {
+ return this.read(b, 0, b.length);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ if (max>=0 && pos>=max) {
+ return -1;
+ }
+ int maxRead = max>=0 ? Math.min(len, max-pos) : len;
+ int bytesRead = in.read(b, off, maxRead);
+
+ if (bytesRead==-1) {
+ return -1;
+ }
+
+ pos+=bytesRead;
+ return bytesRead;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public long skip(long n) throws IOException {
+ long toSkip = max>=0 ? Math.min(n, max-pos) : n;
+ long skippedBytes = in.skip(toSkip);
+ pos+=skippedBytes;
+ return skippedBytes;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int available() throws IOException {
+ if (max>=0 && pos>=max) {
+ return 0;
+ }
+ return in.available();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return in.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void close() throws IOException {
+ if (propagateClose) {
+ in.close();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized void reset() throws IOException {
+ in.reset();
+ pos = mark;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized void mark(int readlimit) {
+ in.mark(readlimit);
+ mark = pos;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean markSupported() {
+ return in.markSupported();
+ }
+
+ public boolean isPropagateClose() {
+ return propagateClose;
+ }
+
+ public void setPropagateClose(boolean propagateClose) {
+ this.propagateClose = propagateClose;
+ }
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/BoundedInputStream.java
___________________________________________________________________
Added: svn
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveContext.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveContext.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveContext.java (working copy)
@@ -0,0 +1,43 @@
+/*
+ * 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 javax.jcr.Session;
+import javax.jcr.Workspace;
+
+/**
+ * CopyMoveContext...
+ */
+public interface CopyMoveContext {
+
+ /**
+ * @return true if this context defines a shallow copy.
+ */
+ boolean isShallowCopy();
+
+ /**
+ * @return the jcr session associated with this context.
+ */
+ Session getSession();
+
+ /**
+ * @return The JCR workspace associated with this context.
+ * @throws RepositoryException If an error occurs.
+ */
+ Workspace getWorkspace() throws RepositoryException;
+}
\ No newline at end of file
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveContext.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision Rev URL
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveContextImpl.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveContextImpl.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveContextImpl.java (working copy)
@@ -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.jackrabbit.server.io;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Workspace;
+
+/**
+ * CopyMoveContextImpl...
+ */
+public class CopyMoveContextImpl implements CopyMoveContext {
+
+ private final boolean isShallow;
+ private final Session session;
+
+ public CopyMoveContextImpl(Session session) {
+ this(session, false);
+ }
+
+ public CopyMoveContextImpl(Session session, boolean isShallowCopy) {
+ this.isShallow = isShallowCopy;
+ this.session = session;
+ }
+
+ //----------------------------------------------------< CopyMoveContext >---
+ /**
+ * @see org.apache.jackrabbit.server.io.CopyMoveContext#isShallowCopy()
+ */
+ public boolean isShallowCopy() {
+ return isShallow;
+ }
+
+ /**
+ * @see org.apache.jackrabbit.server.io.CopyMoveContext#getSession()
+ */
+ public Session getSession() {
+ return session;
+ }
+
+ /**
+ * @see org.apache.jackrabbit.server.io.CopyMoveContext#getWorkspace()
+ */
+ public Workspace getWorkspace() throws RepositoryException {
+ return session.getWorkspace();
+ }
+}
\ No newline at end of file
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveContextImpl.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision Rev URL
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveHandler.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveHandler.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveHandler.java (working copy)
@@ -0,0 +1,75 @@
+/*
+ * 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.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavResource;
+
+/**
+ * CopyMoveHandler...
+ */
+public interface CopyMoveHandler {
+
+ /**
+ * Validates if this handler is able to execute a copy with the given
+ * parameters.
+ *
+ * @param context The context of the copy.
+ * @param source The source of the copy.
+ * @param destination The destination of the copy.
+ * @return true if this instance can handle a copy with the given parameters;
+ * false otherwise.
+ */
+ public boolean canCopy(CopyMoveContext context, DavResource source, DavResource destination);
+
+ /**
+ * Executes the copy with the given parameters.
+ *
+ * @param context The context of the copy.
+ * @param source The source of the copy.
+ * @param destination The destination of the copy.
+ * @return true if this instance successfully executed the copy operation
+ * with the given parameters; false otherwise.
+ * @throws DavException If an error occurs.
+ */
+ public boolean copy(CopyMoveContext context, DavResource source, DavResource destination) throws DavException;
+
+ /**
+ * Validates if this handler is able to execute a move with the given
+ * parameters.
+ *
+ * @param context The context of the move.
+ * @param source The source of the move.
+ * @param destination The destination of the move.
+ * @return true if this instance successfully executed the move operation
+ * with the given parameters; false otherwise.
+ */
+ public boolean canMove(CopyMoveContext context, DavResource source, DavResource destination);
+
+ /**
+ * Executes the move with the given parameters.
+ *
+ * @param context The context of the move.
+ * @param source The source of the move.
+ * @param destination The destination of the move.
+ * @return true if this instance successfully executed the move operation
+ * with the given parameters;
+ * false otherwise.
+ * @throws DavException If an error occurs.
+ */
+ public boolean move(CopyMoveContext context, DavResource source, DavResource destination) throws DavException;
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveHandler.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision Rev URL
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveManager.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveManager.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveManager.java (working copy)
@@ -0,0 +1,62 @@
+/*
+ * 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.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavResource;
+
+/**
+ * CopyMoveManager...
+ */
+public interface CopyMoveManager {
+
+ /**
+ * Handles the copy command
+ *
+ * @param context The context used for this copy operation.
+ * @param source The source of the copy.
+ * @param destination The destination of the copy.
+ * @return true if the copy succeeded.
+ * @throws DavException If an error occurs.
+ */
+ public boolean copy(CopyMoveContext context, DavResource source, DavResource destination) throws DavException;
+
+ /**
+ * Handles the move command
+ *
+ * @param context The context used for this move operation.
+ * @param source The source of the move.
+ * @param destination The destination of the move.
+ * @return true if the move succeeded.
+ * @throws DavException If an error occurs.
+ */
+ public boolean move(CopyMoveContext context, DavResource source, DavResource destination) throws DavException;
+
+ /**
+ * Adds the specified handler to the list of handlers.
+ *
+ * @param copyMoveHandler handler to be added
+ */
+ public void addCopyMoveHandler(CopyMoveHandler copyMoveHandler);
+
+ /**
+ * Returns all handlers that have been added to this manager.
+ *
+ * @return Array of all handlers
+ */
+ public CopyMoveHandler[] getCopyMoveHandlers();
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveManager.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision Rev URL
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveManagerImpl.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveManagerImpl.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveManagerImpl.java (working copy)
@@ -0,0 +1,100 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.List;
+
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavResource;
+
+/**
+ * CopyMoveManagerImpl...
+ */
+public class CopyMoveManagerImpl implements CopyMoveManager {
+
+ private static CopyMoveManager DEFAULT_MANAGER;
+
+ private final List copyMoveHandlers = new ArrayList();
+
+ /**
+ * Create a new CopyMoveManagerImpl.
+ */
+ public CopyMoveManagerImpl() {
+ }
+
+ //----------------------------------------------------< CopyMoveManager >---
+ /**
+ * @see CopyMoveManager#copy(CopyMoveContext,org.apache.jackrabbit.webdav.DavResource,org.apache.jackrabbit.webdav.DavResource)
+ */
+ public boolean copy(CopyMoveContext context, DavResource source, DavResource destination) throws DavException {
+ boolean success = false;
+ CopyMoveHandler[] copyMoveHandlers = getCopyMoveHandlers();
+ for (int i = 0; i < copyMoveHandlers.length && !success; i++) {
+ CopyMoveHandler cmh = copyMoveHandlers[i];
+ if (cmh.canCopy(context, source, destination)) {
+ success = cmh.copy(context, source, destination);
+ }
+ }
+ return success;
+ }
+
+ /**
+ * @see CopyMoveManager#move(CopyMoveContext,org.apache.jackrabbit.webdav.DavResource,org.apache.jackrabbit.webdav.DavResource)
+ */
+ public boolean move(CopyMoveContext context, DavResource source, DavResource destination) throws DavException {
+ boolean success = false;
+ CopyMoveHandler[] copyMoveHandlers = getCopyMoveHandlers();
+ for (int i = 0; i < copyMoveHandlers.length && !success; i++) {
+ CopyMoveHandler cmh = copyMoveHandlers[i];
+ if (cmh.canMove(context, source, destination)) {
+ success = cmh.move(context, source, destination);
+ }
+ }
+ return success;
+ }
+
+ /**
+ * @see org.apache.jackrabbit.server.io.CopyMoveManager#addCopyMoveHandler(CopyMoveHandler)
+ */
+ public void addCopyMoveHandler(CopyMoveHandler copyMoveHandler) {
+ if (copyMoveHandler == null) {
+ throw new IllegalArgumentException("'null' is not a valid copyMoveHandler.");
+ }
+ copyMoveHandlers.add(copyMoveHandler);
+ }
+
+ /**
+ * @see CopyMoveManager#getCopyMoveHandlers()
+ */
+ public CopyMoveHandler[] getCopyMoveHandlers() {
+ return copyMoveHandlers.toArray(new CopyMoveHandler[copyMoveHandlers.size()]);
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ * @return an instance of CopyMoveManager populated with default handlers.
+ */
+ public static CopyMoveManager getDefaultManager() {
+ if (DEFAULT_MANAGER == null) {
+ CopyMoveManager manager = new CopyMoveManagerImpl();
+ manager.addCopyMoveHandler(new DefaultHandler());
+ DEFAULT_MANAGER = manager;
+ }
+ return DEFAULT_MANAGER;
+ }
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveManagerImpl.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision Rev URL
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DefaultHandler.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DefaultHandler.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DefaultHandler.java (working copy)
@@ -0,0 +1,867 @@
+/*
+ * 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.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.commons.NamespaceHelper;
+import org.apache.jackrabbit.util.ISO9075;
+import org.apache.jackrabbit.util.Text;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavResource;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.jcr.JcrDavException;
+import org.apache.jackrabbit.webdav.xml.Namespace;
+import org.apache.jackrabbit.webdav.property.DavPropertyName;
+import org.apache.jackrabbit.webdav.property.DavProperty;
+import org.apache.jackrabbit.webdav.property.PropEntry;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.metadata.TikaCoreProperties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Item;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.PropertyIterator;
+import javax.jcr.Session;
+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;
+
+/**
+ * DefaultHandler implements a simple IOHandler that creates 'file'
+ * and 'folder' nodes. This handler will create the following nodes:
+ *
+ *
New Collection: creates a new node with the {@link #getCollectionNodeType()
+ * collection nodetype}. The name of the node corresponds to the systemId
+ * present on the import context.
+ *
+ *
New Non-Collection: first creates a new node with the {@link #getNodeType()
+ * non-collection nodetype}. The name of the node corresponds to the systemId
+ * present on the import context. Below it creates a node with name
+ * {@link JcrConstants#JCR_CONTENT jcr:content} and the nodetype specified
+ * by {@link #getContentNodeType()}.
+ *
+ *
+ * Import of the content:
+ * The content is imported to the {@link JcrConstants#JCR_DATA} property of the
+ * content node. By default this handler will fail on a attempt to create/replace
+ * a collection if {@link ImportContext#hasStream()} is true.
+ * 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, PropertyHandler, CopyMoveHandler, DeleteHandler {
+
+ private static Logger log = LoggerFactory.getLogger(DefaultHandler.class);
+
+ private String collectionNodetype;
+
+ private String defaultNodetype;
+
+ private String contentNodetype;
+
+ private IOManager ioManager;
+
+ /**
+ * Creates a new DefaultHandler with default nodetype definitions:
+ *
+ *
Nodetype for Collection: {@link JcrConstants#NT_FOLDER nt:folder}
+ *
Nodetype for Non-Collection: {@link JcrConstants#NT_FILE nt:file}
+ *
Nodetype for Non-Collection content: {@link JcrConstants#NT_UNSTRUCTURED nt:unstructured}
+ *
+ */
+ public DefaultHandler() {
+ this(null);
+ }
+
+ /**
+ * Creates a new DefaultHandler with default nodetype definitions:
+ *
+ *
Nodetype for Collection: {@link JcrConstants#NT_FOLDER nt:folder}
+ *
Nodetype for Non-Collection: {@link JcrConstants#NT_FILE nt:file}
+ *
Nodetype for Non-Collection content: {@link JcrConstants#NT_UNSTRUCTURED nt:unstructured}
+ *
+ *
+ * @param ioManager the I/O manager
+ */
+ public DefaultHandler(IOManager ioManager) {
+ this(ioManager,
+ JcrConstants.NT_FOLDER,
+ JcrConstants.NT_FILE,
+ // IMPORTANT NOTE: for webDAV compliance the default type
+ // of the content node has been changed from nt:resource to
+ // nt:unstructured
+ JcrConstants.NT_UNSTRUCTURED);
+ }
+
+ /**
+ * Creates a new DefaultHandler. Please note that the specified
+ * nodetypes must match the definitions of the defaults.
+ */
+ public DefaultHandler(IOManager ioManager, String collectionNodetype, String defaultNodetype, String contentNodetype) {
+ this.ioManager = ioManager;
+
+ this.collectionNodetype = collectionNodetype;
+ this.defaultNodetype = defaultNodetype;
+ this.contentNodetype = contentNodetype;
+ }
+
+ /**
+ * @see IOHandler#getIOManager()
+ */
+ public IOManager getIOManager() {
+ return ioManager;
+ }
+
+ /**
+ * @see IOHandler#setIOManager(IOManager)
+ */
+ public void setIOManager(IOManager ioManager) {
+ this.ioManager = ioManager;
+ }
+
+ /**
+ * @see IOHandler#getName()
+ */
+ public String getName() {
+ return getClass().getName();
+ }
+
+ /**
+ * @see IOHandler#canImport(ImportContext, boolean)
+ */
+ public boolean canImport(ImportContext context, boolean isCollection) {
+ if (context == null || context.isCompleted()) {
+ return false;
+ }
+ Item contextItem = context.getImportRoot();
+ return contextItem != null && contextItem.isNode() && context.getSystemId() != null;
+ }
+
+ /**
+ * @see IOHandler#canImport(ImportContext, DavResource)
+ */
+ public boolean canImport(ImportContext context, DavResource resource) {
+ if (resource == null) {
+ return false;
+ }
+ return canImport(context, resource.isCollection());
+ }
+
+ /**
+ * @see IOHandler#importContent(ImportContext, boolean)
+ */
+ public boolean importContent(ImportContext context, boolean isCollection) throws IOException {
+ if (!canImport(context, isCollection)) {
+ throw new IOException(getName() + ": Cannot import " + context.getSystemId());
+ }
+
+ boolean success = false;
+ try {
+ Node contentNode = getContentNode(context, isCollection);
+ success = importData(context, isCollection, contentNode);
+ if (success) {
+ success = importProperties(context, isCollection, contentNode);
+ }
+ } catch (RepositoryException e) {
+ success = false;
+ throw new IOException(e.getMessage());
+ } finally {
+ // revert any changes made in case the import failed.
+ if (!success) {
+ try {
+ context.getImportRoot().refresh(false);
+ } catch (RepositoryException e) {
+ throw new IOException(e.getMessage());
+ }
+ }
+ }
+ return success;
+ }
+
+ /**
+ * @see IOHandler#importContent(ImportContext, DavResource)
+ */
+ public boolean importContent(ImportContext context, DavResource resource) throws IOException {
+ if (!canImport(context, resource)) {
+ throw new IOException(getName() + ": Cannot import " + context.getSystemId());
+ }
+ return importContent(context, resource.isCollection());
+ }
+
+ /**
+ * Imports the data present on the import context to the specified content
+ * node.
+ */
+ protected boolean importData(ImportContext context, boolean isCollection, Node contentNode) throws IOException, RepositoryException {
+ InputStream in = context.getInputStream();
+ if (in != null) {
+ // NOTE: with the default folder-nodetype (nt:folder) no inputstream
+ // is allowed. setting the property would therefore fail.
+ if (isCollection) {
+ return false;
+ }
+ try {
+ contentNode.setProperty(JcrConstants.JCR_DATA, in);
+ } finally {
+ in.close();
+ }
+ }
+ // success if no data to import.
+ return true;
+ }
+
+ /**
+ * Imports the properties present on the specified context to the content
+ * node.
+ */
+ protected boolean importProperties(ImportContext context, boolean isCollection, Node contentNode) {
+ try {
+ // set mimeType property upon resource creation but don't modify
+ // it on a subsequent PUT. In contrast to a PROPPATCH request, which
+ // is handled by #importProperties(PropertyContext, boolean)}
+ if (!contentNode.hasProperty(JcrConstants.JCR_MIMETYPE)) {
+ contentNode.setProperty(JcrConstants.JCR_MIMETYPE, context.getMimeType());
+ }
+ } catch (RepositoryException e) {
+ // ignore: property may not be present on the node
+ }
+ try {
+ // set encoding property upon resource creation but don't modify
+ // it on a subsequent PUT. In contrast to a PROPPATCH request, which
+ // is handled by #importProperties(PropertyContext, boolean)}
+ if (!contentNode.hasProperty(JcrConstants.JCR_ENCODING)) {
+ contentNode.setProperty(JcrConstants.JCR_ENCODING, context.getEncoding());
+ }
+ } catch (RepositoryException e) {
+ // ignore: property may not be present on the node
+ }
+ setLastModified(contentNode, context.getModificationTime());
+ return true;
+ }
+
+ /**
+ * Retrieves/creates the node that will be used to import properties and
+ * data. In case of a non-collection this includes and additional content node
+ * to be created beside the 'file' node.
+ *
+ * Please note: If the jcr:content node already exists and contains child
+ * nodes, those will be removed in order to make sure, that the import
+ * really replaces the existing content of the file-node.
+ */
+ protected Node getContentNode(ImportContext context, boolean isCollection) throws RepositoryException {
+ Node parentNode = (Node)context.getImportRoot();
+ String name = context.getSystemId();
+ if (parentNode.hasNode(name)) {
+ parentNode = parentNode.getNode(name);
+ } else {
+ String ntName = (isCollection) ? getCollectionNodeType() : getNodeType();
+ parentNode = parentNode.addNode(name, ntName);
+ }
+ Node contentNode = null;
+ if (isCollection) {
+ contentNode = parentNode;
+ } else {
+ if (parentNode.hasNode(JcrConstants.JCR_CONTENT)) {
+ contentNode = parentNode.getNode(JcrConstants.JCR_CONTENT);
+ // check if nodetype is compatible (might be update of an existing file)
+ if (contentNode.isNodeType(getContentNodeType()) ||
+ !forceCompatibleContentNodes()) {
+ // remove all entries in the jcr:content since replacing content
+ // includes properties (DefaultHandler) and nodes (e.g. ZipHandler)
+ if (contentNode.hasNodes()) {
+ NodeIterator it = contentNode.getNodes();
+ while (it.hasNext()) {
+ it.nextNode().remove();
+ }
+ }
+ } else {
+ contentNode.remove();
+ contentNode = null;
+ }
+ }
+ if (contentNode == null) {
+ // JCR-2070: Use the predefined content node type only
+ // when the underlying repository allows it to be used
+ if (parentNode.getPrimaryNodeType().canAddChildNode(
+ JcrConstants.JCR_CONTENT, getContentNodeType())) {
+ contentNode = parentNode.addNode(
+ JcrConstants.JCR_CONTENT, getContentNodeType());
+ } else {
+ contentNode = parentNode.addNode(JcrConstants.JCR_CONTENT);
+ }
+ }
+ }
+ return contentNode;
+ }
+
+ /**
+ * Defines if content nodes should be replace if they don't have the
+ * node type given by {@link #getCollectionNodeType()}.
+ *
+ * @return true if content nodes should be replaced.
+ */
+ protected boolean forceCompatibleContentNodes() {
+ return false;
+ }
+
+ /**
+ * Returns true if the export root is a node and if it contains a child node
+ * with name {@link JcrConstants#JCR_CONTENT jcr:content} in case this
+ * export is not intended for a collection.
+ *
+ * @return true if the export root is a node. If the specified boolean parameter
+ * is false (not a collection export) the given export root must contain a
+ * child node with name {@link JcrConstants#JCR_CONTENT jcr:content}.
+ *
+ * @see IOHandler#canExport(ExportContext, boolean)
+ */
+ public boolean canExport(ExportContext context, boolean isCollection) {
+ if (context == null || context.isCompleted()) {
+ return false;
+ }
+ Item exportRoot = context.getExportRoot();
+ boolean success = exportRoot != null && exportRoot.isNode();
+ if (success && !isCollection) {
+ try {
+ Node n = ((Node)exportRoot);
+ success = n.hasNode(JcrConstants.JCR_CONTENT);
+ } catch (RepositoryException e) {
+ // should never occur.
+ success = false;
+ }
+ }
+ return success;
+ }
+
+ /**
+ * @see IOHandler#canExport(ExportContext, DavResource)
+ */
+ public boolean canExport(ExportContext context, DavResource resource) {
+ if (resource == null) {
+ return false;
+ }
+ return canExport(context, resource.isCollection());
+ }
+
+ /**
+ * Retrieves the content node that will be used for exporting properties and
+ * data and calls the corresponding methods.
+ *
+ * @param context the export context
+ * @param isCollection true if collection
+ * @see #exportProperties(ExportContext, boolean, Node)
+ * @see #exportData(ExportContext, boolean, Node)
+ */
+ public boolean exportContent(ExportContext context, boolean isCollection) throws IOException {
+ if (!canExport(context, isCollection)) {
+ throw new IOException(getName() + ": Cannot export " + context.getExportRoot());
+ }
+ try {
+ Node contentNode = getContentNode(context, isCollection);
+ exportProperties(context, isCollection, contentNode);
+ if (context.hasStream()) {
+ exportData(context, isCollection, contentNode);
+ } // else: missing stream. ignore.
+ return true;
+ } catch (RepositoryException e) {
+ // should never occur, since the proper structure of the content
+ // node must be asserted in the 'canExport' call.
+ throw new IOException(e.getMessage());
+ }
+ }
+
+ /**
+ * Same as (@link IOHandler#exportContent(ExportContext, boolean)} where
+ * the boolean values is defined by {@link DavResource#isCollection()}.
+ *
+ * @see IOHandler#exportContent(ExportContext, DavResource)
+ */
+ public boolean exportContent(ExportContext context, DavResource resource) throws IOException {
+ if (!canExport(context, resource)) {
+ throw new IOException(getName() + ": Cannot export " + context.getExportRoot());
+ }
+ return exportContent(context, resource.isCollection());
+ }
+
+ /**
+ * Checks if the given content node contains a jcr:data property
+ * and spools its value to the output stream of the export context.
+ * Please note, that subclasses that define a different structure of the
+ * content node should create their own
+ * {@link #exportData(ExportContext, boolean, Node) exportData} method.
+ *
+ * @param context export context
+ * @param isCollection true if collection
+ * @param contentNode the content node
+ * @throws IOException if an I/O error occurs
+ */
+ protected void exportData(ExportContext context, boolean isCollection, Node contentNode) throws IOException, RepositoryException {
+ if (contentNode.hasProperty(JcrConstants.JCR_DATA)) {
+ Property p = contentNode.getProperty(JcrConstants.JCR_DATA);
+ IOUtil.spool(p.getStream(), context.getOutputStream());
+ } // else: stream undefined -> content length was not set
+ }
+
+ /**
+ * Retrieves mimetype, encoding and modification time from the content node.
+ * The content length is determined by the length of the jcr:data property
+ * if it is present. The creation time however is retrieved from the parent
+ * node (in case of isCollection == false only).
+ *
+ * @param context the export context
+ * @param isCollection true if collection
+ * @param contentNode the content node
+ * @throws java.io.IOException If an error occurs.
+ */
+ protected void exportProperties(ExportContext context, boolean isCollection, Node contentNode) throws IOException {
+ try {
+ // only non-collections: 'jcr:created' is present on the parent 'fileNode' only
+ if (!isCollection && contentNode.getDepth() > 0 && contentNode.getParent().hasProperty(JcrConstants.JCR_CREATED)) {
+ long cTime = contentNode.getParent().getProperty(JcrConstants.JCR_CREATED).getValue().getLong();
+ context.setCreationTime(cTime);
+ }
+
+ long length = IOUtil.UNDEFINED_LENGTH;
+ if (contentNode.hasProperty(JcrConstants.JCR_DATA)) {
+ Property p = contentNode.getProperty(JcrConstants.JCR_DATA);
+ length = p.getLength();
+ context.setContentLength(length);
+ }
+
+ String mimeType = null;
+ String encoding = null;
+ if (contentNode.hasProperty(JcrConstants.JCR_MIMETYPE)) {
+ mimeType = contentNode.getProperty(JcrConstants.JCR_MIMETYPE).getString();
+ }
+ if (contentNode.hasProperty(JcrConstants.JCR_ENCODING)) {
+ encoding = contentNode.getProperty(JcrConstants.JCR_ENCODING).getString();
+ // ignore "" encoding (although this is avoided during import)
+ if ("".equals(encoding)) {
+ encoding = null;
+ }
+ }
+ context.setContentType(mimeType, encoding);
+
+ long modTime = IOUtil.UNDEFINED_TIME;
+ if (contentNode.hasProperty(JcrConstants.JCR_LASTMODIFIED)) {
+ modTime = contentNode.getProperty(JcrConstants.JCR_LASTMODIFIED).getLong();
+ context.setModificationTime(modTime);
+ } else {
+ context.setModificationTime(System.currentTimeMillis());
+ }
+
+ if (length > IOUtil.UNDEFINED_LENGTH && modTime > IOUtil.UNDEFINED_TIME) {
+ String etag = "\"" + length + "-" + modTime + "\"";
+ context.setETag(etag);
+ }
+ } catch (RepositoryException e) {
+ // should never occur
+ log.error("Unexpected error {} while exporting properties: {}", e.getClass().getName(), e.getMessage());
+ throw new IOException(e.getMessage());
+ }
+ }
+
+ /**
+ * Retrieves the content node that contains the data to be exported. In case
+ * isCollection is true, this corresponds to the export root. Otherwise there
+ * must be a child node with name {@link JcrConstants#JCR_CONTENT jcr:content}.
+ *
+ * @param context the export context
+ * @param isCollection true if collection
+ * @return content node used for the export
+ * @throws RepositoryException if an error during repository access occurs.
+ */
+ protected Node getContentNode(ExportContext context, boolean isCollection) throws RepositoryException {
+ Node contentNode = (Node)context.getExportRoot();
+ // 'file' nodes must have an jcr:content child node (see canExport)
+ if (!isCollection) {
+ contentNode = contentNode.getNode(JcrConstants.JCR_CONTENT);
+ }
+ return contentNode;
+ }
+
+ /**
+ * Name of the nodetype to be used to create a new collection node (folder)
+ *
+ * @return nodetype name
+ */
+ public String getCollectionNodeType() {
+ return collectionNodetype;
+ }
+
+ /**
+ * Name of the nodetype to be used to create a new non-collection node (file)
+ *
+ * @return nodetype name
+ */
+ public String getNodeType() {
+ return defaultNodetype;
+ }
+
+ /**
+ * Name of the nodetype to be used to create the content node below
+ * a new non-collection node, whose name is always {@link JcrConstants#JCR_CONTENT
+ * jcr:content}.
+ *
+ * @return nodetype name
+ */
+ public 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 I/O 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() || isDefinedByFilteredNodeType(def)) {
+ log.debug("Skip 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 extends PropEntry, ?> 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 extends PropEntry> 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) {
+ for (PropEntry propEntry : changeList) {
+ 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);
+ }
+ }
+ }
+ if (failures.isEmpty()) {
+ setLastModified(cn, IOUtil.UNDEFINED_LENGTH);
+ }
+ return failures;
+ }
+
+ /**
+ * Detects the media type of a document based on the given name.
+ *
+ * @param name document name
+ * @return detected content type (or application/octet-stream)
+ */
+ protected String detect(String name) {
+ try {
+ Metadata metadata = new Metadata();
+ metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, name);
+ if (ioManager != null && ioManager.getDetector() != null) {
+ return ioManager.getDetector().detect(null, metadata).toString();
+ } else {
+ return "application/octet-stream";
+ }
+ } catch (IOException e) {
+ // Can not happen since the InputStream above is null
+ throw new IllegalStateException(
+ "Unexpected IOException", e);
+ }
+ }
+
+ //----------------------------------------------------< CopyMoveHandler >---
+ /**
+ * @see CopyMoveHandler#canCopy(CopyMoveContext, org.apache.jackrabbit.webdav.DavResource, org.apache.jackrabbit.webdav.DavResource)
+ */
+ public boolean canCopy(CopyMoveContext context, DavResource source, DavResource destination) {
+ return true;
+ }
+
+ /**
+ * @see CopyMoveHandler#copy(CopyMoveContext, org.apache.jackrabbit.webdav.DavResource, org.apache.jackrabbit.webdav.DavResource)
+ */
+ public boolean copy(CopyMoveContext context, DavResource source, DavResource destination) throws DavException {
+ if (context.isShallowCopy() && source.isCollection()) {
+ // TODO: currently no support for shallow copy; however this is
+ // only relevant if the source resource is a collection, because
+ // otherwise it doesn't make a difference
+ throw new DavException(DavServletResponse.SC_FORBIDDEN, "Unable to perform shallow copy.");
+ }
+ try {
+ context.getSession().getWorkspace().copy(source.getLocator().getRepositoryPath(), destination.getLocator().getRepositoryPath());
+ return true;
+ } catch (PathNotFoundException e) {
+ // according to rfc 2518: missing parent
+ throw new DavException(DavServletResponse.SC_CONFLICT, e.getMessage());
+ } catch (RepositoryException e) {
+ throw new JcrDavException(e);
+ }
+ }
+
+ /**
+ * @see CopyMoveHandler#canMove(CopyMoveContext, org.apache.jackrabbit.webdav.DavResource, org.apache.jackrabbit.webdav.DavResource)
+ */
+ public boolean canMove(CopyMoveContext context, DavResource source, DavResource destination) {
+ return true;
+ }
+
+ /**
+ * @see CopyMoveHandler#move(CopyMoveContext, org.apache.jackrabbit.webdav.DavResource, org.apache.jackrabbit.webdav.DavResource)
+ */
+ public boolean move(CopyMoveContext context, DavResource source, DavResource destination) throws DavException {
+ try {
+ context.getWorkspace().move(source.getLocator().getRepositoryPath(), destination.getLocator().getRepositoryPath());
+ return true;
+ } catch (RepositoryException e) {
+ throw new JcrDavException(e);
+ }
+ }
+
+ //----------------------------------------------------< DeleteHandler >---
+
+ /**
+ * @see DeleteHandler#canDelete(DeleteContext, DavResource)
+ */
+ public boolean canDelete(DeleteContext deleteContext, DavResource member) {
+ return true;
+ }
+
+ /**
+ * @see DeleteHandler#delete(DeleteContext, DavResource)
+ */
+ public boolean delete(DeleteContext deleteContext, DavResource member) throws DavException {
+ try {
+ String itemPath = member.getLocator().getRepositoryPath();
+ Item item = deleteContext.getSession().getItem(itemPath);
+ if (item instanceof Node) {
+ ((Node) item).removeShare();
+ } else {
+ item.remove();
+ }
+ deleteContext.getSession().save();
+ log.debug("default handler deleted {}", member.getResourcePath());
+ return true;
+ } catch (RepositoryException e) {
+ throw new JcrDavException(e);
+ }
+ }
+
+ //------------------------------------------------------------< 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.
+ * Please note, that the local part of the jcrName is checked for XML
+ * compatibility by calling {@link ISO9075#encode(String)}
+ *
+ * @param jcrName name of the jcr property
+ * @param session session
+ * @return a DavPropertyName for the given jcr name.
+ * @throws RepositoryException if an error during repository access occurs.
+ */
+ 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.
+ *
+ * @param propName name of the dav property
+ * @param session repository session
+ * @return jcr name
+ * @throws RepositoryException if an error during repository access occurs.
+ */
+ 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)) {
+ NamespaceHelper helper = new NamespaceHelper(session);
+ String prefix = helper.registerNamespace(
+ propNamespace.getPrefix(), propNamespace.getURI());
+ pName = prefix + ":" + pName;
+ }
+ return pName;
+ }
+
+
+ /**
+ * @param property dav property
+ * @param contentNode the content node
+ * @throws RepositoryException if an error during repository access occurs.
+ */
+ 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();
+ }
+
+ DavPropertyName davName = property.getName();
+ if (DavPropertyName.GETCONTENTTYPE.equals(davName)) {
+ String mimeType = IOUtil.getMimeType(value);
+ String encoding = IOUtil.getEncoding(value);
+ contentNode.setProperty(JcrConstants.JCR_MIMETYPE, mimeType);
+ contentNode.setProperty(JcrConstants.JCR_ENCODING, encoding);
+ } else {
+ contentNode.setProperty(getJcrName(davName, contentNode.getSession()), value);
+ }
+ }
+
+ /**
+ * @param propertyName dav property name
+ * @param contentNode the content node
+ * @throws RepositoryException if an error during repository access occurs.
+ */
+ private void removeJcrProperty(DavPropertyName propertyName, Node contentNode)
+ throws RepositoryException {
+ if (DavPropertyName.GETCONTENTTYPE.equals(propertyName)) {
+ if (contentNode.hasProperty(JcrConstants.JCR_MIMETYPE)) {
+ contentNode.getProperty(JcrConstants.JCR_MIMETYPE).remove();
+ }
+ if (contentNode.hasProperty(JcrConstants.JCR_ENCODING)) {
+ contentNode.getProperty(JcrConstants.JCR_ENCODING).remove();
+ }
+ } else {
+ String jcrName = getJcrName(propertyName, contentNode.getSession());
+ if (contentNode.hasProperty(jcrName)) {
+ contentNode.getProperty(jcrName).remove();
+ }
+ // removal of non existing property succeeds
+ }
+ }
+
+ private void setLastModified(Node contentNode, long hint) {
+ try {
+ Calendar lastMod = Calendar.getInstance();
+ if (hint > IOUtil.UNDEFINED_TIME) {
+ lastMod.setTimeInMillis(hint);
+ } else {
+ lastMod.setTime(new Date());
+ }
+ contentNode.setProperty(JcrConstants.JCR_LASTMODIFIED, lastMod);
+ } catch (RepositoryException e) {
+ // ignore: property may not be available on the node.
+ // deliberately not re-throwing as IOException.
+ }
+ }
+
+ private static boolean isDefinedByFilteredNodeType(PropertyDefinition def) {
+ String ntName = def.getDeclaringNodeType().getName();
+ return ntName.equals(JcrConstants.NT_BASE)
+ || ntName.equals(JcrConstants.MIX_REFERENCEABLE)
+ || ntName.equals(JcrConstants.MIX_VERSIONABLE)
+ || ntName.equals(JcrConstants.MIX_LOCKABLE);
+ }
+
+ //-------------------------------------------< setter for configuration >---
+
+ public void setCollectionNodetype(String collectionNodetype) {
+ this.collectionNodetype = collectionNodetype;
+ }
+
+ public void setDefaultNodetype(String defaultNodetype) {
+ this.defaultNodetype = defaultNodetype;
+ }
+
+ public void setContentNodetype(String contentNodetype) {
+ this.contentNodetype = contentNodetype;
+ }
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DefaultHandler.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+author date id revision url
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DefaultIOListener.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DefaultIOListener.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DefaultIOListener.java (working copy)
@@ -0,0 +1,59 @@
+/*
+ * 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;
+
+/**
+ * DefaultIOListener implements an IOListener that
+ * writes debug/error output to the {@link Logger logger} specified in the constructor.
+ */
+public class DefaultIOListener implements IOListener {
+
+ private static Logger log = LoggerFactory.getLogger(DefaultIOListener.class);
+
+ private Logger ioLog;
+
+ /**
+ * Creates a new DefaultIOListener
+ */
+ public DefaultIOListener(Logger ioLog) {
+ this.ioLog = (ioLog != null) ? ioLog : log;
+ }
+
+ /**
+ * @see IOListener#onBegin(IOHandler, IOContext)
+ */
+ public void onBegin(IOHandler handler, IOContext ioContext) {
+ ioLog.debug("Starting IOHandler (" + handler.getName() + ")");
+ }
+
+ /**
+ * @see IOListener#onEnd(IOHandler, IOContext, boolean)
+ */
+ public void onEnd(IOHandler handler, IOContext ioContext, boolean success) {
+ ioLog.debug("Result for IOHandler (" + handler.getName() + "): " + (success ? "OK" : "Failed"));
+ }
+
+ /**
+ * @see IOListener#onError(IOHandler, IOContext, Exception)
+ */
+ public void onError(IOHandler ioHandler, IOContext ioContext, Exception e) {
+ ioLog.debug("Error: " + e.getMessage());
+ }
+}
\ No newline at end of file
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DefaultIOListener.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+author date id revision url
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DefaultIOManager.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DefaultIOManager.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DefaultIOManager.java (working copy)
@@ -0,0 +1,53 @@
+/*
+ * 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;
+
+/**
+ * DefaultIOManager...
+ */
+public class DefaultIOManager extends IOManagerImpl {
+
+ /**
+ * Creates a new DefaultIOManager and populates the internal
+ * list of IOHandlers by the defaults.
+ *
+ * @see #init()
+ */
+ public DefaultIOManager() {
+ init();
+ }
+
+ /**
+ * Add the predefined IOHandlers to this manager. This includes
+ *
+ *
{@link VersionHistoryHandler}
+ *
{@link VersionHandler}
+ *
{@link ZipHandler}
+ *
{@link XmlHandler}
+ *
{@link DirListingExportHandler}
+ *
{@link DefaultHandler}.
+ *
+ */
+ protected void init() {
+ addIOHandler(new VersionHistoryHandler(this));
+ addIOHandler(new VersionHandler(this));
+ addIOHandler(new ZipHandler(this));
+ addIOHandler(new XmlHandler(this));
+ addIOHandler(new DirListingExportHandler(this));
+ addIOHandler(new DefaultHandler(this));
+ }
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DefaultIOManager.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+author date id revision url
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteContext.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteContext.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteContext.java (working copy)
@@ -0,0 +1,32 @@
+/*
+ * 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.Session;
+
+/**
+ * The context associated with a DELETE operation
+ */
+public interface DeleteContext {
+
+ /**
+ * @return the jcr session associated with this context.
+ */
+ public Session getSession();
+
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteContext.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteContextImpl.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteContextImpl.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteContextImpl.java (working copy)
@@ -0,0 +1,39 @@
+/*
+ * 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.Session;
+
+/**
+ * Implements a simple delete context
+ */
+public class DeleteContextImpl implements DeleteContext {
+
+ private final Session session;
+
+ public DeleteContextImpl(Session session) {
+ this.session = session;
+ }
+
+ /**
+ * @see DeleteContext#getSession()
+ */
+ public Session getSession() {
+ return this.session;
+ }
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteContextImpl.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteHandler.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteHandler.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteHandler.java (working copy)
@@ -0,0 +1,51 @@
+/*
+ * 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.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavResource;
+
+/**
+ * The DeleteHandler is invoked when a webdav DELETE request is received. Implementers of this interface should plugin
+ * their handling of DELETE request here
+ */
+public interface DeleteHandler {
+
+ /**
+ * Executes the delete operation with the given parameters.
+ *
+ * @param deleteContext The context of the delete.
+ * @param resource The resource to be deleted
+ * @return {@code true} if this instance successfully executed the delete operation with the given parameters;
+ * {@code false} otherwise.
+ * @throws DavException If an error occurs.
+ */
+ public boolean delete(DeleteContext deleteContext, DavResource resource) throws DavException;
+
+
+ /**
+ * Validates if this handler is able to execute a delete operation with the given
+ * parameters.
+ *
+ * @param deleteContext The context of the delete
+ * @param resource The resource to be deleted
+ * @return {@code true} if this instance can successfully execute the delete operation with the given parameters;
+ * {@code false} otherwise.
+ */
+ public boolean canDelete(DeleteContext deleteContext, DavResource resource);
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteHandler.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteManager.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteManager.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteManager.java (working copy)
@@ -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.jackrabbit.server.io;
+
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavResource;
+
+/**
+ * The DeleteManager handles DELETE operation by delegating it to its handlers. It also provides a way
+ * to register {@link org.apache.jackrabbit.server.io.DeleteHandler} within it. Implementers of this interface
+ * must invoke the registered delete handlers appropriately when a DELETE operation is to be performed
+ */
+public interface DeleteManager {
+
+ /**
+ * Delegates the delete operation to the fist handler that accepts it.
+ *
+ * @param deleteContext The context associated with the DELETE operation
+ * @param resource The resource to be deleted
+ * @return {@code true} if this instance successfully executed the delete operation with the given parameters;
+ * {@code false} otherwise.
+ * @throws DavException If an error occurs.
+ */
+ public boolean delete(DeleteContext deleteContext, DavResource resource) throws DavException;
+
+ /**
+ * Registers a delete handler
+ *
+ * @param deleteHandler Registers a delete handler with this delete manager
+ */
+ public void addDeleteHandler(DeleteHandler deleteHandler);
+
+ /**
+ * Returns the registered delete handlers
+ *
+ * @return An array of all the registered delete handlers.
+ */
+ public DeleteHandler[] getDeleteHandlers();
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteManager.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteManagerImpl.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteManagerImpl.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteManagerImpl.java (working copy)
@@ -0,0 +1,77 @@
+/*
+ * 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.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavResource;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DeleteManagerImpl implements DeleteManager {
+
+ private static DeleteManager DEFAULT_MANAGER;
+
+ private final List deleteHandlers = new ArrayList();
+
+ /**
+ * @see DeleteManager#delete(DeleteContext, DavResource)
+ */
+ public boolean delete(DeleteContext deleteContext, DavResource member) throws DavException {
+ boolean success = false;
+ DeleteHandler[] deleteHandlers = getDeleteHandlers();
+ for (int i = 0; i < deleteHandlers.length && !success; i++) {
+ DeleteHandler dh = deleteHandlers[i];
+ if (dh.canDelete(deleteContext, member)) {
+ success = dh.delete(deleteContext, member);
+ }
+ }
+ return success;
+ }
+
+ /**
+ * @see DeleteManager#addDeleteHandler(DeleteHandler)
+ */
+ public void addDeleteHandler(DeleteHandler deleteHandler) {
+ if (deleteHandler == null) {
+ throw new IllegalArgumentException("'null' is not a valid DeleteHandler.");
+ }
+ deleteHandlers.add(deleteHandler);
+
+ }
+
+ /**
+ * @see DeleteManager#getDeleteHandlers()
+ */
+ public DeleteHandler[] getDeleteHandlers() {
+ return deleteHandlers.toArray(new DeleteHandler[deleteHandlers.size()]);
+ }
+
+ /**
+ * Returns this delete manager singleton
+ */
+ public static DeleteManager getDefaultManager() {
+ if (DEFAULT_MANAGER == null) {
+ DeleteManager manager = new DeleteManagerImpl();
+ manager.addDeleteHandler(new DefaultHandler());
+ DEFAULT_MANAGER = manager;
+ }
+ return DEFAULT_MANAGER;
+ }
+
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteManagerImpl.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DirListingExportHandler.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DirListingExportHandler.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DirListingExportHandler.java (working copy)
@@ -0,0 +1,299 @@
+/*
+ * 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.apache.jackrabbit.util.Text;
+import org.apache.jackrabbit.webdav.DavResource;
+import org.apache.jackrabbit.webdav.DavResourceIterator;
+import org.apache.jackrabbit.webdav.property.PropEntry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Item;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * DirListingExportHandler represents a simple export for collections:
+ * a human-readable view listing the members.
+ *
+ * Note: If {@link #exportContent(ExportContext, boolean)} is called the view list
+ * child nodes only, without respecting their representation as DavResources.
+ */
+public class DirListingExportHandler implements IOHandler, PropertyHandler {
+
+ private static Logger log = LoggerFactory.getLogger(DirListingExportHandler.class);
+
+ private IOManager ioManager;
+
+ /**
+ * Creates a new DirListingExportHandler
+ */
+ public DirListingExportHandler() {
+ }
+
+ /**
+ * Creates a new DirListingExportHandler
+ *
+ * @param ioManager
+ */
+ public DirListingExportHandler(IOManager ioManager) {
+ this.ioManager = ioManager;
+ }
+
+ /**
+ * Always returns false
+ *
+ * @see IOHandler#canImport(ImportContext, boolean)
+ */
+ public boolean canImport(ImportContext context, boolean isFolder) {
+ return false;
+ }
+
+ /**
+ * Always returns false
+ *
+ * @see IOHandler#canImport(ImportContext, DavResource)
+ */
+ public boolean canImport(ImportContext context, DavResource resource) {
+ return false;
+ }
+
+ /**
+ * Does nothing and returns false
+ *
+ * @see IOHandler#importContent(ImportContext, boolean)
+ */
+ public boolean importContent(ImportContext context, boolean isCollection) throws IOException {
+ // can only handle export
+ return false;
+ }
+
+ /**
+ * Does nothing and returns false
+ *
+ * @see IOHandler#importContent(ImportContext, DavResource)
+ */
+ public boolean importContent(ImportContext context, DavResource resource) throws IOException {
+ return false;
+ }
+
+ /**
+ * @return true if the specified context is still valid and provides a
+ * export root and if 'isCollection' is true. False otherwise
+ * @see IOHandler#canExport(ExportContext, boolean)
+ */
+ public boolean canExport(ExportContext context, boolean isCollection) {
+ if (context == null || context.isCompleted()) {
+ return false;
+ }
+ return isCollection && context.getExportRoot() != null;
+ }
+
+ /**
+ * @return true if the specified context is still valid and provides a
+ * export root and if the specified resource is a collection. False otherwise.
+ * @see IOHandler#canExport(ExportContext, DavResource)
+ * @see DavResource#isCollection()
+ */
+ public boolean canExport(ExportContext context, DavResource resource) {
+ if (resource == null) {
+ return false;
+ }
+ return canExport(context, resource.isCollection());
+ }
+
+ /**
+ * @see IOHandler#exportContent(ExportContext, boolean)
+ */
+ public boolean exportContent(ExportContext context, boolean isCollection) throws IOException {
+ if (!canExport(context, isCollection)) {
+ throw new IOException(getName() + ": Cannot export " + context.getExportRoot());
+ }
+
+ // properties (content length undefined)
+ context.setModificationTime(new Date().getTime());
+ context.setContentType("text/html", "UTF-8");
+
+ // data
+ if (context.hasStream()) {
+ PrintWriter writer = new PrintWriter(new OutputStreamWriter(context.getOutputStream(), "utf8"));
+ try {
+ Item item = context.getExportRoot();
+ Repository rep = item.getSession().getRepository();
+ String repName = rep.getDescriptor(Repository.REP_NAME_DESC);
+ String repURL = rep.getDescriptor(Repository.REP_VENDOR_URL_DESC);
+ String repVersion = rep.getDescriptor(Repository.REP_VERSION_DESC);
+ writer.print("
Powered by ");
+ writer.print(Text.encodeIllegalHTMLCharacters(repName));
+ writer.print(" version ");
+ writer.print(Text.encodeIllegalHTMLCharacters(repVersion));
+ writer.print("");
+ } catch (RepositoryException e) {
+ // should not occur
+ log.debug(e.getMessage());
+ }
+ writer.close();
+ }
+ return true;
+ }
+
+ /**
+ * @see IOHandler#getIOManager()
+ */
+ public IOManager getIOManager() {
+ return ioManager;
+ }
+
+ /**
+ * @see IOHandler#setIOManager(IOManager)
+ */
+ public void setIOManager(IOManager ioManager) {
+ this.ioManager = ioManager;
+ }
+
+ /**
+ * @see IOHandler#getName()
+ */
+ public String getName() {
+ return "DirListing Export";
+ }
+
+ //----------------------------------------------------< PropertyHandler >---
+ /**
+ * Always returns false.
+ * @param context
+ * @param isCollection
+ * @return always returns false.
+ */
+ public boolean canExport(PropertyExportContext context, boolean isCollection) {
+ return false;
+ }
+
+ /**
+ * @see PropertyHandler#exportProperties(PropertyExportContext, boolean)
+ */
+ public boolean exportProperties(PropertyExportContext exportContext, boolean isCollection) throws RepositoryException {
+ // export-content facility only... no responsible for PROPFIND.
+ throw new RepositoryException(getName() + ": Cannot export properties for context " + exportContext);
+ }
+
+ public boolean canImport(PropertyImportContext context, boolean isCollection) {
+ return false;
+ }
+
+ /**
+ * @see PropertyHandler#importProperties(PropertyImportContext, boolean)
+ */
+ public Map extends PropEntry, ?> importProperties(PropertyImportContext importContext, boolean isCollection) throws RepositoryException {
+ // export facilities only -> throw
+ throw new RepositoryException(getName() + ": Cannot import properties.");
+ }
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DirListingExportHandler.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+author date id revision url
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ExportContext.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ExportContext.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ExportContext.java (working copy)
@@ -0,0 +1,84 @@
+/*
+ * 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.io.OutputStream;
+
+/**
+ * ExportContext...
+ */
+public interface ExportContext extends IOContext {
+
+ /**
+ * Returns the item to be exported
+ */
+ public Item getExportRoot();
+
+ /**
+ * Return the output stream to be used for the export or null
+ *
+ * @return output stream or null
+ */
+ public OutputStream getOutputStream();
+
+ /**
+ * Set the content type for the resource content
+ */
+ public void setContentType(String mimeType, String encoding);
+
+ /**
+ * Sets the content language.
+ */
+ public void setContentLanguage(String contentLanguage);
+
+ /**
+ * Sets the length of the data.
+ *
+ * @param contentLength the content length
+ */
+ public void setContentLength(long contentLength);
+
+ /**
+ * Sets the creation time of the resource. A successful properties export may
+ * set this member.
+ *
+ * @param creationTime the creation time
+ */
+ public void setCreationTime(long creationTime);
+
+ /**
+ * Sets the modification time of the resource
+ *
+ * @param modificationTime the modification time
+ */
+ public void setModificationTime(long modificationTime);
+
+ /**
+ * Sets the ETag of the resource. A successful export command
+ * may set this member.
+ *
+ * @param etag the ETag
+ */
+ public void setETag(String etag);
+
+ /**
+ * Sets an arbitrary property to this export context.
+ */
+ public void setProperty(Object propertyName, Object propertyValue);
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ExportContext.java
___________________________________________________________________
Added: svn
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ExportContextImpl.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ExportContextImpl.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ExportContextImpl.java (working copy)
@@ -0,0 +1,200 @@
+/*
+ * 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.apache.jackrabbit.webdav.DavConstants;
+import org.apache.jackrabbit.webdav.DavResource;
+import org.apache.jackrabbit.webdav.io.OutputContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Item;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * ExportContextImpl implements an ExportContext that
+ * wraps around the specified OutputContext as it was passed to
+ * {@link DavResource#spool(OutputContext)}. If a stream is provided a temporary
+ * file is created, which is deleted as soon as {@link #informCompleted(boolean)}
+ * is called on this context. Note however, that the properties and the stream
+ * are written to the OutputContext but upon successful completion.
+ *
+ * @see #informCompleted(boolean)
+ */
+public class ExportContextImpl extends AbstractExportContext {
+
+ private static Logger log = LoggerFactory.getLogger(ExportContextImpl.class);
+
+ private final Map properties = new HashMap();
+ private final OutputContext outputCtx;
+
+ private File outFile;
+ private OutputStream outStream;
+
+ public ExportContextImpl(Item exportRoot, OutputContext outputCtx)
+ throws IOException {
+ super(exportRoot, outputCtx != null && outputCtx.hasStream(), null);
+ this.outputCtx = outputCtx;
+ if (hasStream()) {
+ // we need a tmp file, since the export could fail
+ outFile = File.createTempFile("__exportcontext", "tmp");
+ }
+ }
+
+ /**
+ * Returns a new OutputStream to the temporary file or
+ * null if this context provides no stream.
+ *
+ * @see ExportContext#getOutputStream()
+ * @see #informCompleted(boolean)
+ */
+ public OutputStream getOutputStream() {
+ checkCompleted();
+ if (hasStream()) {
+ try {
+ // clean up the stream retrieved by the preceding handler, that
+ // did not behave properly and failed to export although initially
+ // willing to handle the export.
+ if (outStream != null) {
+ outStream.close();
+ }
+ outStream = new FileOutputStream(outFile);
+ return outStream;
+ } catch (IOException e) {
+ // unexpected error... ignore and return null
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @see ExportContext#setContentLanguage(String)
+ */
+ public void setContentLanguage(String contentLanguage) {
+ properties.put(DavConstants.HEADER_CONTENT_LANGUAGE, contentLanguage);
+ }
+
+ /**
+ * @see ExportContext#setContentLength(long)
+ */
+ public void setContentLength(long contentLength) {
+ properties.put(DavConstants.HEADER_CONTENT_LENGTH, contentLength + "");
+ }
+
+ /**
+ * @see ExportContext#setContentType(String,String)
+ */
+ public void setContentType(String mimeType, String encoding) {
+ properties.put(DavConstants.HEADER_CONTENT_TYPE, IOUtil.buildContentType(mimeType, encoding));
+ }
+
+ /**
+ * Does nothing since the wrapped output context does not understand
+ * creation time
+ *
+ * @see ExportContext#setCreationTime(long)
+ */
+ public void setCreationTime(long creationTime) {
+ // ignore since output-ctx does not understand creation time
+ }
+
+ /**
+ * @see ExportContext#setModificationTime(long)
+ */
+ public void setModificationTime(long modificationTime) {
+ if (modificationTime <= IOUtil.UNDEFINED_TIME) {
+ modificationTime = new Date().getTime();
+ }
+ String lastMod = IOUtil.getLastModified(modificationTime);
+ properties.put(DavConstants.HEADER_LAST_MODIFIED, lastMod);
+ }
+
+ /**
+ * @see ExportContext#setETag(String)
+ */
+ public void setETag(String etag) {
+ properties.put(DavConstants.HEADER_ETAG, etag);
+ }
+
+ /**
+ * @see ExportContext#setProperty(Object, Object)
+ */
+ public void setProperty(Object propertyName, Object propertyValue) {
+ if (propertyName != null && propertyValue != null) {
+ properties.put(propertyName.toString(), propertyValue.toString());
+ }
+ }
+
+ /**
+ * If success is true, the properties set before an the output stream are
+ * written to the wrapped OutputContext.
+ *
+ * @see ExportContext#informCompleted(boolean)
+ */
+ @Override
+ public void informCompleted(boolean success) {
+ checkCompleted();
+ completed = true;
+ // make sure the outputStream gets closed (and don't assume the handlers
+ // took care of this.
+ if (outStream != null) {
+ try {
+ outStream.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ if (success) {
+ // write properties and data to the output-context
+ if (outputCtx != null) {
+ boolean seenContentLength = false;
+ for (Map.Entry entry : properties.entrySet()) {
+ String name = entry.getKey();
+ String value = entry.getValue();
+ if (name != null && value != null) {
+ outputCtx.setProperty(name, value);
+ seenContentLength |= DavConstants.HEADER_CONTENT_LENGTH.equals(name);
+ }
+ }
+
+ if (outputCtx.hasStream() && outFile != null) {
+ OutputStream out = outputCtx.getOutputStream();
+ try {
+ // make sure the content-length is set
+ if (!seenContentLength) {
+ outputCtx.setContentLength(outFile.length());
+ }
+ FileInputStream in = new FileInputStream(outFile);
+ IOUtil.spool(in, out);
+ } catch (IOException e) {
+ log.error(e.toString());
+ }
+ }
+ }
+ }
+ if (outFile != null) {
+ outFile.delete();
+ }
+ }
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ExportContextImpl.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+author date id revision url
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOContext.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOContext.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOContext.java (working copy)
@@ -0,0 +1,47 @@
+/*
+ * 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;
+
+/**
+ * IOContext defines the common methods for {@link ImportContext}
+ * and {@link ExportContext}
+ */
+public interface IOContext {
+
+ /**
+ * Returns the IOListener.
+ */
+ public IOListener getIOListener();
+
+ /**
+ * Return true if the given export context can provide an output stream
+ */
+ public boolean hasStream();
+
+ /**
+ * Informs this context that it will not be used for further exports any
+ * more. A boolean flag indicates about the success of the export.
+ */
+ public void informCompleted(boolean success);
+
+ /**
+ * Returns true if this context already has been completed.
+ *
+ * @return true if this context already has been completed.
+ */
+ public boolean isCompleted();
+}
\ No newline at end of file
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOContext.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+author date id revision url
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOHandler.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOHandler.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOHandler.java (working copy)
@@ -0,0 +1,162 @@
+/*
+ * 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.apache.jackrabbit.webdav.DavResource;
+
+import java.io.IOException;
+
+/**
+ * IOHandler interface defines methods for importing and
+ * exporting resource content as well as some fundamental resource properties
+ * which use to be set/retrieved together with content import and export (e.g.
+ * content length, modification date etc.).
+ */
+public interface IOHandler {
+
+ /**
+ * Returns the IOManager that called this handler or null.
+ */
+ public IOManager getIOManager();
+
+ /**
+ * Sets the IOManager that called this handler.
+ */
+ public void setIOManager(IOManager ioManager);
+
+ /**
+ * Returns a human readable name for this IOHandler.
+ */
+ public String getName();
+
+ /**
+ * Returns true, if this handler can run a successful import based on the
+ * specified context.
+ */
+ public boolean canImport(ImportContext context, boolean isCollection);
+
+ /**
+ * Returns true, if this handler can run a successful import based on
+ * the specified context and resource. A simple implementation may choose
+ * to return the same as {@link IOHandler#canImport(ImportContext, boolean)}
+ * where the isCollection flag is determined by
+ * {@link DavResource#isCollection()}.
+ */
+ public boolean canImport(ImportContext context, DavResource resource);
+
+ /**
+ * Runs the import for the given context and indicates by a boolean return
+ * value, if the import could be completed successfully. If the specified
+ * ImportContext does not provide a {@link ImportContext#hasStream() stream}
+ * the implementation is free, to only import properties of to refuse the
+ * import.
+ *
+ * Please note, that it is the responsibility of the specified
+ * ImportContext to assert, that its stream is not consumed
+ * multiple times when being passed to a chain of IOHandlers.
+ *
+ * @param context
+ * @param isCollection
+ * @return true if the import was successful.
+ * @throws IOException if an unexpected error occurs or if this method has
+ * been called although {@link IOHandler#canImport(ImportContext, boolean)}
+ * returns false.
+ */
+ public boolean importContent(ImportContext context, boolean isCollection) throws IOException;
+
+ /**
+ * Runs the import for the given context and resource. It indicates by a boolean return
+ * value, if the import could be completed successfully. If the specified
+ * ImportContext does not provide a {@link ImportContext#hasStream() stream}
+ * the implementation is free, to only import properties of to refuse the
+ * import. A simple implementation may return the same as
+ * {@link IOHandler#importContent(ImportContext, boolean)} where the
+ * isCollection flag is determined by {@link DavResource#isCollection()}
+ *
+ * Please note, that it is the responsibility of the specified
+ * ImportContext to assert, that its stream is not consumed
+ * multiple times when being passed to a chain of IOHandlers.
+ *
+ * @param context
+ * @param resource
+ * @return
+ * @throws IOException if an unexpected error occurs or if this method has
+ * been called although {@link IOHandler#canImport(ImportContext, DavResource)}
+ * returns false.
+ * @see IOHandler#importContent(ImportContext, boolean)
+ */
+ public boolean importContent(ImportContext context, DavResource resource) throws IOException;
+
+ /**
+ * Returns true, if this handler can run a successful export based on the
+ * specified context.
+ */
+ public boolean canExport(ExportContext context, boolean isCollection);
+
+ /**
+ * Returns true, if this handler can run a successful export based on
+ * the specified context and resource. A simple implementation may choose
+ * to return the same as {@link IOHandler#canExport(ExportContext, boolean)}
+ * where the isCollection flag is determined by
+ * {@link DavResource#isCollection()}.
+ */
+ public boolean canExport(ExportContext context, DavResource resource);
+
+ /**
+ * Runs the export for the given context. It indicates by a boolean return
+ * value, if the export could be completed successfully. If the specified
+ * ExportContext does not provide a {@link ExportContext#hasStream() stream}
+ * the implementation should set the properties only and ignore the content to
+ * be exported. A simple implementation may return the same as
+ * {@link IOHandler#exportContent(ExportContext, boolean)} where the
+ * isCollection flag is determined by {@link DavResource#isCollection()}
+ *
+ * Please note, that it is the responsibility of the specified
+ * ExportContext to assert, that its stream is not written
+ * multiple times when being passed to a chain of IOHandlers.
+ *
+ * @param context
+ * @param isCollection
+ * @return
+ * @throws IOException if an unexpected error occurs or if this method has
+ * been called although {@link IOHandler#canExport(ExportContext, boolean)}
+ * returns false.
+ */
+ public boolean exportContent(ExportContext context, boolean isCollection) throws IOException;
+
+ /**
+ * Runs the export for the given context and resource. It indicates by a boolean return
+ * value, if the export could be completed successfully. If the specified
+ * ExportContext does not provide a {@link ExportContext#hasStream() stream}
+ * the implementation should set the properties only and ignore the content to
+ * be exported. A simple implementation may return the same as
+ * {@link IOHandler#exportContent(ExportContext, boolean)} where the
+ * isCollection flag is determined by {@link DavResource#isCollection()}
+ *
+ * Please note, that it is the responsibility of the specified
+ * ExportContext to assert, that its stream is not written
+ * multiple times when being passed to a chain of IOHandlers.
+ *
+ * @param context
+ * @param resource
+ * @return
+ * @throws IOException if an unexpected error occurs or if this method has
+ * been called although {@link IOHandler#canExport(ExportContext, DavResource)}
+ * returns false.
+ */
+ public boolean exportContent(ExportContext context, DavResource resource) throws IOException;
+}
\ No newline at end of file
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOHandler.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+author date id revision url
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOListener.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOListener.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOListener.java (working copy)
@@ -0,0 +1,40 @@
+/*
+ * 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;
+
+/**
+ * IOListener defines an import/export listener.
+ */
+public interface IOListener {
+
+ /**
+ * The import/export context has been passed to the given IOHandler.
+ */
+ public void onBegin(IOHandler handler, IOContext context);
+
+ /**
+ * The specified IOHandler finished. A boolean flag indicates
+ * whether the handler was able to run the import/export.
+ */
+ public void onEnd(IOHandler handler, IOContext context, boolean success);
+
+ /**
+ * An exception occurred during import/export within the specified
+ * IOHandler.
+ */
+ public void onError(IOHandler ioHandler, IOContext context, Exception e);
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOListener.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+author date id revision url
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOManager.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOManager.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOManager.java (working copy)
@@ -0,0 +1,118 @@
+/*
+ * 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.apache.jackrabbit.webdav.DavResource;
+import org.apache.tika.detect.Detector;
+
+import java.io.IOException;
+
+/**
+ * IOManager interface provides the means to define a list of
+ * IOHandlers that should be asked to perform an import or export.
+ */
+public interface IOManager {
+
+ /**
+ * Adds the specified handler to the list of handlers.
+ *
+ * @param ioHandler to be added
+ */
+ public void addIOHandler(IOHandler ioHandler);
+
+ /**
+ * Returns all handlers that have been added to this manager.
+ *
+ * @return Array of all handlers
+ */
+ public IOHandler[] getIOHandlers();
+
+ /**
+ * Return the configured type detector.
+ *
+ * @return content type detector
+ */
+ Detector getDetector();
+
+ /**
+ * Sets the configured type detector.
+ *
+ * @param detector content type detector.
+ */
+ void setDetector(Detector detector);
+
+ /**
+ * Passes the specified context and boolean value to the IOHandlers present
+ * on this manager.
+ * As soon as the first handler indicates success the import should be
+ * considered completed. If none of the handlers can deal with the given
+ * information this method must return false.
+ *
+ * @param context
+ * @param isCollection
+ * @return true if any of the handlers import the given context.
+ * False otherwise.
+ * @throws IOException
+ * @see IOHandler#importContent(ImportContext, boolean)
+ */
+ public boolean importContent(ImportContext context, boolean isCollection) throws IOException;
+
+ /**
+ * Passes the specified information to the IOHandlers present on this manager.
+ * As soon as the first handler indicates success the import should be
+ * considered completed. If none of the handlers can deal with the given
+ * information this method must return false.
+ *
+ * @param context
+ * @param resource
+ * @return true if any of the handlers import the information present on the
+ * specified context.
+ * @throws IOException
+ * @see IOHandler#importContent(ImportContext, DavResource)
+ */
+ public boolean importContent(ImportContext context, DavResource resource) throws IOException;
+
+ /**
+ * Passes the specified information to the IOHandlers present on this manager.
+ * As soon as the first handler indicates success the export should be
+ * considered completed. If none of the handlers can deal with the given
+ * information this method must return false.
+ *
+ * @param context
+ * @param isCollection
+ * @return true if any of the handlers could run the export successfully,
+ * false otherwise.
+ * @throws IOException
+ * @see IOHandler#exportContent(ExportContext, boolean)
+ */
+ public boolean exportContent(ExportContext context, boolean isCollection) throws IOException;
+
+ /**
+ * Passes the specified information to the IOHandlers present on this manager.
+ * As soon as the first handler indicates success the export should be
+ * considered completed. If none of the handlers can deal with the given
+ * information this method must return false.
+ *
+ * @param context
+ * @param resource
+ * @return true if any of the handlers could run the export successfully,
+ * false otherwise.
+ * @throws IOException
+ * @see IOHandler#exportContent(ExportContext, DavResource)
+ */
+ public boolean exportContent(ExportContext context, DavResource resource) throws IOException;
+}
\ No newline at end of file
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOManager.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+author date id revision url
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOManagerImpl.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOManagerImpl.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOManagerImpl.java (working copy)
@@ -0,0 +1,185 @@
+/*
+ * 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 java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.jackrabbit.webdav.DavResource;
+import org.apache.tika.detect.Detector;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * IOManagerImpl represents the most simple IOManager
+ * implementation that provides a default constructor and does define any
+ * IOHandlers.
+ */
+public class IOManagerImpl implements IOManager {
+
+ private static Logger log = LoggerFactory.getLogger(IOManagerImpl.class);
+
+ /**
+ * Content type detector.
+ */
+ private Detector detector;
+
+ private final List ioHandlers = new ArrayList();
+
+ /**
+ * Create a new IOManager.
+ * Note, that this manager does not define any IOHandlers by
+ * default. Use {@link #addIOHandler(IOHandler)} in order to populate the
+ * internal list of handlers that are called for importContent and
+ * exportContent.
+ */
+ public IOManagerImpl() {
+ }
+
+ /**
+ * @see IOManager#addIOHandler(IOHandler)
+ */
+ public void addIOHandler(IOHandler ioHandler) {
+ if (ioHandler == null) {
+ throw new IllegalArgumentException("'null' is not a valid IOHandler.");
+ }
+ ioHandler.setIOManager(this);
+ ioHandlers.add(ioHandler);
+ }
+
+ /**
+ * @see IOManager#getIOHandlers()
+ */
+ public IOHandler[] getIOHandlers() {
+ return ioHandlers.toArray(new IOHandler[ioHandlers.size()]);
+ }
+
+ /**
+ * Return the configured type detector.
+ *
+ * @return content type detector
+ */
+ public Detector getDetector() {
+ return detector;
+ }
+
+ /**
+ * Sets the configured type detector.
+ *
+ * @param detector content type detector
+ */
+ public void setDetector(Detector detector) {
+ this.detector = detector;
+ }
+
+ /**
+ * @see IOManager#importContent(ImportContext, boolean)
+ */
+ public boolean importContent(ImportContext context, boolean isCollection) throws IOException {
+ boolean success = false;
+ if (context != null) {
+ IOListener ioListener = context.getIOListener();
+ if (ioListener == null) {
+ ioListener = new DefaultIOListener(log);
+ }
+ IOHandler[] ioHandlers = getIOHandlers();
+ for (int i = 0; i < ioHandlers.length && !success; i++) {
+ IOHandler ioh = ioHandlers[i];
+ if (ioh.canImport(context, isCollection)) {
+ ioListener.onBegin(ioh, context);
+ success = ioh.importContent(context, isCollection);
+ ioListener.onEnd(ioh, context, success);
+ }
+ }
+ context.informCompleted(success);
+ }
+ return success;
+ }
+
+ /**
+ * @see IOManager#importContent(ImportContext, DavResource)
+ */
+ public boolean importContent(ImportContext context, DavResource resource) throws IOException {
+ boolean success = false;
+ if (context != null && resource != null) {
+ IOListener ioListener = context.getIOListener();
+ if (ioListener == null) {
+ ioListener = new DefaultIOListener(log);
+ }
+ IOHandler[] ioHandlers = getIOHandlers();
+ for (int i = 0; i < ioHandlers.length && !success; i++) {
+ IOHandler ioh = ioHandlers[i];
+ if (ioh.canImport(context, resource)) {
+ ioListener.onBegin(ioh, context);
+ success = ioh.importContent(context, resource);
+ ioListener.onEnd(ioh, context, success);
+ }
+ }
+ context.informCompleted(success);
+ }
+ return success;
+ }
+
+ /**
+ * @see IOManager#exportContent(ExportContext, boolean)
+ */
+ public boolean exportContent(ExportContext context, boolean isCollection) throws IOException {
+ boolean success = false;
+ if (context != null) {
+ IOListener ioListener = context.getIOListener();
+ if (ioListener == null) {
+ ioListener = new DefaultIOListener(log);
+ }
+ IOHandler[] ioHandlers = getIOHandlers();
+ for (int i = 0; i < ioHandlers.length && !success; i++) {
+ IOHandler ioh = ioHandlers[i];
+ if (ioh.canExport(context, isCollection)) {
+ ioListener.onBegin(ioh, context);
+ success = ioh.exportContent(context, isCollection);
+ ioListener.onEnd(ioh, context, success);
+ }
+ }
+ context.informCompleted(success);
+ }
+ return success;
+ }
+
+ /**
+ * @see IOManager#exportContent(ExportContext, DavResource)
+ */
+ public boolean exportContent(ExportContext context, DavResource resource) throws IOException {
+ boolean success = false;
+ if (context != null && resource != null) {
+ IOListener ioListener = context.getIOListener();
+ if (ioListener == null) {
+ ioListener = new DefaultIOListener(log);
+ }
+ IOHandler[] ioHandlers = getIOHandlers();
+ for (int i = 0; i < ioHandlers.length && !success; i++) {
+ IOHandler ioh = ioHandlers[i];
+ if (ioh.canExport(context, resource)) {
+ ioListener.onBegin(ioh, context);
+ success = ioh.exportContent(context, resource);
+ ioListener.onEnd(ioh, context, success);
+ }
+ }
+ context.informCompleted(success);
+ }
+ return success;
+ }
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOManagerImpl.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+author date id revision url
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOUtil.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOUtil.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOUtil.java (working copy)
@@ -0,0 +1,200 @@
+/*
+ * 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.apache.jackrabbit.util.Text;
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.apache.jackrabbit.webdav.util.HttpDateFormat;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Date;
+
+/**
+ * IOUtil provides utility methods used for import and export
+ * operations.
+ */
+public final class IOUtil {
+
+ /**
+ * Avoid instantiation
+ */
+ private IOUtil() {}
+
+ /**
+ * Constant for undefined modification/creation time
+ */
+ public static final long UNDEFINED_TIME = DavConstants.UNDEFINED_TIME;
+
+ /**
+ * Constant for undefined content length
+ */
+ public static final long UNDEFINED_LENGTH = -1;
+
+ /**
+ * Return the last modification time as formatted string.
+ *
+ * @return last modification time as string.
+ * @see org.apache.jackrabbit.webdav.util.HttpDateFormat#modificationDateFormat()
+ */
+ public static String getLastModified(long modificationTime) {
+ if (modificationTime <= IOUtil.UNDEFINED_TIME) {
+ modificationTime = new Date().getTime();
+ }
+ return HttpDateFormat.modificationDateFormat().format(new Date(modificationTime));
+ }
+
+ /**
+ * Return the creation time as formatted string.
+ *
+ * @return creation time as string.
+ * @see org.apache.jackrabbit.webdav.util.HttpDateFormat#creationDateFormat()
+ */
+ public static String getCreated(long createdTime) {
+ if (createdTime <= IOUtil.UNDEFINED_TIME) {
+ createdTime = 0;
+ }
+ return HttpDateFormat.creationDateFormat().format(new Date(createdTime));
+ }
+
+ /**
+ */
+ public static void spool(InputStream in, OutputStream out) throws IOException {
+ try {
+ byte[] buffer = new byte[8192];
+ int read;
+ while ((read = in.read(buffer)) >= 0) {
+ out.write(buffer, 0, read);
+ }
+ } finally {
+ in.close();
+ }
+ }
+
+ /**
+ * Build a valid content type string from the given mimeType and encoding:
+ *
+ * <mimeType>; charset="<encoding>"
+ *
+ * If the specified mimeType is null, null is returned.
+ *
+ * @param mimeType
+ * @param encoding
+ * @return contentType or null if the specified mimeType is
+ * null
+ */
+ public static String buildContentType(String mimeType, String encoding) {
+ String contentType = mimeType;
+ if (contentType != null && encoding != null) {
+ contentType += "; charset=" + encoding;
+ }
+ return contentType;
+ }
+
+ /**
+ * Retrieve the mimeType from the specified contentType.
+ *
+ * @param contentType
+ * @return mimeType or null
+ */
+ public static String getMimeType(String contentType) {
+ String mimeType = contentType;
+ if (mimeType == null) {
+ // property will be removed.
+ // Note however, that jcr:mimetype is a mandatory property with the
+ // built-in nt:file nodetype.
+ return mimeType;
+ }
+ // strip any parameters
+ int semi = mimeType.indexOf(';');
+ return (semi > 0) ? mimeType.substring(0, semi) : mimeType;
+ }
+
+ /**
+ * Retrieve the encoding from the specified contentType.
+ *
+ * @param contentType
+ * @return encoding or null if the specified contentType is
+ * null or does not define a charset.
+ */
+ public static String getEncoding(String contentType) {
+ // find the charset parameter
+ int equal;
+ if (contentType == null || (equal = contentType.indexOf("charset=")) == -1) {
+ // jcr:encoding property will be removed
+ return null;
+ }
+ String encoding = contentType.substring(equal + 8);
+ // get rid of any other parameters that might be specified after the charset
+ int semi = encoding.indexOf(';');
+ if (semi != -1) {
+ encoding = encoding.substring(0, semi);
+ }
+ return encoding;
+ }
+
+ /**
+ * Builds a new temp. file from the given input stream.
+ *
+ * It is left to the user to remove the file as soon as it is not used
+ * any more.
+ *
+ * @param inputStream the input stream
+ * @return temp. file or null if the specified input is
+ * null.
+ */
+ public static File getTempFile(InputStream inputStream) throws IOException {
+ if (inputStream == null) {
+ return null;
+ }
+ // we need a tmp file, since the import could fail
+ File tmpFile = File.createTempFile("__importcontext", ".tmp");
+ FileOutputStream out = new FileOutputStream(tmpFile);
+ byte[] buffer = new byte[8192];
+ int read;
+ while ((read=inputStream.read(buffer))>0) {
+ out.write(buffer, 0, read);
+ }
+ out.close();
+ inputStream.close();
+ return tmpFile;
+ }
+
+ /**
+ * Recursively creates nodes below the specified root node.
+ *
+ * @param root
+ * @param relPath
+ * @return the node corresponding to the last segment of the specified
+ * relative path.
+ * @throws RepositoryException
+ */
+ public static Node mkDirs(Node root, String relPath, String dirNodeType) throws RepositoryException {
+ for (String seg : Text.explode(relPath, '/')) {
+ if (!root.hasNode(seg)) {
+ root.addNode(seg, dirNodeType);
+ }
+ root = root.getNode(seg);
+ }
+ return root;
+ }
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOUtil.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+author date id revision url
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ImportContext.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ImportContext.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ImportContext.java (working copy)
@@ -0,0 +1,96 @@
+/*
+ * 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.io.InputStream;
+
+/**
+ * ImportContext...
+ */
+public interface ImportContext extends IOContext {
+
+ /**
+ * Returns the import root of the resource to import, i.e. the parent node
+ * of the new content to be created.
+ *
+ * @return the import root of the resource to import.
+ */
+ public Item getImportRoot();
+
+ /**
+ * Returns the system id of the resource to be imported. This id depends on
+ * the system the resource is coming from. it can be a filename, a
+ * display name of a webdav resource, an URI, etc.
+ *
+ * @return the system id of the resource to import
+ */
+ public String getSystemId();
+
+ /**
+ * Returns the input stream of the data to import or null if
+ * there are none.
+ *
+ * @return the input stream.
+ * @see #hasStream()
+ */
+ public InputStream getInputStream();
+
+ /**
+ * Returns the modification time of the resource or the current time if
+ * the modification time has not been set.
+ *
+ * @return the modification time.
+ */
+ public long getModificationTime();
+
+ /**
+ * Returns the content language or null
+ *
+ * @return contentLanguage
+ */
+ public String getContentLanguage();
+
+ /**
+ * Returns the length of the data or {@link IOUtil#UNDEFINED_LENGTH -1} if
+ * the content length could not be determined.
+ *
+ * @return the content length
+ */
+ public long getContentLength();
+
+ /**
+ * Returns the main media type. It should be retrieved from a content type
+ * (as present in a http request) or from the systemId. If either value
+ * is undefined null should be returned.
+ *
+ * @return the mimetype of the resource to be imported
+ */
+ public String getMimeType();
+
+ /**
+ * Returns the encoding extracted from a content type as present in a
+ * request header or null
+ *
+ * @return the encoding to be used for importing
+ */
+ public String getEncoding();
+
+ /**
+ */
+ public Object getProperty(Object propertyName);
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ImportContext.java
___________________________________________________________________
Added: svn
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ImportContextImpl.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ImportContextImpl.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ImportContextImpl.java (working copy)
@@ -0,0 +1,221 @@
+/*
+ * 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.apache.jackrabbit.webdav.io.InputContext;
+import org.apache.tika.detect.Detector;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.metadata.TikaCoreProperties;
+import org.apache.tika.mime.MediaType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Item;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Date;
+
+/**
+ * ImportContextImpl...
+ */
+public class ImportContextImpl implements ImportContext {
+
+ private static Logger log = LoggerFactory.getLogger(ImportContextImpl.class);
+
+ private final IOListener ioListener;
+ private final Item importRoot;
+ private final String systemId;
+ private final File inputFile;
+
+ private InputContext inputCtx;
+ private boolean completed;
+
+ private final MediaType type;
+
+ /**
+ * Creates a new item import context. The specified InputStream is written
+ * to a temporary file in order to avoid problems with multiple IOHandlers
+ * that try to run the import but fail. The temporary file is deleted as soon
+ * as this context is informed that the import has been completed and it
+ * will not be used any more.
+ *
+ * @param importRoot
+ * @param systemId
+ * @param inputCtx input context, or null
+ * @param stream document input stream, or null
+ * @param ioListener
+ * @param detector content type detector
+ * @throws IOException
+ * @see ImportContext#informCompleted(boolean)
+ */
+ public ImportContextImpl(
+ Item importRoot, String systemId, InputContext inputCtx,
+ InputStream stream, IOListener ioListener, Detector detector)
+ throws IOException {
+ this.importRoot = importRoot;
+ this.systemId = systemId;
+ this.inputCtx = inputCtx;
+ this.ioListener = (ioListener != null) ? ioListener : new DefaultIOListener(log);
+
+ Metadata metadata = new Metadata();
+ if (inputCtx != null && inputCtx.getContentType() != null) {
+ metadata.set(Metadata.CONTENT_TYPE, inputCtx.getContentType());
+ }
+ if (systemId != null) {
+ metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, systemId);
+ }
+ if (stream != null && !stream.markSupported()) {
+ stream = new BufferedInputStream(stream);
+ }
+ this.type = detector.detect(stream, metadata);
+ this.inputFile = IOUtil.getTempFile(stream);
+ }
+
+ /**
+ * @see ImportContext#getIOListener()
+ */
+ public IOListener getIOListener() {
+ return ioListener;
+ }
+
+ /**
+ * @see ImportContext#getImportRoot()
+ */
+ public Item getImportRoot() {
+ return importRoot;
+ }
+
+ /**
+ * @see ImportContext#hasStream()
+ */
+ public boolean hasStream() {
+ return inputFile != null;
+ }
+
+ /**
+ * Returns a new InputStream to the temporary file created
+ * during instantiation or null, if this context does not
+ * provide a stream.
+ *
+ * @see ImportContext#getInputStream()
+ * @see #hasStream()
+ */
+ public InputStream getInputStream() {
+ checkCompleted();
+ InputStream in = null;
+ if (inputFile != null) {
+ try {
+ in = new FileInputStream(inputFile);
+ } catch (IOException e) {
+ // unexpected error... ignore and return null
+ }
+ }
+ return in;
+ }
+
+ /**
+ * @see ImportContext#getSystemId()
+ */
+ public String getSystemId() {
+ return systemId;
+ }
+
+ /**
+ * @see ImportContext#getModificationTime()
+ */
+ public long getModificationTime() {
+ return (inputCtx != null) ? inputCtx.getModificationTime() : new Date().getTime();
+ }
+
+ /**
+ * @see ImportContext#getContentLanguage()
+ */
+ public String getContentLanguage() {
+ return (inputCtx != null) ? inputCtx.getContentLanguage() : null;
+ }
+
+ /**
+ * @see ImportContext#getContentLength()
+ */
+ public long getContentLength() {
+ long length = IOUtil.UNDEFINED_LENGTH;
+ if (inputCtx != null) {
+ length = inputCtx.getContentLength();
+ }
+ if (length < 0 && inputFile != null) {
+ length = inputFile.length();
+ }
+ if (length < 0) {
+ log.debug("Unable to determine content length -> default value = " + IOUtil.UNDEFINED_LENGTH);
+ }
+ return length;
+ }
+
+ /**
+ * @see ImportContext#getMimeType()
+ */
+ public String getMimeType() {
+ return IOUtil.getMimeType(type.toString());
+ }
+
+ /**
+ * @see ImportContext#getEncoding()
+ */
+ public String getEncoding() {
+ return IOUtil.getEncoding(type.toString());
+ }
+
+ /**
+ * @see ImportContext#getProperty(Object)
+ */
+ public Object getProperty(Object propertyName) {
+ return (inputCtx != null) ? inputCtx.getProperty(propertyName.toString()) : null;
+ }
+
+ /**
+ * @see ImportContext#informCompleted(boolean)
+ */
+ public void informCompleted(boolean success) {
+ checkCompleted();
+ completed = true;
+ if (inputFile != null) {
+ inputFile.delete();
+ }
+ }
+
+ /**
+ * @see ImportContext#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("ImportContext has already been consumed.");
+ }
+ }
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ImportContextImpl.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+author date id revision url
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyExportContext.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyExportContext.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyExportContext.java (working copy)
@@ -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;
+
+/**
+ * PropertyExportContext 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
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyExportContext.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+author date id revision url
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyHandler.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyHandler.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyHandler.java (working copy)
@@ -0,0 +1,87 @@
+/*
+ * 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.apache.jackrabbit.webdav.property.PropEntry;
+
+import javax.jcr.RepositoryException;
+import java.util.Map;
+
+/**
+ * PropertyHandler 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 PropertyHandler 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 PropertyHandler#canExport(PropertyExportContext, boolean)}
+ * returns false or if some other unrecoverable error occurs.
+ */
+ 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 PropertyHandler 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 null is equivalent to its removal.
+ *
+ * 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 PropertyHandler#canImport(PropertyImportContext, boolean)}
+ * returns false for the given parameters or if some other unrecoverable
+ * error occurred. Note, that normal failure of a property update must be
+ * reported with the return value and should not result in an exception.
+ */
+ public Map extends PropEntry, ?> importProperties(PropertyImportContext importContext, boolean isCollection) throws RepositoryException;
+
+}
\ No newline at end of file
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyHandler.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+author date id revision url
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyImportContext.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyImportContext.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyImportContext.java (working copy)
@@ -0,0 +1,46 @@
+/*
+ * 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.apache.jackrabbit.webdav.property.PropEntry;
+
+import javax.jcr.Item;
+import java.util.List;
+
+/**
+ * PropertyImportContext...
+ */
+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 extends PropEntry> getChangeList();
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyImportContext.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+author date id revision url
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyManager.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyManager.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyManager.java (working copy)
@@ -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 org.apache.jackrabbit.webdav.property.PropEntry;
+
+import javax.jcr.RepositoryException;
+import java.util.Map;
+
+/**
+ * PropertyManager...
+ */
+public interface PropertyManager {
+
+ /**
+ */
+ public boolean exportProperties(PropertyExportContext exportContext, boolean isCollection) throws RepositoryException;
+
+ /**
+ */
+ public Map extends PropEntry, ?> alterProperties(PropertyImportContext importContext, boolean isCollection) throws RepositoryException;
+
+ /**
+ */
+ public void addPropertyHandler(PropertyHandler propertyHandler);
+
+ /**
+ */
+ public PropertyHandler[] getPropertyHandlers();
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyManager.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+author date id revision url
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyManagerImpl.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyManagerImpl.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyManagerImpl.java (working copy)
@@ -0,0 +1,111 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.webdav.property.PropEntry;
+
+/**
+ * PropertyManagerImpl...
+ */
+public class PropertyManagerImpl implements PropertyManager {
+
+ private static PropertyManager DEFAULT_MANAGER;
+
+ private final List propertyHandlers = new ArrayList();
+
+ /**
+ * Create a new PropertyManagerImpl.
+ * Note, that this manager does not define any PropertyHandlers by
+ * default. Use {@link #addPropertyHandler(PropertyHandler)} in order to populate the
+ * internal list of handlers that are called for importProperties and
+ * exportProperties 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 extends PropEntry, ?> alterProperties(PropertyImportContext context, boolean isCollection) throws RepositoryException {
+ Map extends PropEntry, ?> failures = null;
+ for (PropertyHandler ph : getPropertyHandlers()) {
+ if (ph.canImport(context, isCollection)) {
+ failures = ph.importProperties(context, isCollection);
+ break;
+ }
+ }
+ if (failures == null) {
+ 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 propertyHandlers.toArray(new PropertyHandler[propertyHandlers.size()]);
+ }
+
+ /**
+ * @return an instance of PropertyManager populated with default handlers.
+ */
+ public static PropertyManager getDefaultManager() {
+ if (DEFAULT_MANAGER == null) {
+ PropertyManager manager = new PropertyManagerImpl();
+ manager.addPropertyHandler(new ZipHandler());
+ manager.addPropertyHandler(new XmlHandler());
+ manager.addPropertyHandler(new DefaultHandler());
+ DEFAULT_MANAGER = manager;
+ }
+ return DEFAULT_MANAGER;
+ }
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyManagerImpl.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+author date id revision url
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/VersionHandler.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/VersionHandler.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/VersionHandler.java (working copy)
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. 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 java.io.IOException;
+import java.util.Map;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.version.Version;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.webdav.DavResource;
+import org.apache.jackrabbit.webdav.property.PropEntry;
+
+public class VersionHandler extends DefaultHandler implements IOHandler{
+
+ public VersionHandler() {
+ }
+
+ public VersionHandler(IOManager ioManager) {
+ super(ioManager);
+ }
+
+ //----------------------------------------------------------< IOHandler >---
+ @Override
+ public boolean canImport(ImportContext context, boolean isCollection) {
+ // version node is read only.
+ return false;
+ }
+
+ @Override
+ public boolean canImport(ImportContext context, DavResource resource) {
+ // version node is read only.
+ return false;
+ }
+
+ @Override
+ public boolean importContent(ImportContext context, boolean isCollection) throws IOException {
+ // version node is read only.
+ return false;
+ }
+
+ @Override
+ public boolean importContent(ImportContext context, DavResource resource) throws IOException {
+ // version node is read only.
+ return false;
+ }
+
+ /**
+ * @param context
+ * @param isCollection
+ * @return true if the export root is a Version node. False otherwise.
+ */
+ @Override
+ public boolean canExport(ExportContext context, boolean isCollection) {
+ if (context == null) {
+ return false;
+ }
+ return context.getExportRoot() instanceof Version;
+ }
+
+ /**
+ * @return true if the export root is a Version node. False otherwise.
+ * @see IOHandler#canExport(ExportContext, DavResource)
+ */
+ @Override
+ public boolean canExport(ExportContext context, DavResource resource) {
+ if (context == null) {
+ return false;
+ }
+ return context.getExportRoot() instanceof Version;
+ }
+
+ //----------------------------------------------------< PropertyHandler >---
+ @Override
+ public boolean canImport(PropertyImportContext context, boolean isCollection) {
+ // version is read only
+ return false;
+ }
+
+ @Override
+ public Map extends PropEntry, ?> importProperties(PropertyImportContext importContext, boolean isCollection) throws RepositoryException {
+ // version is read only
+ throw new RepositoryException("Properties cannot be imported");
+ }
+
+ /**
+ * @see PropertyHandler#exportProperties(PropertyExportContext, boolean)
+ */
+ @Override
+ 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);
+ // BUT don't export the special properties defined by nt:version
+ return true;
+ } catch (IOException e) {
+ // should not occur (log output see 'exportProperties')
+ return false;
+ }
+ }
+
+ /**
+ * Retrieves the content node that contains the data to be exported.
+ *
+ * @param context
+ * @param isCollection
+ * @return content node used for the export
+ * @throws javax.jcr.RepositoryException
+ */
+ @Override
+ protected Node getContentNode(ExportContext context, boolean isCollection) throws RepositoryException {
+ Node node = (Node)context.getExportRoot();
+ Node frozenNode = node.getNode(JcrConstants.JCR_FROZENNODE);
+ if (frozenNode.hasNode(JcrConstants.JCR_CONTENT)) {
+ return frozenNode.getNode(JcrConstants.JCR_CONTENT);
+ } else {
+ return frozenNode;
+ }
+ }
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/VersionHandler.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+author date id revision url
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/VersionHistoryHandler.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/VersionHistoryHandler.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/VersionHistoryHandler.java (working copy)
@@ -0,0 +1,133 @@
+/*
+ * 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 java.io.IOException;
+import java.util.Map;
+
+import javax.jcr.Item;
+import javax.jcr.RepositoryException;
+import javax.jcr.version.VersionHistory;
+
+import org.apache.jackrabbit.webdav.DavResource;
+import org.apache.jackrabbit.webdav.property.PropEntry;
+
+/**
+ * VersionHistoryHandler...
+ */
+public class VersionHistoryHandler implements IOHandler, PropertyHandler {
+
+ private IOManager ioManager;
+
+ public VersionHistoryHandler() {
+ }
+
+ public VersionHistoryHandler(IOManager ioManager) {
+ this.ioManager = ioManager;
+ }
+
+ //----------------------------------------------------------< IOHandler >---
+ public IOManager getIOManager() {
+ return ioManager;
+ }
+
+ public void setIOManager(IOManager ioManager) {
+ this.ioManager = ioManager;
+ }
+
+ public String getName() {
+ return getClass().getName();
+ }
+
+ public boolean canImport(ImportContext context, boolean isCollection) {
+ return false;
+ }
+
+ public boolean canImport(ImportContext context, DavResource resource) {
+ return false;
+ }
+
+ public boolean importContent(ImportContext context, boolean isCollection) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean importContent(ImportContext context, DavResource resource) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean canExport(ExportContext context, boolean isCollection) {
+ if (context == null) {
+ return false;
+ }
+ return context.getExportRoot() instanceof VersionHistory;
+ }
+
+ public boolean canExport(ExportContext context, DavResource resource) {
+ if (context == null) {
+ return false;
+ }
+ return context.getExportRoot() instanceof VersionHistory;
+ }
+
+ public boolean exportContent(ExportContext context, boolean isCollection) throws IOException {
+ Item exportRoot = context.getExportRoot();
+ if (exportRoot instanceof VersionHistory) {
+ return export(context);
+ } else {
+ return false;
+ }
+ }
+
+ public boolean exportContent(ExportContext context, DavResource resource) throws IOException {
+ Item exportRoot = context.getExportRoot();
+ if (exportRoot instanceof VersionHistory) {
+ return export(context);
+ } else {
+ return false;
+ }
+ }
+
+ //----------------------------------------------------< PropertyHandler >---
+ public boolean canImport(PropertyImportContext context, boolean isCollection) {
+ return false;
+ }
+
+ public Map extends PropEntry, ?> importProperties(PropertyImportContext importContext, boolean isCollection) throws RepositoryException {
+ throw new UnsupportedOperationException();
+ }
+
+ 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.");
+ }
+ return export(exportContext);
+ }
+
+ //--------------------------------------------------------------------------
+ private boolean export(ExportContext exportContext) {
+ // don't export any properties of the version history node. deltaV
+ // defines a fix set of properties to be exported and the dav-resource
+ // needs to take care of those.
+ exportContext.setContentLength(0);
+ exportContext.setModificationTime(IOUtil.UNDEFINED_TIME);
+ return true;
+ }
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/VersionHistoryHandler.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+author date id revision url
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/XmlHandler.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/XmlHandler.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/XmlHandler.java (working copy)
@@ -0,0 +1,207 @@
+/*
+ * 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 java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.jcr.ImportUUIDBehavior;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.JcrConstants;
+
+/**
+ * XmlHandler imports xml files and exports nodes that have
+ * the proper {@link #XML_MIMETYPE} defined with their content. The export is
+ * performed by running a {@link Session#exportDocumentView(String, OutputStream, boolean, boolean)
+ * document view export} for the content of the export root defined with the
+ * specified {@link ExportContext}.
+ *
+ * Please note that this handler is not suited for a generic system or document
+ * view import/export of {@link Node}s because an extra root node is always
+ * created during import and expected during export, respectively.
+ */
+public class XmlHandler extends DefaultHandler {
+
+ /**
+ * the xml mimetype
+ */
+ public static final String XML_MIMETYPE = "text/xml";
+
+ /**
+ * the alternative xml mimetype. tika detects xml as this.
+ */
+ public static final String XML_MIMETYPE_ALT = "application/xml";
+
+ private static final Set supportedTypes;
+ static {
+ supportedTypes = new HashSet();
+ supportedTypes.add(XML_MIMETYPE);
+ supportedTypes.add(XML_MIMETYPE_ALT);
+ }
+
+
+ /**
+ * Creates a new XmlHandler with default nodetype definitions
+ * and without setting the IOManager.
+ *
+ * @see IOHandler#setIOManager(IOManager)
+ */
+ public XmlHandler() {
+ }
+
+ /**
+ * Creates a new XmlHandler with default nodetype definitions:
+ *
+ *
Nodetype for Collection: {@link JcrConstants#NT_UNSTRUCTURED nt:unstructured}
+ *
Nodetype for Non-Collection: {@link JcrConstants#NT_FILE nt:file}
+ *
Nodetype for Non-Collection content: {@link JcrConstants#NT_UNSTRUCTURED nt:unstructured}
+ *
+ *
+ * @param ioManager
+ */
+ public XmlHandler(IOManager ioManager) {
+ super(ioManager, JcrConstants.NT_UNSTRUCTURED, JcrConstants.NT_FILE, JcrConstants.NT_UNSTRUCTURED);
+ }
+
+ /**
+ * Creates a new XmlHandler
+ *
+ * @param ioManager
+ * @param collectionNodetype
+ * @param defaultNodetype
+ * @param contentNodetype
+ */
+ public XmlHandler(IOManager ioManager, String collectionNodetype, String defaultNodetype, String contentNodetype) {
+ super(ioManager, collectionNodetype, defaultNodetype, contentNodetype);
+ }
+
+ /**
+ * @see IOHandler#canImport(ImportContext, boolean)
+ */
+ @Override
+ public boolean canImport(ImportContext context, boolean isCollection) {
+ return !(context == null || context.isCompleted())
+ && supportedTypes.contains(context.getMimeType())
+ && context.hasStream()
+ && context.getContentLength() > 0
+ && super.canImport(context, isCollection);
+ }
+
+ /**
+ * @see DefaultHandler#importData(ImportContext, boolean, Node)
+ */
+ @Override
+ protected boolean importData(ImportContext context, boolean isCollection, Node contentNode) throws IOException, RepositoryException {
+ InputStream in = context.getInputStream();
+ int uuidBehavior = (isCollection)
+ ? ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING
+ : ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW;
+ try {
+ contentNode.getSession().importXML(contentNode.getPath(), in, uuidBehavior);
+ } finally {
+ in.close();
+ }
+ return true;
+ }
+
+ /**
+ * @see DefaultHandler#importProperties(ImportContext, boolean, Node)
+ */
+ @Override
+ protected boolean importProperties(ImportContext context, boolean isCollection, Node contentNode) {
+ boolean success = super.importProperties(context, isCollection, contentNode);
+ if (success) {
+ // encoding: always UTF-8 for the xml import
+ try {
+ contentNode.setProperty(JcrConstants.JCR_ENCODING, "UTF-8");
+ } catch (RepositoryException e) {
+ // ignore, since given nodetype could not allow encoding
+ // deliberately not re-throwing an IOException.
+ }
+ }
+ return success;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return true, always.
+ */
+ @Override
+ protected boolean forceCompatibleContentNodes() {
+ return true;
+ }
+
+ /**
+ * @see IOHandler#canExport(ExportContext, boolean)
+ */
+ @Override
+ public boolean canExport(ExportContext context, boolean isCollection) {
+ if (super.canExport(context, isCollection)) {
+ String mimeType = null;
+ try {
+ Node contentNode = getContentNode(context, isCollection);
+ if (contentNode.hasProperty(JcrConstants.JCR_MIMETYPE)) {
+ mimeType = contentNode.getProperty(JcrConstants.JCR_MIMETYPE).getString();
+ } else {
+ mimeType = detect(context.getExportRoot().getName());
+ }
+ } catch (RepositoryException e) {
+ // ignore and return false
+ }
+ return XML_MIMETYPE.equals(mimeType);
+ }
+ return false;
+ }
+
+ /**
+ * @see DefaultHandler#exportData(ExportContext, boolean, Node)
+ */
+ @Override
+ protected void exportData(ExportContext context, boolean isCollection, Node contentNode) throws IOException, RepositoryException {
+ // first child of content is XML document root
+ if (contentNode.getNodes().hasNext()) {
+ contentNode = contentNode.getNodes().nextNode();
+ }
+ OutputStream out = context.getOutputStream();
+ contentNode.getSession().exportDocumentView(contentNode.getPath(), out, true, false);
+ }
+
+ /**
+ * @see DefaultHandler#exportProperties(ExportContext, boolean, Node)
+ */
+ @Override
+ protected void exportProperties(ExportContext context, boolean isCollection, Node contentNode) throws IOException {
+ super.exportProperties(context, isCollection, contentNode);
+ // set mimetype if the content node did not provide the
+ // jcr property (thus not handled by super class)
+ try {
+ if (!contentNode.hasProperty(JcrConstants.JCR_MIMETYPE)) {
+ context.setContentType("text/xml", "UTF-8");
+ }
+ } catch (RepositoryException e) {
+ // should never occur
+ throw new IOException(e.getMessage());
+ }
+ }
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/XmlHandler.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+author date id revision url
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ZipHandler.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ZipHandler.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ZipHandler.java (working copy)
@@ -0,0 +1,377 @@
+/*
+ * 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.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.util.Text;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Item;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+
+/**
+ * ZipHandler imports and extracts Zip files and exported nodes
+ * (an their subnodes) to a Zip file. Please not that for the export the selected
+ * export root must have the property {@link #ZIP_MIMETYPE} defined with its
+ * content. Furthermore the content must not represent a zip-file that has
+ * been imported to a binary {@link Property property}, which is properly
+ * handled by the {@link DefaultHandler}.
+ */
+public class ZipHandler extends DefaultHandler {
+
+ private static Logger log = LoggerFactory.getLogger(ZipHandler.class);
+
+ /**
+ * the zip mimetype
+ */
+ public static final String ZIP_MIMETYPE = "application/zip";
+
+ private boolean intermediateSave;
+
+ /**
+ * Creates a new ZipHandler with default nodetype definitions
+ * and without setting the IOManager.
+ *
+ * @see IOHandler#setIOManager(IOManager)
+ */
+ public ZipHandler() {
+ }
+
+ /**
+ * Creates a new ZipHandler with default nodetype definitions:
+ *
+ *
Nodetype for Collection: {@link JcrConstants#NT_UNSTRUCTURED nt:unstructured}
+ *
Nodetype for Non-Collection: {@link JcrConstants#NT_FILE nt:file}
+ *
Nodetype for Non-Collection content: {@link JcrConstants#NT_UNSTRUCTURED nt:unstructured}
+ *
+ *
+ * @param ioManager
+ * @throws IllegalArgumentException if the specified IOManager
+ * is null
+ */
+ public ZipHandler(IOManager ioManager) {
+ this(ioManager, JcrConstants.NT_FOLDER, JcrConstants.NT_FILE, JcrConstants.NT_UNSTRUCTURED);
+ }
+
+ /**
+ * Creates a new ZipHandler
+ *
+ * @param ioManager
+ * @param collectionNodetype
+ * @param defaultNodetype
+ * @param contentNodetype
+ * @throws IllegalArgumentException if the specified IOManager
+ * is null
+ */
+ public ZipHandler(IOManager ioManager, String collectionNodetype, String defaultNodetype, String contentNodetype) {
+ super(ioManager, collectionNodetype, defaultNodetype, contentNodetype);
+ if (ioManager == null) {
+ throw new IllegalArgumentException("The IOManager must not be null.");
+ }
+ }
+
+ /**
+ * If set to true the import root will be {@link Item#save() saved}
+ * after every imported zip entry. Note however, that this removes the possibility
+ * to revert all modifications if the import cannot be completed successfully.
+ * By default the intermediate save is disabled.
+ *
+ * @param intermediateSave
+ */
+ public void setIntermediateSave(boolean intermediateSave) {
+ this.intermediateSave = intermediateSave;
+ }
+
+ /**
+ * @see IOHandler#canImport(ImportContext, boolean)
+ */
+ @Override
+ public boolean canImport(ImportContext context, boolean isCollection) {
+ if (context == null || context.isCompleted()) {
+ return false;
+ }
+ boolean isZip = ZIP_MIMETYPE.equals(context.getMimeType());
+ return isZip && context.hasStream() && super.canImport(context, isCollection);
+ }
+
+ /**
+ * @see DefaultHandler#importData(ImportContext, boolean, Node)
+ */
+ @Override
+ protected boolean importData(ImportContext context, boolean isCollection, Node contentNode) throws IOException, RepositoryException {
+ boolean success = true;
+ InputStream in = context.getInputStream();
+ ZipInputStream zin = new ZipInputStream(in);
+ try {
+ ZipEntry entry;
+ while ((entry=zin.getNextEntry())!=null && success) {
+ success = importZipEntry(zin, entry, context, contentNode);
+ zin.closeEntry();
+ }
+ } finally {
+ zin.close();
+ in.close();
+ }
+ return success;
+ }
+
+ /**
+ * @see IOHandler#canExport(ExportContext, boolean)
+ */
+ @Override
+ public boolean canExport(ExportContext context, boolean isCollection) {
+ if (super.canExport(context, isCollection)) {
+ // mimetype must be application/zip
+ String mimeType = null;
+ // if zip-content has not been extracted -> delegate to some other handler
+ boolean hasDataProperty = false;
+ try {
+ Node contentNode = getContentNode(context, isCollection);
+ // jcr:data property indicates that the zip-file has been imported as binary (not extracted)
+ hasDataProperty = contentNode.hasProperty(JcrConstants.JCR_DATA);
+ if (contentNode.hasProperty(JcrConstants.JCR_MIMETYPE)) {
+ mimeType = contentNode.getProperty(JcrConstants.JCR_MIMETYPE).getString();
+ } else {
+ mimeType = detect(context.getExportRoot().getName());
+ }
+ } catch (RepositoryException e) {
+ // ignore and return false
+ }
+ return ZIP_MIMETYPE.equals(mimeType) && !hasDataProperty;
+ }
+ return false;
+ }
+
+ /**
+ * @see DefaultHandler#exportData(ExportContext,boolean,Node)
+ */
+ @Override
+ protected void exportData(ExportContext context, boolean isCollection, Node contentNode) throws IOException, RepositoryException {
+ ZipOutputStream zout = new ZipOutputStream(context.getOutputStream());
+ zout.setMethod(ZipOutputStream.DEFLATED);
+ try {
+ int pos = contentNode.getPath().length();
+ exportZipEntry(context, zout, contentNode, pos > 1 ? pos+1 : pos);
+ } finally {
+ zout.finish();
+ }
+ }
+
+ /**
+ * If the specified node is the defined non-collection nodetype a new
+ * Zip entry is created and the exportContent is called on the IOManager
+ * defined with this handler. If in contrast the specified node does not
+ * represent a non-collection this method is called recursively for all
+ * child nodes.
+ *
+ * @param context
+ * @param zout
+ * @param node
+ * @param pos
+ * @throws IOException
+ */
+ private void exportZipEntry(ExportContext context, ZipOutputStream zout, Node node, int pos) throws IOException{
+ try {
+ if (node.isNodeType(getNodeType())) {
+ ZipEntryExportContext subctx = new ZipEntryExportContext(node, zout, context, pos);
+ // try if iomanager can treat node as zip entry otherwise recurs.
+ zout.putNextEntry(subctx.entry);
+ getIOManager().exportContent(subctx, false);
+ } else {
+ // recurs
+ NodeIterator niter = node.getNodes();
+ while (niter.hasNext()) {
+ exportZipEntry(context, zout, niter.nextNode(), pos);
+ }
+ }
+ } catch (RepositoryException e) {
+ log.error(e.getMessage());
+ // should never occur
+ }
+ }
+
+ /**
+ * Creates a new sub context for the specified Zip entry and passes it to
+ * the IOManager defined with this handler.
+ *
+ * @param zin
+ * @param entry
+ * @param context
+ * @param node
+ * @return
+ * @throws RepositoryException
+ * @throws IOException
+ */
+ private boolean importZipEntry(ZipInputStream zin, ZipEntry entry, ImportContext context, Node node) throws RepositoryException, IOException {
+ boolean success = false;
+ log.debug("entry: " + entry.getName() + " size: " + entry.getSize());
+ if (entry.isDirectory()) {
+ IOUtil.mkDirs(node, makeValidJCRPath(entry.getName(), false), getCollectionNodeType());
+ success = true;
+ } else {
+ // import zip entry as file
+ BoundedInputStream bin = new BoundedInputStream(zin);
+ bin.setPropagateClose(false);
+ ImportContext entryContext = new ZipEntryImportContext(context, entry, bin, node);
+
+ // let the iomanager deal with the individual entries.
+ IOManager ioManager = getIOManager();
+ success = (ioManager != null) ? ioManager.importContent(entryContext, false) : false;
+
+ // intermediate save in order to avoid problems with large zip files
+ if (intermediateSave) {
+ context.getImportRoot().save();
+ }
+ }
+ return success;
+ }
+
+ /**
+ * Creates a valid jcr label from the given one
+ *
+ * @param label
+ * @return
+ */
+ private static String makeValidJCRPath(String label, boolean appendLeadingSlash) {
+ if (appendLeadingSlash && !label.startsWith("/")) {
+ label = "/" + label;
+ }
+ StringBuffer ret = new StringBuffer(label.length());
+ for (int i=0; i---
+ /**
+ * Inner class used to create subcontexts for the import of the individual
+ * zip file entries.
+ */
+ private class ZipEntryImportContext extends ImportContextImpl {
+
+ private final Item importRoot;
+ private final ZipEntry entry;
+
+ private ZipEntryImportContext(ImportContext context, ZipEntry entry, BoundedInputStream bin, Node contentNode) throws IOException, RepositoryException {
+ super(contentNode, Text.getName(makeValidJCRPath(entry.getName(), true)),
+ null, bin, context.getIOListener(), getIOManager().getDetector());
+ this.entry = entry;
+ String path = makeValidJCRPath(entry.getName(), true);
+ importRoot = IOUtil.mkDirs(contentNode, Text.getRelativeParent(path, 1), getCollectionNodeType());
+ }
+
+ @Override
+ public Item getImportRoot() {
+ return importRoot;
+ }
+
+ @Override
+ public long getModificationTime() {
+ return entry.getTime();
+ }
+
+ @Override
+ public long getContentLength() {
+ return entry.getSize();
+ }
+ }
+
+ /**
+ * Inner class used to create subcontexts for the export of the individual
+ * zip file entries.
+ */
+ private static class ZipEntryExportContext extends AbstractExportContext {
+
+ private ZipEntry entry;
+ private OutputStream out;
+
+ private ZipEntryExportContext(Item exportRoot, OutputStream out, ExportContext context, int pos) {
+ super(exportRoot, out != null, context.getIOListener());
+ this.out = out;
+ try {
+ String entryPath = (exportRoot.getPath().length() > pos) ? exportRoot.getPath().substring(pos) : "";
+ entry = new ZipEntry(entryPath);
+ } catch (RepositoryException e) {
+ // should never occur
+ }
+ }
+
+ /**
+ * Returns the Zip output stream. Note, that this context does not
+ * deal properly with multiple IOHandlers writing to the stream.
+ *
+ * @return
+ */
+ public OutputStream getOutputStream() {
+ return out;
+ }
+
+ public void setContentType(String mimeType, String encoding) {
+ if (entry != null) {
+ entry.setComment(mimeType);
+ }
+ }
+
+ public void setContentLanguage(String contentLanguage) {
+ // ignore
+ }
+
+ public void setContentLength(long contentLength) {
+ if (entry != null) {
+ entry.setSize(contentLength);
+ }
+ }
+
+ public void setCreationTime(long creationTime) {
+ // ignore
+ }
+
+ public void setModificationTime(long modificationTime) {
+ if (entry != null) {
+ entry.setTime(modificationTime);
+ }
+ }
+
+ public void setETag(String etag) {
+ // ignore
+ }
+
+ public void setProperty(Object propertyName, Object propertyValue) {
+ // ignore
+ }
+ }
+}
Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ZipHandler.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+author date id revision url
\ No newline at end of property
Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/jcr/JCRWebdavServer.java
===================================================================
--- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/jcr/JCRWebdavServer.java (nonexistent)
+++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/jcr/JCRWebdavServer.java (working copy)
@@ -0,0 +1,418 @@
+/*
+ * 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.jcr;
+
+import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants;
+import org.apache.jackrabbit.server.SessionProvider;
+import org.apache.jackrabbit.spi.commons.SessionExtensions;
+import org.apache.jackrabbit.util.Text;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavSession;
+import org.apache.jackrabbit.webdav.DavSessionProvider;
+import org.apache.jackrabbit.webdav.WebdavRequest;
+import org.apache.jackrabbit.webdav.header.IfHeader;
+import org.apache.jackrabbit.webdav.jcr.JcrDavException;
+import org.apache.jackrabbit.webdav.jcr.JcrDavSession;
+import org.apache.jackrabbit.webdav.util.LinkHeaderFieldParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.LoginException;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletResponse;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * JCRWebdavServer...
+ */
+public class JCRWebdavServer implements DavSessionProvider {
+
+ /** the default logger */
+ private static Logger log = LoggerFactory.getLogger(JCRWebdavServer.class);
+
+ /** the session cache */
+ private final SessionCache cache;
+
+ /** the jcr repository */
+ private final Repository repository;
+
+ /** the provider for the credentials */
+ private final SessionProvider sessionProvider;
+
+ /**
+ * Creates a new JCRWebdavServer that operates on the given repository.
+ *
+ * @param repository
+ */
+ public JCRWebdavServer(Repository repository, SessionProvider sessionProvider) {
+ this.repository = repository;
+ this.sessionProvider = sessionProvider;
+ cache = new SessionCache();
+ }
+
+ /**
+ * Creates a new JCRWebdavServer that operates on the given repository.
+ *
+ * @param repository
+ * @param concurrencyLevel
+ */
+ public JCRWebdavServer(Repository repository, SessionProvider sessionProvider, int concurrencyLevel) {
+ this.repository = repository;
+ this.sessionProvider = sessionProvider;
+ cache = new SessionCache(concurrencyLevel);
+ }
+
+ //---------------------------------------< DavSessionProvider interface >---
+ /**
+ * Acquires a DavSession either from the session cache or creates a new
+ * one by login to the repository.
+ * Upon success, the WebdavRequest will reference that session.
+ *
+ * @param request
+ * @throws DavException if no session could be obtained.
+ * @see DavSessionProvider#attachSession(org.apache.jackrabbit.webdav.WebdavRequest)
+ */
+ public boolean attachSession(WebdavRequest request)
+ throws DavException {
+ DavSession session = cache.get(request);
+ request.setDavSession(session);
+ return true;
+ }
+
+ /**
+ * Releases the reference from the request to the session. If no further
+ * references to the session exist, the session will be removed from the
+ * cache.
+ *
+ * @param request
+ * @see DavSessionProvider#releaseSession(org.apache.jackrabbit.webdav.WebdavRequest)
+ */
+ public void releaseSession(WebdavRequest request) {
+ DavSession session = request.getDavSession();
+ if (session != null) {
+ session.removeReference(request);
+ }
+ // remove the session from the request
+ request.setDavSession(null);
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ * Private inner class implementing the DavSession interface.
+ */
+ private class DavSessionImpl extends JcrDavSession {
+
+ /**
+ * Private constructor.
+ *
+ * @param session
+ */
+ private DavSessionImpl(Session session) {
+ super(session);
+ }
+
+ /**
+ * Add a reference to this DavSession.
+ *
+ * @see DavSession#addReference(Object)
+ */
+ public void addReference(Object reference) {
+ cache.addReference(this, reference);
+ }
+
+ /**
+ * Removes the reference from this DavSession. If no
+ * more references are present, this DavSession is removed
+ * from the internal cache and the underlying session is released by
+ * calling {@link SessionProvider#releaseSession(javax.jcr.Session)}
+ *
+ * @see DavSession#removeReference(Object)
+ */
+ public void removeReference(Object reference) {
+ cache.removeReference(this, reference);
+ }
+ }
+
+ /**
+ * Private inner class providing a cache for referenced session objects.
+ */
+ private class SessionCache {
+
+ private static final int CONCURRENCY_LEVEL_DEFAULT = 50;
+ private static final int INITIAL_CAPACITY = 50;
+ private static final int INITIAL_CAPACITY_REF_TO_SESSION = 3 * INITIAL_CAPACITY;
+
+ private ConcurrentMap> sessionMap;
+ private ConcurrentMap